Dashboard › publish › Distillation
3f79f9bd-d7d1-4130-8ae8-21ff412e3ad3["lore_tm_v1_4XnF0zDbswjfY-Jpr2UCCA9h4Qn5kYdm6BBAdhj454g","lore_tm_v1_xN5GuYjFVsHqvV0f-5Eyxs4kkAFzu6w5bMoNgrugIEM","lore_tm_v1_PfDn3Wh963zNzb74Q4f-2z49GXoaPgww--ZjhmAsiT4","lore_tm_v1_9vSIMbntwKRmmWrYvEDygFT7eMgMVcf8cTUsA5m4Zmg","lore_tm_v1_fkQ5AcP2POKOlQgbc7PmepvIWqLSpQWSNiuNbB2QDug","lore_tm_v1_Je4496HZzVgOSZx3NCIKoHMbzyRSlvaoKush21vuiiM","lore_tm_v1_Vbz27fXx_lCyw3w85ZCN5kSdbxipRMU7U-Vtr_nIzYg","lore_tm_v1_uY8P40zqLUt0DwBGC0Mkhgxj-7JCiyMvCpWlxlm5r2Y","lore_tm_v1_GrJwBIqHQ2A4EvWkb344JXvton_5RHa3ZqRl6bSq1EI"]
Date: Sep 10, 2026
src/commands/publish.ts defines getPublishStateGitHubConfig(githubConfig, stateRepository = process.env.CRAFT_PUBLISH_STATE_GITHUB_REPO): when stateRepository is absent it returns the release githubConfig; when present it overrides the GitHub configuration used for publish-state identity. The override is deliberately limited to state identity because the Publish controller prepopulates a secure state file using the issue’s checkout repository, which can differ from a workspace’s release GitHub configuration.publishToTarget(target, version, revision) logs an === Publishing to target: <target.id> === banner and calls target.publish(version, revision) inside withTracing using trace name craft.target.<target.id>, operation craft.target.publish, and attributes target.id, target.name, version, and revision.git pull <remote>/<mergeTarget> --rebase by attempting git rebase --abort; failure to abort is logged at trace level as "git rebase --abort failed (may be no rebase in progress)", after which the original pull error is rethrown.argv.rev by first attempting getRevisionBranchName(git, rev) and then using the discovered branch name or the raw revision; without argv.rev, it uses release branch <branchPrefix>/<newVersion>. The publication revision is obtained with git.revparse('HEAD')."All publish targets completed successfully — only the post-publish merge failed." and includes a manual branch-deletion command git push ${argv.remote} --delete ${branchName}.getsentry/publish repository was at commit 7c60ddb on main (origin/main, origin/HEAD), titled feat: accept workspace publish requests.getsentry/publish commits, newest first, were: 1. 7c60ddb feat: accept workspace publish requests; 2. 83d210b build(deps): bump js-yaml from 4.3.0 to 4.3.1 (#9174) on branch opencode/tidy-orchid; 3. 5268a23 feat: Add Vercel creds; 4. 92eba3f feat: Add CLOUDFLARE_API_TOKEN (#9122); 5. ada6147 build(deps): bump js-yaml from 4.1.1 to 4.3.0 (#8731); 6. a4f961a fix: Add GITHUB_API_TOKEN for commit-on-git target (#9069); 7. bf10f82 build(deps): bump postcss from 8.5.15 to 8.5.23 (#9017); 8. 837edc0 docs: fix possessive apostrophe placement (#9015); 9. 4da4a25 chore: replace deprecated trimRight() with trimEnd() (#9012); 10. 22fd64d docs: fix typo 'acces' -> 'access' (#9011); 11. 24b9ce3 docs: fix missing article in rfc.md (#9014); 12. c1bded6 docs: fix run-on sentence in README (#9010).trimRight() with trimEnd() in #9012.7c60ddb changed 32 files with exactly 3,257 insertions and 115 deletions.7c60ddb touched: .github/workflows/ci-poller.yml, .github/workflows/cocoapods-keepalive.yml, .github/workflows/publish.yml, README.md, docs/publish-issue-format.md, package.json, scripts/generate-publish-issue-title-parser.js, src/modules/__tests__/ci-poller-input.js, src/modules/__tests__/ci-poller-workflow.js, src/modules/__tests__/details-from-context.js, src/modules/__tests__/generate-publish-issue-title-parser.js, src/modules/__tests__/publish-location.js, src/modules/__tests__/publish-workflow.js, src/modules/__tests__/release-revision.js, src/modules/__tests__/update-issue.js, src/modules/ci-poller-input.js, src/modules/details-from-context.js, src/modules/publish-issue-title.js, src/modules/publish-issue-title.peggy, src/modules/publish-issue-validation.js, src/modules/publish-location.js, src/modules/release-revision.js, src/modules/update-issue.js, src/publish/__tests__/discover-location.js, src/publish/__tests__/resolve-location.js, src/publish/__tests__/resolve-release-revision.js, src/publish/discover-location.js, src/publish/inputs.js, src/publish/resolve-ci-poller-input.js, src/publish/resolve-location.js, src/publish/resolve-release-revision.js, and yarn.lock..github/workflows/publish.yml is triggered by issue labeled events, uses concurrency group ${{ github.event.issue.title }} with cancel-in-progress: false, and grants contents: read, issues: write, and packages: write..github/workflows/publish.yml waiting-for-ci job runs only when the added label is accepted, the issue is open, and its title starts with publish: . It resets labels by removing ci-failed and ci-ready and adding ci-pending; removing ci-ready ensures a later fresh ci-ready labeled event is generated after a retry.waiting-for-ci job obtains a GitHub App token using actions/create-github-app-token@v3 with vars.SENTRY_INTERNAL_APP_ID and secrets.SENTRY_INTERNAL_APP_PRIVATE_KEY, then performs idempotent label edits with gh issue edit.ci-failed, waiting-for-ci comments "Retrying — CI was previously failed. Checking CI status now."; otherwise it comments "Approved. Checking CI status on the release branch. Publishing will start automatically when CI passes.".waiting-for-ci sets repository variable CI_POLLER_HAS_PENDING to "true" using gh variable set.ci-ready after checking CI. Even if ci-ready was previously present, waiting-for-ci removes it first so the poller’s addition emits a fresh labeled event..github/workflows/publish.yml publish job has timeout-minutes: 90, uses the production environment, and sets SENTRY_DSN to the shown Sentry ingest DSN..github/workflows/publish.yml, both repository checkout steps use actions/checkout@v7; the Publish repository is checked out into .__publish__, while the target repository is checked out into __repo__ at ${{ steps.release-revision.outputs.revision }} with fetch-depth: 0.Resolve CI-approved release revision workflow step runs node .__publish__/src/publish/resolve-release-revision.js with PUBLISH_ARGS from steps.inputs.outputs.result and PUBLISH_ISSUE_BODY from github.event.issue.body.Set targets step receives CRAFT_PUBLISH_REPO, location-derived CRAFT_PUBLISH_PATH, CRAFT_PUBLISH_VERSION, location-derived CRAFT_PUBLISH_WORKSPACE defaulting to '', and CRAFT_PUBLISH_TARGETS_JSON. It renders state JSON with jq in the form { "published": { "<target>": true } }.realpath -m "/github/workspace/__repo__/$CRAFT_PUBLISH_PATH" and passes CRAFT_PUBLISH_STATE_GITHUB_REPO as getsentry/${{ fromJSON(steps.inputs.outputs.result).repo }}..github/workflows/publish.yml reports cancellation by running node .__publish__/src/publish/post-result.js cancelled with PUBLISH_ARGS and GITHUB_TOKEN.src/modules/publish-issue-title.peggy defines canonical title syntax "publish: " "getsentry/"? <Repository> <Path>? "@" <Version>, returning { repo, path: path || "", version }. Repository and path-segment characters are [A-Za-z0-9_.-]; version characters are [A-Za-z0-9_.+-].src/modules/publish-issue-title.peggy, a path suffix is syntactic only; the controller resolves the complete suffix as a workspace after checking out the CI-approved revision.src/modules/publish-issue-title.peggy requires the release-revision request header at the beginning of the issue body: Requested by: @..., Merge target: ..., Quick links:, - [View changes](...), then - [View check runs](https://github.com/getsentry/<repo>/commit/<revision>/checks[/]). It accepts LF or CRLF, optional indentation and blank lines, and a 40-character lowercase hexadecimal revision.CheckRunsLinkCount counts literal "- [View check runs](" occurrences across the complete body to defend against appended decoy links. MergeTarget accepts (default) or [A-Za-z0-9_./-]+.scripts/generate-publish-issue-title-parser.js reads src/modules/publish-issue-title.peggy, generates CommonJS source into src/modules/publish-issue-title.js with Peggy start rules PublishIssueTitle, ReleaseRevision, and CheckRunsLinkCount, identifies the grammar source as publish-issue-title.peggy, and formats generated output with Prettier.scripts/generate-publish-issue-title-parser.js extracts content between // BEGIN TITLE GRAMMAR and // END TITLE GRAMMAR and replaces exactly one <!-- BEGIN GENERATED TITLE GRAMMAR --> / <!-- END GENERATED TITLE GRAMMAR --> block in docs/publish-issue-format.md with a fenced peggy block.scripts/generate-publish-issue-title-parser.js --check compares both generated parser and generated documentation with their checked-in versions. Stale parser output throws "The generated publish issue title parser is stale. Run \yarn generate`."; stale documentation throws "The generated publish issue title documentation is stale. Run `yarn generate`."`.src/modules/__tests__/generate-publish-issue-title-parser.js has 3 tests for generateDocumentation(): 1. missing generated-title markers are rejected; 2. duplicate marker pairs are rejected; 3. a malformed marker <!-- BEGIN GENERATED TITLE GRAMMAR -- > is rejected. All throw "Could not find the generated title grammar in the documentation.".src/publish/__tests__/discover-location.js verifies discoverLocation() preserves checkout-path behavior when the root config is absent: input path ./packages/cli, repository directory __repo__, and exists: () => false returns { path: "./packages/cli" }.src/publish/__tests__/discover-location.js verifies exact workspace discovery through Docker: Craft output '["packages/CLI"]' for input ./packages/CLI returns { path: ".", workspace: "packages/CLI" }, and Docker arguments include image getsentry/craft@sha256:9a4a5d5efa44a00c2215078ead39800d4aaa5a97908b94f45a64d7d506d6e14b, command workspace list, and { encoding: "utf8" }.getWorkspaceNames() fails closed when Craft returns either "{}" or only "\n", throwing "Craft workspace discovery returned an invalid workspace list.".src/publish/resolve-location.js parses PUBLISH_ARGS with fallback "{}" and CRAFT_WORKSPACE_NAMES with fallback "[]"; it requires CRAFT_WORKSPACE_NAMES to decode to an array or throws "Craft workspace discovery returned an invalid workspace list.".src/publish/resolve-location.js calls resolvePublishLocation({ path: input.path, workspaceNames }) and writes its JSON-serialized result to GitHub Actions output result through core.setOutput(). The module invokes resolveLocation() immediately.