Dashboard › publish › Distillation
2319acf5-7bec-46b9-a3c0-79126afcaffa["lore_tm_v1_SuXZ39Oqltu-2PVRyu9ZZg8gBfcy0bU7PPDnHriOedY","lore_tm_v1_KJjbZfEo70bTM2AhchVR8hu7i_a1tH3aw2o7EezVhbc","lore_tm_v1_MQpgJ9V5-q0sL4SEGGx9NDA6xRrMU3NaWQ9t6Xcuym0","lore_tm_v1_QzuhzvGrYef8g6XsXvDJGJA_dq9z1mDq7qELA2eW7HY","lore_tm_v1_ORd-BKla8n3D-mg16k_Y6DkwQyRnQAe3Q8OGU7QS2tY","lore_tm_v1_BoqteWqIMvu6ClkC6DSUtV2Alq0fTDDJy_hvqdMe89g","lore_tm_v1_16W5UzbSkopaoo5TFZyjxE8RxbSSnjDzmBxPPdXGwzA","lore_tm_v1_l_pn_zzYY0zU2n1v2LLveoQTMtHafOprUzGy8IIi0g0"]
src/publish/resolve-ci-poller-input.js reads issueBody from process.env.PUBLISH_ISSUE_BODY_FILE using readFileSync(..., "utf8") when present, otherwise from process.env.PUBLISH_ISSUE_BODY || ""; it writes JSON from getCiPollerInput({ issueBody, labels: JSON.parse(process.env.PUBLISH_ISSUE_LABELS || ""), title: process.env.PUBLISH_TITLE || "", revision: process.env.PUBLISH_REVISION || "" }) directly to stdout.src/modules/__tests__/process-end-state.js tests processEndState for four statuses: failure posts Failed to publish. with run-log and branch-deletion links; cancelled posts Publish workflow cancelled. with the same links; success posts Published successfully: [run#1234](https://github.com/getsentry/sentry/actions/runs/1234) and closes issue 211; undefined status rejects with Unknown status: 'undefined' and performs neither comment nor issue update.process-end-state.js failure and cancellation snapshots link logs to https://github.com/getsentry/sentry/actions/runs/1234?check_suite_focus=true#step:8 and offer deletion of branch/version 21.3.1 at https://github.com/getsentry/sentry/branches/all?query=21.3.1; all comments target owner: "getsentry", repo: "publish", issue_number: "211".src/modules/__tests__/update-issue.js configures CRAFT_STATE_FILE_PATH as .craft-state/craft/publish-state-getsentry-sentry-c232c383e26f-21.3.1.json; when that file exists, updateIssue() fetches issue 211, reads state { published: { lol: true, hey: false, github: true } }, updates target checkboxes to include - [x] github, - [ ] pypi, - [x] lol, and - [ ] hey, and removes the accepted label.src/modules/__tests__/update-issue.js verifies that when the Craft state file does not exist, the issue body is not updated but the accepted label is still removed; when CRAFT_STATE_FILE_PATH is absent, existsSync is not called and no issue body update occurs; updateIssue({ context, octokit }) also removes accepted without parsed publish inputs.transformIssueBody test in src/modules/__tests__/update-issue.js verifies exact target reconciliation: npm[@sentry/node] changes from unchecked to checked, aws-lambda remains checked, github changes from checked to unchecked, and previously undeclared foo is appended checked, while surrounding issue text is preserved.src/modules/__tests__/post-workflow-details.js verifies postWorkflowDetails() creates exactly one comment on getsentry/publish#211 with body Publishing: [run#1234](https://github.com/getsentry/sentry/actions/runs/1234).src/modules/__tests__/ci-poller-workflow.js extracts the shell script between workflow steps Check CI status for ci-pending issues and Check for remaining pending issues from .github/workflows/ci-poller.yml, then runs it under bash -e -o pipefail with mocked node, mktemp, and gh executables.INITIAL_REVISION = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" and UPDATED_REVISION = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; its mocked issue is number 1, title publish: getsentry/toolkit@1.2.3, and its initial resolver output is { repo: "getsentry/toolkit", revision: INITIAL_REVISION, version: "1.2.3" }.src/modules/__tests__/ci-poller-workflow.js verifies the poller exits successfully and does not edit an issue or leave temporary files when the initial resolver exits 1, when rewrite output has no issueBody, when issueBody is empty, when rewrite output is malformed JSON (not JSON), or when rewrite output is a non-object JSON value ([])."canonical issue body\n\n" and verifies the exact bytes reach --body-file; the poller runs issue edit 1 -R getsentry/publish --remove-label ci-pending --remove-label accepted, does not add ci-ready, does not query /status, and leaves no temporary files.src/publish/__tests__/ci-poller-workflow.js verifies .github/workflows/ci-poller.yml checks out trusted code at github.event.repository.default_branch using a 40-character pinned actions/checkout revision before Get auth token.repository_dispatch type ci-poller and a successful workflow_run from Run CI Status Poller only when its head_branch equals the repository default branch; the main workflow excludes workflow_dispatch, while .github/workflows/ci-poller-dispatch.yml includes workflow_dispatch, permissions: {}, and environment: production, and includes neither secrets. nor repository_dispatch:.src/publish/__tests__/ci-poller-workflow.js must occur before Get auth token; valid attempts are decimal strings 0 through 59, while "", "00", "01", "60", "-1", "1x", "$(id)" are rejected. The workflow sets ATTEMPT: ${{ github.event_name == 'repository_dispatch' && steps.dispatch-attempt.outputs.value || '0' }}, increments with attempt=$((10#$ATTEMPT + 1)), and dispatches via gh api --method POST "repos/$GITHUB_REPOSITORY/dispatches" --input -.src/publish/__tests__/ci-poller-workflow.js verifies every poller approval fence is bound to the listed request snapshot: request_digest=$(echo "$publish_input" | jq -r '.requestDigest') is present and EXPECTED_REQUEST_DIGEST="$request_digest" occurs exactly 4 times.src/modules/__tests__/publish-workflow.js verifies .github/workflows/publish.yml resolves the CI-approved release revision before Inform start, then checks out the target repository, resolves the publish location, sets targets, and finally publishes with Craft.ref: ${{ steps.release-revision.outputs.revision }}, contains exactly 2 uses of actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1, runs node .__publish__/src/publish/discover-location.js, sets PUBLISH_REPOSITORY_DIRECTORY: __repo__, and uses docker://getsentry/craft@sha256:9a4a5d5efa44a00c2215078ead39800d4aaa5a97908b94f45a64d7d506d6e14b.CRAFT_PUBLISH_PATH: ${{ fromJSON(steps.location.outputs.result).path }} and CRAFT_PUBLISH_WORKSPACE: ${{ fromJSON(steps.location.outputs.result).workspace || '' }}, then runs craft publish ${{ fromJSON(steps.inputs.outputs.result).version }} --rev ${{ steps.release-revision.outputs.revision }}.src/modules/__tests__/publish-workflow.js verifies publishing only occurs on a fresh ci-ready label event: github.event.label.name == 'ci-ready', issue labels contain both accepted and ci-ready, and contain neither ci-pending nor ci-failed.getsentry/sentry@21.3.1 with path . uses Craftβs legacy state filename matching .craft-state/craft/publish-state-getsentry-sentry-c232c383e26f-21.3.1.json and writes { published: { github: true } }../packages/cli with workspace name packages/cli and confirms getsentry/toolkit@1.2.3 uses state filename matching .craft-state/craft/publish-state-getsentry-toolkit-c232c383e26f-workspace-cGFja2FnZXMvY2xp-1.2.3.json, again containing { published: { github: true } }.4.2.6+sentry1 and 4.2.6+Sentry1 produce different filenames, respectively ending -version-NC4yLjYrc2VudHJ5MQ.json and -version-NC4yLjYrU2VudHJ5MQ.json.