Dashboard › publish › Distillation
6cc1943d-0430-4194-bc52-986889f65c71["lore_tm_v1_nvBrfqHte5qOalQzK53nmTcnUra91NH7tjaNAQe9SHI","lore_tm_v1_Xi6CjFYfiFOofBKa2ENgedc-NFg_EAoyU21p7K49VI8","lore_tm_v1_ZJFHZC9Fpsd5NlZFAdqD06Pmh95aGu-KnibAkMsiiGM","lore_tm_v1_8POgVeVRujQrzix8HM8rKqSnukcXpb7lXGxUZIv6DRs","lore_tm_v1_fLPjUijl2tJ4pHiV0LfAF62trtuuDHF58b0HTQWpEpw","lore_tm_v1_TBB-hiDg8epjg4rTw_dAlVp_4NO6_Hb0Yh7haPc-Q40","lore_tm_v1_HrjSiTQgmnZIfAbiqDqSyqq2-jXqaAytbvSehDux3bk","lore_tm_v1_CcwyKim9uHOJ1kh54SYG9zEhLf__LQSg09KpxUUSVCI","lore_tm_v1_LFVzSzQT0dScCk34ETUWzh-XEpIrOML84bYOFeEiuYM","lore_tm_v1_ZQMD7EpS19PYJHT0RUO6LhoKNEz8yOJ02_HK0MAXZQg","lore_tm_v1_Y--6mzVKONMsq-DU5y1PUm2vEME4_9jsaiyz9QGWNJA","lore_tm_v1_-nhbi99o-PH6pFJ838xYrI_r-sXzku5uyjo6jHZjrQk","lore_tm_v1_QeUUAv2DEl7tdQXMIP9I18HI9EluQpTIS6B1eCGabAo","lore_tm_v1_iCT3V8O11-OIo_wWL-2oIJlNAh3y3nO4l9Hzo3rMfz8"]
src/publish/update-issue.js imports updateIssue from ../modules/update-issue.js, getGitHubToken from ../libs/github, and @actions/github. main() creates Octokit from github.context and getGitHubToken(), attempts to parse process.env.PUBLISH_ARGS as JSON, warns Could not parse publish inputs; skipping target update and leaves inputs undefined on parse failure, then calls updateIssue({ context, octokit, inputs }). Direct execution catches errors, logs them, and sets process.exitCode = 1; the module exports { main } (src/publish/update-issue.js:1-28).src/modules/__tests__/approval-attestation.js verifies currentAcceptedEvent() chooses the latest accepted label event and normalizes GitHub numeric event ID 29503999078 to string "29503999078". Approval attestations must match the trusted comment author, current actor/event ID, request title/digest, and dry-run state; malformed <!-- publish-approval not-base64 -->, stale event IDs, changed titles, changed dry-run state, and comments by an untrusted author are rejected.src/modules/__tests__/approval-attestation.js verifies CI-ready attestations bind the current accepted event and expected CI-ready actor: an attestation for accepted { actor: "contractor", eventId: "200" } and ciReadyActor: "sentry-internal-app[bot]" is accepted when the current CI-ready event has that actor, but rejected if the accepted event changes to ID "201" or the CI-ready event actor changes to "contractor".src/modules/__tests__/approval-authorizer.js defines authorization rules for publish title publish: getsentry/sentry-javascript@10.0.0: direct approval by getsantry[bot] or sentry-release-bot[bot] is rejected without a permission lookup; getsantry[bot] is also rejected when the release is outside autoApprovedRepositories; collaborator roles write, maintain, and admin are authorized, while none, read, triage, Elevated Bot, and undefined are rejected. Permission lookup arguments are { owner: "getsentry", repository: "sentry-javascript", username: "contractor" }.authorizeApproval() treats the unqualified title publish: sentry-javascript/packages/core@10.0.0 as repository getsentry/sentry-javascript. Malformed titles publish: @1.0.0 and publish: getsentry/sentry-javascript return { authorized: false, repository: null } without querying GitHub. Permission lookup failures such as Error("Not Found") propagate (src/modules/__tests__/approval-authorizer.js:71-146).src/publish/__tests__/authorize-approval.js verifies getAutoApprovedRepositories() reads exact release paths, producing new Set(["getsentry/sentry-javascript", "getsentry/objectstore/clients"]) from newline-separated input. The authorization entry point uses APPROVAL_TOKEN, APPROVAL_ACTOR, APPROVAL_ISSUE_NUMBER, APPROVAL_ISSUE_REPOSITORY, APPROVAL_ISSUE_TITLE, and GITHUB_OUTPUT.https://api.github.com/repos/getsentry/sentry-javascript/collaborators/contractor/permission with Authorization: "Bearer release-bot-token" and writes authorized=true plus a <!-- publish-approval … --> attestation to /tmp/github-output. A requester approving their own release writes exactly authorized=false\n (src/publish/__tests__/authorize-approval.js:56-123).publish: getsentry/relay@1.2.3 requires a request proof created by createAutoApprovalAttestation({ autoApprover: "getsantry[bot]", issue }) and posted by github-actions[bot]; it does not query a collaborator endpoint and writes authorization plus an approval attestation. Missing request proof is rejected. Direct approval by automated opener sentry-release-bot[bot] is rejected without any fetch (src/publish/__tests__/authorize-approval.js:125-213).404: main() rejects with Could not retrieve contractor's permission for getsentry/sentry-javascript: GitHub returned 404, writes no output, and does not itself call console.error (src/publish/__tests__/authorize-approval.js:215-235)..github/workflows/auto-approve.yml is tested to run node src/publish/record-auto-approval-attestation.js before --add-label accepted. The “Post automated approval attestation” portion uses GH_TOKEN: ${{ github.token }}, while the later labeling flow uses GH_TOKEN: ${{ steps.token.outputs.token }}, ensuring the proof is posted as github-actions before the internal app labels the issue (src/publish/__tests__/auto-approval-workflow.js:1-27)..github/workflows/ci-poller.yml is tested to check out trusted code at github.event.repository.default_branch using a 40-character pinned actions/checkout revision before “Get auth token”. Manual recovery is split through .github/workflows/ci-poller-dispatch.yml: the main workflow accepts repository_dispatch type [ci-poller] and successful workflow_run events from the repository default branch but contains no workflow_dispatch; the relay contains workflow_dispatch, permissions: {}, and environment: production, and contains neither secrets. nor repository_dispatch: (src/publish/__tests__/ci-poller-workflow.js:10-38).[[ "$ATTEMPT" =~ ^(0|[1-5][0-9])$ ]], limiting accepted text values to 0 through 59. The workflow derives ATTEMPT from steps.dispatch-attempt.outputs.value for repository_dispatch and otherwise uses "0", increments via attempt=$((10#$ATTEMPT + 1)), and redispatches with gh api --method POST "repos/$GITHUB_REPOSITORY/dispatches" --input - (src/publish/__tests__/ci-poller-workflow.js:40-55).getCurrentAcceptedEvent() is tested to return the latest accepted-label event, e.g. { actor: "contractor", eventId: "200" } after events "100" and "200", and to reject an empty/invalid event history with The issue has no current accepted label event (src/publish/__tests__/current-accepted-event.js:1-38)..github/workflows/publish.yml is tested to place “Revalidate approval attestation” after “Set targets” and immediately before “Publish using Craft”, with REQUIRE_CI_READY_ATTESTATION: "true". Craft must be pinned as docker://getsentry/craft@sha256: followed by exactly 64 lowercase hexadecimal characters (src/publish/__tests__/publish-workflow.js:1-22).recordAutoApprovalAttestation() is tested to bind automated requester getsantry[bot] to the live open request publish: getsentry/sentry-javascript@10.0.0; parsing the result yields { autoApprover: "getsantry[bot]", requestDigest: <String>, title }. If the live issue author is instead contractor, it rejects with The automated approval request changed before approval (src/publish/__tests__/record-auto-approval-attestation.js:1-54).recordCiReadyAttestation() is tested to bind current accepted actor contractor, accepted event ID "100", authenticated CI-ready actor sentry-internal-app[bot], request digest, and title publish: getsentry/sentry-javascript@10.0.0. It rejects with The approval changed before CI could be marked ready if the live title changes to publish: getsentry/sentry-python@10.0.0, no accepted event exists, or the current accepted event changes from expected ID "100" to "200" (src/publish/__tests__/record-ci-ready-attestation.js:1-93).src/publish/__tests__/workflow-action-pinning.js enumerates every .github/workflows/*.yml file and requires all actions/* references to use exact 40-character lowercase hexadecimal revisions. It forbids workflow_dispatch: in every workflow except .github/workflows/ci-poller-dispatch.yml.environment: production are: .github/workflows/auto-approve.yml job auto-approve; .github/workflows/ci-poller.yml job check-ci; .github/workflows/cocoapods-keepalive.yml job keepalive; and .github/workflows/publish.yml jobs waiting-for-ci and publish. The sole workflow-dispatch relay, .github/workflows/ci-poller-dispatch.yml, must contain workflow_dispatch:, permissions: {}, and environment: production, and must not contain secrets. (src/publish/__tests__/workflow-action-pinning.js:11-75).src/libs/__tests__/github.js verifies getGitHubToken() throws when GITHUB_TOKEN is absent, with the message beginning No "GITHUB_TOKEN" environment variable found., and returns the exact configured value "Example Token" when present (src/libs/__tests__/github.js:1-19).src/modules/__tests__/details-from-context.js verifies parsing issue publish: getsentry/sentry@21.3.1 with Merge target: custom-branch and checked targets github, npm[@sentry/node], and docker[latest] produces { dry_run: "", merge_target: "custom-branch", path: ".", repo: "sentry", targets: ["github", "npm[@sentry/node]", "docker[latest]"], version: "21.3.1" }. Unchecked pypi, docker[release], and npm[@sentry/opentelemetry] are excluded.+ in versions, preserving 4.2.6+sentry1, and supports qualified and legacy titles: publish: getsentry/sentry-javascript/packages/core@10.0.0 parses to { path: "/packages/core", repo: "sentry-javascript", version: "10.0.0" }, while publish: sentry-javascript@10.0.0 parses with path: undefined (src/modules/__tests__/details-from-context.js:52-84).detailsFromContext() does not extract Merge target: (default); for that case it returns merge_target: "", checked targets ["github", "docker[latest]"], path: ".", repository sentry, and version 21.3.1. Missing issue payload rejects with Issue context is not defined (src/modules/__tests__/details-from-context.js:86-127).