Dashboard › publish › Distillation
0a415dd5-ff40-4979-a8f6-3d33bc260438["lore_tm_v1_4HlQUczTy8D1V8spLa3akcUmeDgB1jMKdbXjWN9HO_E","lore_tm_v1_4oZxkELnT9YRfpe3CJWNV44OLFoxiKzYQwuqF0x5ekI","lore_tm_v1_-RnT7FT0LBiQng6MB3aPjjCbwBw3RqWZT3fDZSeyMwc","lore_tm_v1_eX6mlkarrR2hQp2QwESTtrEiClrZW5CLtbJ-6viVDzk","lore_tm_v1_igoxS3QK0TcXsD-0mgHe6LaVaWxWrpCAP7gU9Q0YXFM"]
Date: Sep 9, 2026
.github/workflows/ci-poller.yml, user-provided current code supports both successful workflow_run events from Run CI Status Poller and manual recovery through workflow_dispatch; the poller job uses the production environment and checks out trusted code rather than an arbitrary dispatched ref..github/workflows/ci-poller.yml, the poll cycle binds processing to the current accepted label event before inspecting CI, then revalidates the accepted event before progressing so a changed, renamed, or re-approved release cannot reach ci-ready..github/workflows/ci-poller-dispatch.yml; protected production environment secrets enforce that an arbitrary dispatched ref cannot add them..github/workflows/ci-poller-dispatch.yml is a 16-line relay workflow named Run CI Status Poller, triggered only by workflow_dispatch, with top-level permissions: {} and one dispatch job on ubuntu-latest in the production environment whose sole step runs ":"..github/workflows/publish.yml, user-provided current code states the poller always adds ci-ready; the publish job runs only when ci-ready is present and does not race the waiting-for-ci job on the same event..github/workflows/publish.yml, the waiting-for-ci flow authorizes the approval actor, validates the approval attestation, uses idempotent label operations, and can remove ci-ready when validation does not succeed..github/workflows/publish.yml, current code uses the pinned Craft container docker://getsentry/craft@sha256:9a4a5d5efa44a00c2215078ead39800d4aaa5a97908b94f45a64d7d506d6e14b; it hashes the container working directory seen by Craftβs Node process and writes a state file before publishing.src/modules/approval-attestation.js defines three encoded HTML-comment formats: <!-- publish-approval β¦ -->, <!-- publish-auto-approval β¦ -->, and <!-- publish-ci-ready β¦ -->; createAttestation() serializes JSON and encodes it with base64url.src/modules/approval-attestation.js, requestDigest({ body, labels, title }) rejects non-string bodies or non-array labels with Invalid publish request, then computes a SHA-256 hex digest over JSON containing exact body, title, and dryRun, where dryRun is true when any label is named dry-run.src/modules/approval-attestation.js, createApprovalAttestation() binds actor, stringified eventId, requestDigest, and title; createAutoApprovalAttestation() binds autoApprover, requestDigest, and title; createCiReadyAttestation() binds the accepted eventβs actor and stringified event ID, ciReadyActor, requestDigest, and title.src/modules/approval-attestation.js, parseAttestation() finds the selected prefix and --> suffix, decodes base64url, parses JSON, and returns null for missing or malformed data; parseApprovalAttestation(), parseAutoApprovalAttestation(), and parseCiReadyAttestation() additionally require every expected field to be a string.src/modules/approval-attestation.js, compareEventIds() strips leading zeroes, normalizes an empty result to "0", rejects non-decimal IDs with Invalid issue event ID, and compares arbitrary-length IDs first by normalized string length and then via localeCompare().src/modules/approval-attestation.js, currentLabeledEvent(events, labelName) filters for matching labeled events with a string-or-number ID and an actor login, selects the greatest event ID using compareEventIds(), and returns { actor, eventId }; it returns null when no valid event exists or comparison fails. currentAcceptedEvent() selects accepted, while currentCiReadyEvent() selects ci-ready.src/modules/approval-attestation.js, hasApprovalAttestation(), hasAutoApprovalAttestation(), and hasCiReadyAttestation() only accept comments authored by the expected attestationAuthor and require exact matches against the current request digest and issue title; approval also binds actor/event ID, auto-approval binds autoApprover, and CI-ready binds accepted actor/event ID plus the CI-ready actor.src/modules/approval-authorizer.js defines allowed manual-approval roles as exactly write, maintain, and admin; AUTO_APPROVAL_LABELER is sentry-internal-app[bot], and AUTO_APPROVERS are getsantry[bot] and sentry-release-bot[bot].src/modules/approval-authorizer.js, isAutoApprovedRepository() requires the actor to be in AUTO_APPROVERS, requires parsePublishTitle(issueTitle) to succeed, and checks the exact allowlist key getsentry/${title.repo}${title.path || ""}.src/modules/approval-authorizer.js, authorizeApproval() returns { authorized: false, repository: null } for an invalid publish title; otherwise it derives getsentry/${title.repo}, categorically rejects actors in AUTO_APPROVERS and AUTO_APPROVAL_LABELER, and calls getPermission({ owner: "getsentry", repository: title.repo, username: actor }) for other actors, authorizing only when role_name is write, maintain, or admin.