From 6752afd0fce957700d09b9e7a113817f0a98846a Mon Sep 17 00:00:00 2001 From: Saadi Myftija Date: Tue, 5 May 2026 18:00:10 +0200 Subject: [PATCH 1/3] ci: GHCR commit-SHA tag, OCI labels, and build provenance --- .github/workflows/publish-webapp.yml | 17 +++++++++++++++++ docker/Dockerfile | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/.github/workflows/publish-webapp.yml b/.github/workflows/publish-webapp.yml index b4ac9defb6f..d13c06a3a21 100644 --- a/.github/workflows/publish-webapp.yml +++ b/.github/workflows/publish-webapp.yml @@ -4,6 +4,7 @@ permissions: contents: read packages: write id-token: write + attestations: write on: workflow_call: @@ -58,6 +59,12 @@ jobs: image_tags=$image_tags,$ref_without_tag:v4-beta fi + # when pushing the mutable main tag, also push an immutable-by-convention + # full-commit-sha tag so a commit can be resolved to a specific digest + if [[ "${STEPS_GET_TAG_OUTPUTS_TAG}" == "main" ]]; then + image_tags=$image_tags,$ref_without_tag:${GITHUB_SHA} + fi + echo "image_tags=${image_tags}" >> "$GITHUB_OUTPUT" env: STEPS_GET_TAG_OUTPUTS_TAG: ${{ steps.get_tag.outputs.tag }} @@ -74,6 +81,7 @@ jobs: echo "BUILD_GIT_SHA=${GITHUB_SHA}" echo "BUILD_GIT_REF_NAME=${GITHUB_REF_NAME}" echo "BUILD_TIMESTAMP_SECONDS=$(date +%s)" + echo "BUILD_TIMESTAMP_RFC3339=$(date -u +%Y-%m-%dT%H:%M:%SZ)" } >> "$GITHUB_OUTPUT" env: STEPS_GET_TAG_OUTPUTS_TAG: ${{ steps.get_tag.outputs.tag }} @@ -87,6 +95,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: 🐳 Build image and push to GitHub Container Registry + id: build_push uses: depot/build-push-action@5f3b3c2e5a00f0093de47f657aeaefcedff27d18 # v1.17.0 with: file: ./docker/Dockerfile @@ -98,8 +107,16 @@ jobs: BUILD_GIT_SHA=${{ steps.set_build_info.outputs.BUILD_GIT_SHA }} BUILD_GIT_REF_NAME=${{ steps.set_build_info.outputs.BUILD_GIT_REF_NAME }} BUILD_TIMESTAMP_SECONDS=${{ steps.set_build_info.outputs.BUILD_TIMESTAMP_SECONDS }} + BUILD_TIMESTAMP_RFC3339=${{ steps.set_build_info.outputs.BUILD_TIMESTAMP_RFC3339 }} SENTRY_RELEASE=${{ steps.set_build_info.outputs.BUILD_GIT_SHA }} SENTRY_ORG=triggerdev SENTRY_PROJECT=trigger-cloud secrets: | sentry_auth_token=${{ secrets.SENTRY_AUTH_TOKEN }} + + - name: 🪪 Attest build provenance + uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0 + with: + subject-name: ghcr.io/triggerdotdev/trigger.dev + subject-digest: ${{ steps.build_push.outputs.digest }} + push-to-registry: true diff --git a/docker/Dockerfile b/docker/Dockerfile index bd280879419..5906b63e194 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -98,11 +98,17 @@ ARG BUILD_APP_VERSION ARG BUILD_GIT_SHA ARG BUILD_GIT_REF_NAME ARG BUILD_TIMESTAMP_SECONDS +ARG BUILD_TIMESTAMP_RFC3339 ENV BUILD_APP_VERSION=${BUILD_APP_VERSION} \ BUILD_GIT_SHA=${BUILD_GIT_SHA} \ BUILD_GIT_REF_NAME=${BUILD_GIT_REF_NAME} \ BUILD_TIMESTAMP_SECONDS=${BUILD_TIMESTAMP_SECONDS} +LABEL org.opencontainers.image.source="https://github.com/triggerdotdev/trigger.dev" \ + org.opencontainers.image.revision="${BUILD_GIT_SHA}" \ + org.opencontainers.image.version="${BUILD_APP_VERSION}" \ + org.opencontainers.image.created="${BUILD_TIMESTAMP_RFC3339}" + EXPOSE 3000 # Add global pnpm shims and install pnpm during build (root user) From 93eb75cce7dca58e7837d7938de454f5be05cfaa Mon Sep 17 00:00:00 2001 From: Saadi Myftija Date: Tue, 5 May 2026 18:14:10 +0200 Subject: [PATCH 2/3] ci: grant attestations:write on publish-webapp reusable-workflow call Per GitHub Actions reusable-workflow semantics, the GITHUB_TOKEN passed to a called workflow is at most the caller's job-level permissions. Without this, actions/attest-build-provenance fails at runtime even though the called workflow declares the scope. --- .github/workflows/publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0bc873d80d4..a238395c8c0 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -68,6 +68,7 @@ jobs: contents: read packages: write id-token: write + attestations: write uses: ./.github/workflows/publish-webapp.yml secrets: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} From bd152be4f43e926d79e56806c760df4f7165ea12 Mon Sep 17 00:00:00 2001 From: Saadi Myftija Date: Tue, 5 May 2026 18:25:07 +0200 Subject: [PATCH 3/3] ci: don't block releases on attestation step + grant scope on release path - release.yml's publish-docker job now grants attestations:write so the reusable-workflow chain (release.yml -> publish.yml -> publish-webapp.yml) carries the scope all the way to actions/attest-build-provenance. - continue-on-error on the attestation step itself: image is already pushed by the time this runs, so a Sigstore outage or GHCR referrer hiccup shouldn't fail the workflow and block the downstream publish-helm job. Real config errors still surface as a step warning. --- .github/workflows/publish-webapp.yml | 4 ++++ .github/workflows/release.yml | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/publish-webapp.yml b/.github/workflows/publish-webapp.yml index d13c06a3a21..036d65728ed 100644 --- a/.github/workflows/publish-webapp.yml +++ b/.github/workflows/publish-webapp.yml @@ -115,6 +115,10 @@ jobs: sentry_auth_token=${{ secrets.SENTRY_AUTH_TOKEN }} - name: 🪪 Attest build provenance + # Image is already pushed by this point — don't fail releases (and the + # downstream publish-helm job) on a Sigstore/GHCR-referrer hiccup. Real + # config errors still surface as a step warning in the workflow run. + continue-on-error: true uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0 with: subject-name: ghcr.io/triggerdotdev/trigger.dev diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0f0c8cae302..07af45a8a40 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -169,6 +169,7 @@ jobs: contents: read packages: write id-token: write + attestations: write uses: ./.github/workflows/publish.yml secrets: DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}