diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index 04b9ab7..47f6a8d 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -1,39 +1,26 @@ name: build-docker-image -permissions: - contents: read - id-token: write on: push: branches: [ main ] pull_request: + jobs: + multiarch: + permissions: + contents: read + id-token: write + uses: ./.github/workflows/multiarch-build-workflow.yml + with: + image_name: synapse + google_ar_image_name: us-docker.pkg.dev/sentryio/synapse/image + google_workload_identity_provider: projects/868781662168/locations/global/workloadIdentityPools/prod-github/providers/github-oidc-pool + google_service_account: gha-gcr-push@sac-prod-sa.iam.gserviceaccount.com + push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + + # Gate job — keeps `build-docker` as a single branch-protection check. build-docker: + permissions: {} + needs: [ multiarch ] runs-on: ubuntu-latest steps: - - name: Checkout repository - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - - - name: Docker build - pull request - if: github.event_name == 'pull_request' - uses: getsentry/action-build-and-push-images@8fc75e483c09a68721f2c8951292ee17f8821766 - with: - image_name: synapse - platforms: linux/amd64 - ghcr: false - tag_nightly: false - - - name: Docker build - push to registry - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: getsentry/action-build-and-push-images@8fc75e483c09a68721f2c8951292ee17f8821766 - with: - image_name: synapse - platforms: linux/amd64 - google_ar: true - google_ar_image_name: us-docker.pkg.dev/sentryio/synapse/image - ghcr: false - tag_nightly: false - google_workload_identity_provider: projects/868781662168/locations/global/workloadIdentityPools/prod-github/providers/github-oidc-pool - google_service_account: gha-gcr-push@sac-prod-sa.iam.gserviceaccount.com + - run: 'true' diff --git a/.github/workflows/multiarch-build-workflow.yml b/.github/workflows/multiarch-build-workflow.yml new file mode 100644 index 0000000..3ed07e6 --- /dev/null +++ b/.github/workflows/multiarch-build-workflow.yml @@ -0,0 +1,88 @@ +name: multiarch-build-workflow + +# Reusable workflow: matrix-builds a Dockerfile per-arch on native runners +# via getsentry/action-build-and-push-images, then assembles a multi-arch +# manifest from the per-arch suffixed tags. +on: + workflow_call: + inputs: + image_name: + description: Only feeds GHCR naming in the underlying action; unused here since ghcr is disabled, but still required by the action. + required: true + type: string + google_ar_image_name: + description: Fully-qualified GAR image path (e.g. us-docker.pkg.dev/sentryio/synapse/image). + required: true + type: string + push: + description: Whether to assemble the manifest. + type: boolean + default: false + google_workload_identity_provider: + required: true + type: string + google_service_account: + required: true + type: string + +jobs: + build-arch: + strategy: + fail-fast: false + matrix: + include: + - { platform: linux/amd64, runner: ubuntu-latest, pair: amd64 } + - { platform: linux/arm64, runner: ubuntu-24.04-arm, pair: arm64 } + runs-on: ${{ matrix.runner }} + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 + - uses: getsentry/action-build-and-push-images@8fc75e483c09a68721f2c8951292ee17f8821766 + with: + image_name: ${{ inputs.image_name }} + platforms: ${{ matrix.platform }} + # Each matrix leg stages a single arch as :sha-; + # the assemble job stitches them into the multi-arch :sha and :latest. + # This is the same as Snuba's multiarch workflow. + tag_suffix: -${{ matrix.pair }} + ghcr: false + google_ar: true + google_ar_image_name: ${{ inputs.google_ar_image_name }} + google_workload_identity_provider: ${{ inputs.google_workload_identity_provider }} + google_service_account: ${{ inputs.google_service_account }} + # latest/nightly belong on the assembled manifest, not per-arch. + tag_latest: false + tag_nightly: false + + assemble: + needs: [ build-arch ] + if: inputs.push + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: google-github-actions/auth@ba79af03959ebeac9769e648f473a284504d9193 # v2.1.10 + with: + workload_identity_provider: ${{ inputs.google_workload_identity_provider }} + service_account: ${{ inputs.google_service_account }} + + - env: + IMAGE: ${{ inputs.google_ar_image_name }} + run: gcloud auth configure-docker "$(echo "$IMAGE" | cut -d/ -f1)" + + - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 + + - name: Assemble manifest + env: + IMAGE: ${{ inputs.google_ar_image_name }} + SHA: ${{ github.sha }} + run: | + docker buildx imagetools create \ + -t "${IMAGE}:${SHA}" \ + -t "${IMAGE}:latest" \ + "${IMAGE}:${SHA}-amd64" \ + "${IMAGE}:${SHA}-arm64" + docker buildx imagetools inspect "${IMAGE}:${SHA}" diff --git a/Dockerfile b/Dockerfile index 54dd92f..dedb422 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,12 +18,14 @@ COPY shared ./shared RUN cargo build --release +RUN mkdir /stage && cp --parents /usr/lib/$(gcc -print-multiarch)/libzstd.so.1 /stage + # Runtime stage FROM gcr.io/distroless/cc-debian13:nonroot WORKDIR /app COPY --from=builder /app/target/release/synapse synapse -COPY --from=builder /usr/lib/x86_64-linux-gnu/libzstd.so.1 /usr/lib/x86_64-linux-gnu/libzstd.so.1 +COPY --from=builder /stage/ / ENTRYPOINT ["/app/synapse"] CMD []