Dashboard › publish › Distillation
ef22cc0e-f355-4476-a962-4c227c36cbde["lore_tm_v1_vNjVU7cETyWST8csUcE0g-7HhJGh0jaAhJuMCKC-ekk","lore_tm_v1_UkFi7KOFUt5AEfyllkDHZ18DlRaTRcKU_42zLdzBULY","lore_tm_v1_nw33_w65e9Tuo_RGihH9FCtV5YbEdfKl2QjspIBdX0c","lore_tm_v1_M5i3ywbX9vn-fWhqd1ULQTmVA-YrZ2D1ja90ZvfKr4g"]
π΄ (03:25) User directed: Always allow workflow_dispatch for manual recovery.
π΄ (03:25) User directed: Always run trusted code; because workflow_dispatch can target any ref, the CI pollerβs protected manual-recovery path must execute code checked out from a trusted ref rather than arbitrary dispatched-ref code.
π΄ (03:25) User directed: Never move a release to ci-ready after it changes.
π΄ (03:25) User stated a renamed or re-approved issue never reaches ci-ready.
π΄ (03:25) .github/workflows/publish.yml now checks out trusted publish code with actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 and persist-credentials: false before processing acceptance.
π΄ (03:25) .github/workflows/publish.yml pins actions/create-github-app-token to bcd2ba49218906704ab6c1aa796996da409d3eb1, actions/setup-node to 249970729cb0ef3589644e2896645e5dc5ba9c38, and publish-job actions/checkout to 3d3c42e5aac5ba805825da76410c181273ba90b1; target-repository checkout also sets persist-credentials: false.
π΄ (03:25) The acceptance path in .github/workflows/publish.yml binds the event request snapshot with node src/publish/request-digest-from-event.js, obtains a release-bot token with access to owner getsentry, and runs node src/publish/authorize-approval.js using APPROVAL_TOKEN, APPROVAL_ACTOR, APPROVAL_ISSUE_NUMBER, APPROVAL_ISSUE_REPOSITORY, APPROVAL_ISSUE_TITLE, and EXPECTED_REQUEST_DIGEST.
π΄ (03:25) .github/workflows/publish.yml posts the generated approval attestation through gh issue comment only when authorization succeeded and output authorized == 'true', then validates it with src/publish/validate-approval-attestation.js against author github-actions[bot] and the bound request digest.
π΄ (03:25) If acceptance authorization, attestation posting, or attestation validation fails, .github/workflows/publish.yml removes the accepted label, comments Approval is invalid or could not be verified. Re-add the accepted label to retry after resolving the issue., and exits with failure.
π΄ (03:25) The publish job in .github/workflows/publish.yml independently computes the request digest and validates both approval and CI-ready attestations with REQUIRE_CI_READY_ATTESTATION: "true" before continuing; invalid approval removes accepted, posts the standard retry comment, and fails.
π΄ (03:25) .github/workflows/publish.yml performs a second final-approval-validation immediately before publishing with Craft, again requiring the CI-ready attestation; revoked or changed approval removes accepted, posts the standard retry comment, and fails.
π΄ (03:25) .github/workflows/publish.yml replaced gh workflow run ci-poller.yml -R "$GITHUB_REPOSITORY" with a repository dispatch: gh api --method POST "repos/$GITHUB_REPOSITORY/dispatches" -f event_type=ci-poller.
π΄ (03:25) .github/workflows/publish.yml pins the publish container from docker://getsentry/craft:latest to docker://getsentry/craft@sha256:9a4a5d5efa44a00c2215078ead39800d4aaa5a97908b94f45a64d7d506d6e14b.
π΄ (03:25) .github/workflows/ci-poller.yml replaced its direct workflow_dispatch trigger with repository_dispatch type ci-poller and a workflow_run trigger for completed runs of Run CI Status Poller; its issue permission changed from issues: read to issues: write.
π΄ (03:25) The .github/workflows/ci-poller.yml job runs when vars.CI_POLLER_HAS_PENDING == 'true', on repository_dispatch, or after a successful Run CI Status Poller workflow run whose head_branch equals github.event.repository.default_branch; the latter is the protected workflow_dispatch relay for manual recovery.
π΄ (03:25) .github/workflows/ci-poller.yml validates repository-dispatch attempt values as integers from 0 through 59, emitting ::error::repository_dispatch attempt must be an integer from 0 through 59 when invalid; redispatch increments with attempt=$((10#$ATTEMPT + 1)).
π΄ (03:25) CI polling now revalidates the issue/request and approval state while inspecting CI and again before recording CI readiness, binding checks to request_digest, accepted_event_id, and the expected accepted actor/event; changed, renamed, or re-approved issues are rejected rather than labeled ci-ready.
π΄ (03:25) .github/workflows/auto-approve.yml now grants issues: write, runs in the production environment, checks out with actions/checkout@11d5960a326750d5838078e36cf38b85af677262 and persist-credentials: false, and pins actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1.
π΄ (03:25) Before applying automated approval, .github/workflows/auto-approve.yml computes the request digest with src/publish/request-digest-from-event.js, invokes src/publish/record-auto-approval-attestation.js with the issue snapshot and AUTO_APPROVER: ${{ github.actor }}, posts output auto_approval_attestation as an issue comment, and runs the allow-list approval step only if attestation creation succeeded.
π΄ (03:25) .github/workflows/cocoapods-keepalive.yml removed its workflow_dispatch trigger and retains the daily 0 0 * * * schedule.
π΄ (03:25) .github/workflows/test.yml pins actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803, actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 with Node 24, and actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830.
π΄ (03:25) Action-pin search found 12 uses across the security-sensitive workflows: .github/workflows/publish.yml lines 36, 42, 56, 155, 198, 234, and 262; .github/workflows/ci-poller.yml lines 49, 61, 72, and 435; and .github/workflows/auto-approve.yml line 23.