Dashboard › publish › Distillation
eb0c7e72-de5d-40ed-9053-acc5d959b380["lore_tm_v1_QgExh0InELDAkw-hT8i7PEpLhQ37cBjmGZQYr1Ewkl8","lore_tm_v1_02SitxA7WRsbPc6wmUzpMmDvCOha70zSJquaGTUbytk","lore_tm_v1_AGu8S5lMxuq2pxBeyGW7JvZ-PHZcZSOAbvSLJVNvntE"]
Date: Sep 8, 2026
ci-ready after checking CI; waiting-for-ci must first remove an existing ci-ready label so this creates a fresh labeled event and guarantees the publish job triggers on the happy path..github/workflows/publish.yml defines Publish, triggered by issues labeled events, with concurrency group ${{ github.event.issue.title }}, cancel-in-progress: false, and permissions contents: read, issues: write, packages: write.Publish job waiting-for-ci runs in production on ubuntu-latest only when the added label is "accepted", the issue is open, and its title starts with "publish: ". It checks out trusted workflow code with actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 and persist-credentials: false before requesting tokens.waiting-for-ci obtains a sentry-internal-app token using SENTRY_INTERNAL_APP_ID/SENTRY_INTERNAL_APP_PRIVATE_KEY, and best-effort all-getsentry release-bot token using SENTRY_RELEASE_BOT_CLIENT_ID/SENTRY_RELEASE_BOT_PRIVATE_KEY with owner: getsentry. It runs node src/publish/authorize-approval.js with APPROVAL_TOKEN set to the release-bot token, APPROVAL_ACTOR: ${{ github.actor }}, and issue number/repository/title inputs.authorized == 'true', waiting-for-ci comments the emitted approval attestation using gh issue comment and ${{ github.token }}. It then runs node src/publish/validate-approval-attestation.js with APPROVAL_TOKEN: ${{ github.token }} and APPROVAL_ATTESTATION_AUTHOR: github-actions[bot].waiting-for-ci removes "accepted", comments Approval is invalid or could not be verified. Re-add the accepted label to retry after resolving the issue., and exits 1.waiting-for-ci resets label state idempotently by removing "ci-failed" and "ci-ready" and adding "ci-pending". It comments either Retrying — CI was previously failed. Checking CI status now. when the event payload had ci-failed, or Approved. Checking CI status on the release branch. Publishing will start automatically when CI passes. otherwise.waiting-for-ci best-effort obtains a dedicated CI_POLLER_APP_CLIENT_ID/CI_POLLER_APP_PRIVATE_KEY token to set repository variable CI_POLLER_HAS_PENDING to "true", then immediately sends repository_dispatch event type ci-poller using the internal-app token because GITHUB_TOKEN-created workflow_dispatch events are suppressed.Publish job publish runs in production on ubuntu-latest with timeout-minutes: 90 only for an open issue where the triggering label is "ci-ready", labels include "accepted" and "ci-ready", and labels exclude "ci-pending" and "ci-failed". It sets SENTRY_DSN to a configured Sentry ingest DSN.publish checks out trusted publish workflow code into .__publish__ with actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 and persist-credentials: false; before installing dependencies or publishing, it validates approval plus CI-ready attestations using node .__publish__/src/publish/validate-approval-attestation.js with REQUIRE_CI_READY_ATTESTATION: "true". Failure removes "accepted", posts the invalid-approval retry comment, and exits 1.publish uses actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 with Node 24, Yarn cache, and .__publish__/yarn.lock; installs with yarn install --cwd ".__publish__"; parses inputs via node .__publish__/src/publish/inputs.js; and informs workflow start with node .__publish__/src/publish/post-workflow-details.js.publish conditionally takes Craft configuration from protected target branches for: sentry-migr8/tmp-merge-target; sentry-javascript/v10, v9, v8, v7, or master; sentry-python/alpha; and sentry-wizard/1.x. It emits target_repo_branch=$MERGE_TARGET.publish creates an all-getsentry release-bot token and checks out getsentry/${{ fromJSON(steps.inputs.outputs.result).repo }} into __repo__ at ${{ steps.target-repo-branch.outputs.target_repo_branch || '' }} with fetch-depth: 0.Set targets creates Craft’s “already published” JSON payload from CRAFT_PUBLISH_TARGETS_JSON and writes it outside untrusted __repo__/ contents under $GITHUB_WORKSPACE/.craft-state/craft/publish-state-${owner_sanitised}-${repo_sanitised}-${cwd_hash}-${version_sanitised}.json. It derives cwd_hash as the first 12 characters of SHA-1 for Craft’s container-visible working directory, and sanitizes owner/repo/version by lowercasing and replacing non-[a-z0-9._-] runs with _.publish revalidates the approval and CI-ready attestations with REQUIRE_CI_READY_ATTESTATION: "true"; failure removes "accepted", posts the invalid-approval retry comment, and exits 1.publish runs pinned container docker://getsentry/craft@sha256:9a4a5d5efa44a00c2215078ead39800d4aaa5a97908b94f45a64d7d506d6e14b, executes craft publish ${{ fromJSON(steps.inputs.outputs.result).version }} from __repo__/${{ fromJSON(steps.inputs.outputs.result).path }}, and sets XDG_STATE_HOME: /github/workspace/.craft-state, CRAFT_MERGE_TARGET, CRAFT_LOG_LEVEL defaulting to 'Info', and CRAFT_DRY_RUN.sentry-release-bot[bot] and separate credentials: ${{ secrets.GITHUB_TOKEN }} for GHCR (DOCKER_GHCR_IO_USERNAME: x-access-token), release-bot token for GITHUB_API_TOKEN and GITHUB_TOKEN, plus configured publishing secrets including CLOUDFLARE_API_TOKEN, COCOAPODS_TRUNK_TOKEN, CRATES_IO_TOKEN, NPM_TOKEN, GEM_HOST_API_KEY, AWS credentials, NUGET_API_TOKEN, GPG_PRIVATE_KEY, GPG_PASSPHRASE, OSSRH_USERNAME/OSSRH_PASSWORD, Pub.dev tokens, and VERCEL_TOKEN.publish runs node .__publish__/src/publish/update-issue.js to update completed targets/remove the label; on cancellation it posts post-result.js cancelled, on failure post-result.js failure, and on success post-result.js success.src/publish/__tests__/ contains 9 test files: authorize-approval.js, auto-approval-workflow.js, ci-poller-workflow.js, current-accepted-event.js, publish-workflow.js, record-auto-approval-attestation.js, record-ci-ready-attestation.js, validate-approval-attestation.js, and workflow-action-pinning.js.src/publish/__tests__/ci-poller-workflow.js reads .github/workflows/ci-poller.yml and .github/workflows/ci-poller-dispatch.yml and contains 3 Vitest tests: (1) verifies a 40-hex-SHA-pinned Get publish code checkout with ref: ${{ github.event.repository.default_branch }} occurs before Get auth token; (2) verifies the no-secret manual-recovery relay uses workflow_dispatch, while the main poller uses workflow_run for Run CI Status Poller and repository_dispatch type ci-poller, and verifies neither main poller nor relay has an inappropriate dispatch/secret configuration; (3) verifies dispatch attempts are validated before app-token creation with [[ "$ATTEMPT" =~ ^(0|[1-5][0-9])$ ]], incremented using attempt=$((10#$ATTEMPT + 1)), and self-dispatched using gh api --method POST "repos/$GITHUB_REPOSITORY/dispatches" --input -.