Dashboard › publish › Distillation
bd7101f7-a745-4fd5-8ac6-90aaae3421c7["lore_tm_v1_NUTsUTULvq0__EX275T5jXrNCfYugIUUepBAnZdR208","lore_tm_v1_s16WKCB1cYtgDxLC9hT5MTGJJ7o9tWHOR-SMV7lzhh4","lore_tm_v1_s2kLBrO7Q6uj2zwkw9dH_JgCBXBZ2b-2WrzKPoWRlq8","lore_tm_v1_9RKuPj4RbQ1a7NHqJ8J7BOJGIW7tRDrOth-OehcOig8"]
ci-ready label, revalidate the exact approved release snapshot, and always add ci-ready again so a fresh label event triggers publishing; the add must never be treated as an idempotent optimization.ci-readyβif the issue is renamed, its release details change, or it is re-approved with a different accepted event.ci-ready removal, final revalidation, and per-issue termination, including mutation checks proving tests fail when any of those protections is removed.workflow_dispatch wherever operators need manual recovery.main-only environment and a successful default-branch workflow_run handoff rather than direct secret-bearing dispatch, because dispatchers select workflow YAML before jobs, guards, or checkout execute.ci-poller.yml, rather than placeholders or numeric IDs.github-actions[bot] proof before sentry-internal-app[bot] adds accepted; generic app identity is insufficient.ci-ready, and immediately before Craft. Repeated live fencing was chosen over initial-only validation because issue state can change during CI or setup.accepted, moving an issue to ci-ready, or publishing, validate the live canonical issue, current label events, actor provenance, and matching attestations; reject renamed, closed, changed, re-approved, self-approved, or unverifiable requests.ci-ready.dry-run state and rejecting requests whose live state no longer matches.production environment, no secrets for dispatched refs, and immutable digests for actions and containers.authorizeApproval() to fail closed when either getsantry[bot] or sentry-release-bot[bot] directly adds accepted, even if both appear in generic AUTO_APPROVERS; only sentry-internal-app[bot] may represent automated approval, backed by matching github-actions[bot] attestation.src/modules/__tests__/approval-authorizer.js tests both direct-bot paths with test.each(["getsantry[bot]", "sentry-release-bot[bot]"]); each must return { authorized: false, repository: "getsentry/sentry-javascript" } without calling getPermission.src/modules/__tests__/approval-authorizer.js also verifies: 1. getsantry[bot] is rejected when getsentry/sentry-javascript is outside autoApprovedRepositories; 2. write, maintain, and admin collaborators are authorized; 3. none, read, triage, "Elevated Bot", and undefined roles are rejected; 4. unqualified publish: sentry-javascript/packages/core@10.0.0 resolves to getsentry/sentry-javascript; 5. malformed titles return { authorized: false, repository: null } without a GitHub query; 6. permission lookup error "Not Found" propagates.src/modules/__tests__/approval-attestation.js verifies currentAcceptedEvent() chooses the latest accepted event and returns { actor: "contractor", eventId: "200" }; numeric GitHub event ID 29503999078 is normalized to string "29503999078".src/modules/__tests__/approval-attestation.js verifies approval attestations authored by github-actions[bot] are matched to the exact issue and current accepted event, while malformed, stale, wrong-author, changed-event, and changed-request attestations are rejected; parseApprovalAttestation("<!-- publish-approval not-base64 -->") returns null.src/modules/__tests__/approval-attestation.js verifies CI-ready attestations bind accepted event { actor: "contractor", eventId: "200" }, CI-ready actor sentry-internal-app[bot], and issue snapshot; changing the accepted event to ID "201" or the CI-ready actor to contractor causes rejection.src/modules/__tests__/approval-attestation.js verifies changing a request from non-dry-run to dry-run changes requestDigest() and causes hasApprovalAttestation() to reject the previously created attestation.src/modules/__tests__/ci-poller-input.js defines REVISION = "7e5ca7ed5581552de066e2a8bc295b8306be38ac" and verifies getCiPollerInput() parses both publish: getsentry/toolkit/cli@1.2.3 and publish: toolkit/packages/cli/v2@1.2.3 into repo: "getsentry/toolkit", revision: REVISION, version: "1.2.3", and a snapshot-derived requestDigest.src/modules/__tests__/ci-poller-input.js verifies .github/workflows/ci-poller.yml checks out publish code under .__publish__, contains name: Get publish code, invokes node .__publish__/src/publish/resolve-ci-poller-input.js, and no longer parses the revision with grep -oP '(?<=commit/.src/modules/__tests__/ci-poller-input.js rejects unsafe repositories -toolkit, ., .., and __proto__ with Invalid publish issue repository; invalid versions --config and 1.2 with Invalid publish issue version; malformed identities publish: getsentry/@1.2.3 and publish: getsentry/toolkit$@1.2.3 with Invalid publish issue title; and unsafe paths containing ../other, ./other, __proto__/other, or --config with Invalid publish issue path.