diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index fbf3cc0..277c8ea 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -34,6 +34,20 @@ on: description: "JSON matrix of services to build (GitHub Actions matrix `include` shape)" required: true type: string + private-modules: + description: >- + Mint a short-lived, read-only token for the org-wide pinpredict-argocd + App (BOOTSTRAP_APP_ID / BOOTSTRAP_APP_PRIVATE_KEY) and expose it to the + build as BuildKit secret `id=gh_token`. Opt-in for services whose + Dockerfile fetches a private pinpredict module instead of vendoring it + (e.g. a Go repo that requires github.com/pinpredict/ppkit) via + `RUN --mount=type=secret,id=gh_token ... go mod download`. Handed to + buildx as a `--secret`, never a `--build-arg`, so it never lands in an + image layer or `docker history`. Default false — a no-op for every + existing caller. + required: false + type: boolean + default: false env: AWS_REGION: us-east-1 @@ -115,6 +129,23 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 + # Opt-in (private-modules: true): mint a short-lived, read-only token for + # the org-wide pinpredict-argocd App so the build can fetch private + # pinpredict modules without vendoring. contents:read across the org (the + # App is installed on all repos); consumed by buildx as a BuildKit + # `--secret` below — never a build-arg — so it never lands in an image + # layer or `docker history`. Skipped (and the secret omitted) for every + # caller that leaves private-modules at its default false. + - name: Mint private-module read token + id: private-module-token + if: ${{ inputs.private-modules }} + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ secrets.BOOTSTRAP_APP_ID }} + private-key: ${{ secrets.BOOTSTRAP_APP_PRIVATE_KEY }} + owner: pinpredict + permission-contents: read + - name: Resolve version, build, push, tag id: release env: @@ -126,6 +157,9 @@ jobs: ECR_REGISTRY: ${{ steps.ecr-login.outputs.registry }} SHORT_SHA: ${{ github.sha }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Empty unless private-modules minted a token above; gates the + # BuildKit --secret so it's a no-op for every other caller. + GH_PRIVATE_TOKEN: ${{ steps.private-module-token.outputs.token }} run: | set -euo pipefail SHORT_SHA="${SHORT_SHA:0:7}" @@ -196,6 +230,15 @@ jobs: done <<< "${BUILD_ARGS}" fi + # Private-module fetch (inputs.private-modules): hand the minted App + # token to the build as a BuildKit secret, readable inside the + # Dockerfile at /run/secrets/gh_token via + # `RUN --mount=type=secret,id=gh_token`. Only added when the token + # step ran (env non-empty) — a no-op for every other caller. + if [ -n "${GH_PRIVATE_TOKEN:-}" ]; then + buildx_args+=(--secret "id=gh_token,env=GH_PRIVATE_TOKEN") + fi + docker buildx build "${buildx_args[@]}" . # Tag immediately after successful push (retry up to 3 times). diff --git a/README.md b/README.md index d2e83cf..5c42af4 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Why `.github` and not a dedicated `github-actions` repo: `.github` is *the* GitH | File | Purpose | |---|---| -| `docker-release.yml` | Matrix-based image build + push to ECR. Version = highest `X.Y.Z` tag in the ECR repo + 1 (ECR is the version record — platform-gitops#1201); advances the `refs/releases/image/` marker ref, mints the legacy `image//X.Y.Z` git tag (Dispatch correlation, being phased out), aggregated GitHub Release. Caller passes a `matrix` input in the standard `{include:[...]}` shape. | +| `docker-release.yml` | Matrix-based image build + push to ECR. Version = highest `X.Y.Z` tag in the ECR repo + 1 (ECR is the version record — platform-gitops#1201); advances the `refs/releases/image/` marker ref, mints the legacy `image//X.Y.Z` git tag (Dispatch correlation, being phased out), aggregated GitHub Release. Caller passes a `matrix` input in the standard `{include:[...]}` shape. Optional `private-modules: true` mints a short-lived read-only `pinpredict-argocd` App token and exposes it to the build as BuildKit secret `id=gh_token` (`RUN --mount=type=secret,id=gh_token …`) — for Dockerfiles that fetch a private pinpredict module (e.g. `github.com/pinpredict/ppkit`) instead of vendoring it. Default false. | | `chart-release.yml` | Auto-discovers `charts/*/`, skips charts unchanged since their `refs/releases/chart/` marker ref, resolves the next version from the ECR OCI repo, packages, pushes, advances the marker, mints the legacy `chart//X.Y.Z` tag. No caller inputs. | | `tag-config.yml` | Tags merges to main that touch `.platform/services/.yaml` with `vX.Y.Z+` (per-service Kargo `-config` Warehouse freight), then dispatches `service-config-tag` to platform-gitops so missing pointer files get seeded. | | `actionlint.yml` | Lints GitHub Actions workflow YAML with [`actionlint`](https://github.com/rhysd/actionlint) at a pinned version. Self-runs on this repo when PRs/pushes touch `.github/workflows/**` or `actions/**/action.yml`; callers reuse it via `uses: pinpredict/.github/.github/workflows/actionlint.yml@main`. |