Dashboard › publish › Distillation
e9412ba2-1152-40c0-a993-7ccdea3bc9cd["lore_tm_v1_HW6yMnpsMvaA-jgJOmbq82X0SZqZ6MJ7I2X7br6Mh7g","lore_tm_v1_bDVVjGmXHpB1CxgM3PEqOTPCr_SIM6dDXtPxKM_286g","lore_tm_v1_E9T7WZZIhgpr6cZw7BIOkh7fvxjXoQ0TfEyDwsKF8QA","lore_tm_v1_oltCNAT9w8ggx-9a2r1i62NF3dYB22bRYP8kLhDVhGw","lore_tm_v1_kjPplw9LRHZt2h6Cu2HxLAX6YyM5iRipuRmMib_E0rQ","lore_tm_v1__omzSEkn0lvIcuwXRXfjAjL2pnzo8uvIhHkFa0Z-JFg","lore_tm_v1_F1O5bFr2RTVvKP2J3behdi28GcCj84Jzync_7u40UFw","lore_tm_v1_PSu6nx6n5IffmJqp83T5GdpmGZoSKhh6sMl7ZgxXtSs","lore_tm_v1_vCq4ITrs1_TWqyRiwVHVBEWaZcBuNa8YrJh11qVeaf8","lore_tm_v1_LvxoZVtAlrIdoec3D73wYux6KB5aadUtFvnsbT98gjA","lore_tm_v1_yiIlIbK3db9-8khsoWskQxAOrQuTKkcb6hmbzEEEEa4","lore_tm_v1_6Bzd572gU9r7DdvM52zJgPYTtvr3GS2qN2Sz3WkD9lo"]
2026-09-10
workflow_dispatch to check out and run trusted code from ${{ github.event.repository.default_branch }}, rather than code from an arbitrary dispatch ref; workflow comment at line 51 states: “workflow_dispatch can target any ref. Always run trusted code.”ci-ready after its issue/release input changes; workflow comment at line 139 states: “Never move a release to ci-ready after it changes.”ci-ready; workflow comment at line 284 identifies this failure mode.Run CI Status Poller; execution is gated on github.event.workflow_run.head_branch == github.event.repository.default_branch; ATTEMPT defaults to '0'; the poller queries issues carrying both ci-pending and accepted; and output reports Found ${count} ci-pending + accepted issue(s).printf '%s' "$issue" | jq -jr '.body' > "$body_file" and the resolved revision is read as issue_sha=$(echo "$publish_input" | jq -r '.revision').Approval is invalid or could not be verified. Re-add the accepted label to retry after resolving the issue.gh_api_release --paginate "repos/${repo}/commits/${sha}/check-runs" --jq '.check_runs[]'; unsuccessful checks are counted with jq -s '[.[] | select(.status == "completed" and .conclusion != "success" and .conclusion != "neutral" and .conclusion != "skipped")] | length'.ci-pending to ci-failed and removes accepted; comments explain only issues with both ci-pending and accepted are polled.CI_POLLER_APP_PRIVATE_KEY, a poller-variable reconciliation step (“Update the poller variable to match reality”), and manual triggering through either re-adding accepted or a workflow_dispatch relay.src/modules/publish-issue-title.js found 12 relevant generated-parser references, including start rules ReleaseRevision and CheckRunsLinkCount, parser functions peg$parseReleaseRevision(), peg$parseCheckRunsRevision(), peg$parseCheckRunsLinkCount(), and peg$parseCheckRunsLink(), plus StartRules: ["PublishIssueTitle", "ReleaseRevision", "CheckRunsLinkCount"].src/modules/publish-issue-title.js:305-320: peg$f7(mergeTarget, repo, revision) returns { repo, mergeTarget, revision }; peg$f8(value) requires value.length === 40; peg$f9(value) records { value, start: range.start.offset, end: range.end.offset }; and peg$f11(entries) counts truthy entries with entries.filter(Boolean).length.src/modules/publish-issue-title.js:197-227: parser start rules are PublishIssueTitle, ReleaseRevision, and CheckRunsLinkCount; constants enforce publish: , getsentry/, Requested by: @, Merge target: , Quick links:, - [View changes](, and canonical check-runs links beginning - [View check runs](https://github.com/getsentry/ and ending /checks.src/modules/publish-issue-title.js:221-227: repository characters are [A-Za-z0-9_.-], release-version characters are [A-Za-z0-9_.+-], revision characters are lowercase [0-9a-f], merge-target characters are [A-Za-z0-9_./-], and generic link destinations exclude CR, LF, and ).scripts/generate-publish-issue-title-parser.js, grammar src/modules/publish-issue-title.peggy, generated parser src/modules/publish-issue-title.js, and generator test src/modules/__tests__/generate-publish-issue-title-parser.js.src/publish/inputs.js:1-10: inputs() calls detailsFromContext({ context: github.context }) and emits the serialized result through core.setOutput("result", JSON.stringify(result)); the function executes immediately.src/publish/resolve-release-revision.js:4-16: resolveReleaseRevision() parses process.env.PUBLISH_ARGS || "{}", requires repo, and sets output revision from getReleaseRevision({ issueBody: process.env.PUBLISH_ISSUE_BODY || "", repo }); a missing repository throws Publish input must define a repository.src/publish/discover-location.js:9-10: Craft workspace discovery pins image getsentry/craft@sha256:9a4a5d5efa44a00c2215078ead39800d4aaa5a97908b94f45a64d7d506d6e14b.src/publish/discover-location.js:12-49: getWorkspaceNames() returns [] when <repositoryDirectory>/.craft.yml does not exist; otherwise it synchronously runs docker run --rm --volume <resolved repositoryDirectory>:/github/workspace/__repo__ --workdir /github/workspace/__repo__ <pinned CRAFT_IMAGE> workspace list with UTF-8 output, parses JSON, and throws Craft workspace discovery returned an invalid workspace list. if parsing fails or the result is not an array.src/publish/discover-location.js:52-85: discoverLocation() passes input.path and discovered workspace names to resolvePublishLocation(); main() parses PUBLISH_ARGS, requires input.path, defaults PUBLISH_REPOSITORY_DIRECTORY to __repo__, emits JSON output result, runs only under require.main === module, and exports { discoverLocation, getWorkspaceNames }.src/publish/resolve-ci-poller-input.js:4-17: issue-body identity comes from PUBLISH_ISSUE_BODY_FILE via readFileSync(..., "utf8") when set, otherwise from PUBLISH_ISSUE_BODY || ""; the script writes JSON from getCiPollerInput() using labels parsed from PUBLISH_ISSUE_LABELS || "", title from PUBLISH_TITLE || "", and revision from PUBLISH_REVISION || "".src/publish/update-issue.js:5-18: main() obtains github.context and an Octokit client from getGitHubToken(); it conditionally parses PUBLISH_ARGS, warns Could not parse publish inputs; skipping target update on parse failure, then calls updateIssue({ context, octokit, inputs }).src/publish/update-issue.js:21-28: direct execution catches errors, prints them, and sets process.exitCode = 1; the module exports { main }.src/modules/update-issue.js:7-38: updateTargets() silently returns when stateFilePath is absent or does not exist; otherwise it concurrently fetches the issue and reads/parses the UTF-8 Craft state file, transforms issue.body, and updates the issue body.src/modules/update-issue.js:40-63: transformIssueBody(craftState, issueBody) replaces the section matched by TARGETS_SECTION_PARSER_REGEX; each declared target becomes - [x] <targetId> when craftState.published[targetId] is truthy or - [ ] <targetId> otherwise; keys in craftState.published not already declared are appended in Object.keys() order with equivalent checked state.src/modules/update-issue.js:65-82: updateIssue({ context, octokit }) derives the publish repository from context.repo and issue number from context.payload.issue.number, then concurrently calls updateTargets() with process.env.CRAFT_STATE_FILE_PATH and removes the accepted label.src/publish/update-issue.js parses and passes inputs, but src/modules/update-issue.js:65 destructures only { context, octokit }; target-state lookup is therefore controlled solely by CRAFT_STATE_FILE_PATH, not by the parsed PUBLISH_ARGS.