Dashboard › publish › Distillation
436ef117-91ee-4507-88cc-0d94dfe047a1["lore_tm_v1_MnAuBp4iSwqLcxV7dv84vyDPXJ0E_rm_ftUpV-_ChiA","lore_tm_v1_igaEgnTt5MscEQnuvHa3VbgbW0IbYkCSP4OLGUNhRvs","lore_tm_v1_eqe5GCEFce4oCGQRlC5AWY5PfaRp6AJSVExN6027hqM","lore_tm_v1_sl6zGB8VfNrSUmKRQyuFaeT-w9RXckbZ-np0qfzdjnQ","lore_tm_v1_5t8Kk3RRUryd-ZtQ6Hgb2u206ycMmow13gzcPixdZQs","lore_tm_v1_VL4Jse_-aelIwZuKYDJ-JPye13_w7riXsFGOGJhFuPs","lore_tm_v1_bi_2PWDtcb-q-eW7l2zsrNTTy1FeFqea-RtZczdkN8Y","lore_tm_v1_0D_b5mIS-l2FpYfmUU-m8sB3RL2xK0IEmUnT31rR6Q8","lore_tm_v1_XUfs4ZniIibGbhyCaH6RFvOS_jKxWdMcDX_fK4nHx0c","lore_tm_v1_hmcWau2VLOtOJtU2uLKsWq6JRQe7FbAdUAZqVlFSZ-8","lore_tm_v1_h0qV62CfguxthO5ng-Y6qp10qB0AWqvkgI5L6ZTm6dk","lore_tm_v1_2-ztuGao--7_eDp7JWjjW1GBzERdWZ26oOKdbyVdnrI","lore_tm_v1_px3le7JGJql9_sz6CUveshv7rhnULGrh_876t9cQFNc","lore_tm_v1_uMjX9Agmqxa52KCVIX0k67G6p2NmFhs2kE17f7XG70o","lore_tm_v1_VSkwYoDV1RM-oB0nIiVV8MAswflrAXkvKMhyMXdGu8U"]
UU) in exactly 6 files: .github/workflows/ci-poller.yml, .github/workflows/publish.yml, src/modules/__tests__/update-issue.js, src/modules/details-from-context.js, src/modules/update-issue.js, and src/publish/inputs.js..github/workflows/auto-approve.yml, .github/workflows/cocoapods-keepalive.yml, .github/workflows/test.yml, AGENTS.md, README.md, docs/key_rotation_vault_changes.md, docs/rfc.md, src/libs/__tests__/github.js, src/libs/github.js, src/modules/__tests__/details-from-context.js, src/modules/post-workflow-details.js, src/modules/process-end-state.js, src/publish/post-result.js, src/publish/post-workflow-details.js, and src/publish/update-issue.js..github/workflows/ci-poller-dispatch.yml, .lore.md, src/modules/__tests__/approval-attestation.js, src/modules/__tests__/approval-authorizer.js, src/modules/approval-attestation.js, src/modules/approval-authorizer.js, src/publish/__tests__/authorize-approval.js, src/publish/__tests__/auto-approval-workflow.js, src/publish/__tests__/ci-poller-workflow.js, src/publish/__tests__/current-accepted-event.js, src/publish/__tests__/publish-workflow.js, src/publish/__tests__/record-auto-approval-attestation.js, src/publish/__tests__/record-ci-ready-attestation.js, src/publish/__tests__/validate-approval-attestation.js, src/publish/__tests__/workflow-action-pinning.js, src/publish/authorize-approval.js, src/publish/current-accepted-event.js, src/publish/record-auto-approval-attestation.js, src/publish/record-ci-ready-attestation.js, and src/publish/validate-approval-attestation.js.src/modules/details-from-context.js, upstream parses titles with generated parsePublishIssueTitle, rejects invalid repository via isPublishRepository(), rejects invalid version via isReleaseVersion(), converts the title suffix to checkout path using "." + titleDetails.path, and rejects it via isPublishPath(). The stashed side retained PUBLISH_TITLE_REGEX and a non-throwing parsePublishTitle() based on title.match(...).src/modules/update-issue.js, upstream updateTargets() accepts stateFilePath, returns before fs.existsSync() when the path is absent, and updateIssue() passes process.env.CRAFT_STATE_FILE_PATH; the stashed implementation instead derived ${process.env.GITHUB_WORKSPACE}/__repo__/.craft-publish-${version}.json from parsed inputs.version.src/modules/update-issue.js performs target restoration and removal of the accepted label together with Promise.all(). Target restoration reads and parses the state file, fetches the issue, rewrites target checkboxes using craftState.published, appends previously undeclared targets, and updates the issue body.src/publish/inputs.js had a conflict over output serialization: upstream calls core.setOutput('result', JSON.stringify(result)), while the stashed side calls core.setOutput("result", result).parsePublishTitle() API, but that wrapper delegates to the generated grammar instead of retaining PUBLISH_TITLE_REGEX; cleanup uses the workflow-provided state-file path and label revocation remains unconditional.src/modules/approval-authorizer.js defines allowed roles as write, maintain, and admin; auto-approvers as getsantry[bot] and sentry-release-bot[bot]; and the auto-approval labeler as sentry-internal-app[bot]. It constructs permission lookups with owner: "getsentry", repository: title.repo, and username: actor.src/modules/approval-authorizer.js currently invokes parsePublishTitle() before permission lookup. Invalid titles return { authorized: false, repository: null }; auto-approvers and sentry-internal-app[bot] are denied manual authorization; other actors are authorized only when getPermission() returns a role in write, maintain, or admin.src/modules/publish-issue-title.peggy accepts publish: followed by optional getsentry/, a repository, optional slash-separated path, @, and a version. It returns { repo, path: path || "", version }; repository/path characters are [A-Za-z0-9_.-], and version characters are [A-Za-z0-9_.+-].src/modules/publish-issue-title.peggy parses release revisions only from the canonical request headerβs View check runs link. CheckRunsRevision accepts lowercase hexadecimal only and requires exactly 40 characters while returning { value, start, end }; CheckRunsLinkCount counts all - [View check runs]( occurrences to reject appended decoys.src/modules/publish-issue-validation.js rejects repository names ".", "..", "__proto__", names beginning with -, and names outside /^[A-Za-z0-9_.-]+$/. isReleaseVersion() requires a three-component semantic version with optional prerelease and build metadata.src/modules/__tests__/details-from-context.js expects qualified title publish: getsentry/sentry-javascript/packages/core@10.0.0 to parse as { repo: "sentry-javascript", path: "/packages/core", version: "10.0.0" }; its legacy unqualified-title expectation currently uses path: undefined, while the generated grammar returns an empty string for a missing suffix.src/modules/__tests__/details-from-context.js covers: 4.2.6+sentry1; default merge target becoming ""; canonical-header merge target winning over a later decoy; concrete suffix /packages/cli becoming checkout path ./packages/cli; rejection of a space before @version; rejection of ../ and ./ path segments; rejection of repository identities -toolkit, ., .., and __proto__; rejection of versions --config and 1.2; rejection of version path syntax 1.2.3/other; and rejection when issue context is absent.src/modules/__tests__/update-issue.js sets CRAFT_STATE_FILE_PATH to .craft-state/craft/publish-state-getsentry-sentry-c232c383e26f-21.3.1.json and verifies that exact path reaches fs.existsSync(). Its unresolved test conflict is between upstream coverage that a missing CRAFT_STATE_FILE_PATH causes no state-file check/read and stashed coverage that missing parsed inputs still removes accepted.src/modules/release-revision.js requires exactly one View check runs link, verifies that the canonical link repository equals the parsed title repository, and rewrites only the parsed revision byte range. Replacement revisions must match lowercase /^[0-9a-f]{40}$/, otherwise it throws Release revision must be a lowercase 40-character SHA.ci-ready; the workflow comment explains that this avoids racing ci-ready with waiting-for-ci on the same event.actions/checkout to full SHA d23441a48e516b6c34aea4fa41551a30e30af803 and actions/setup-node to full SHA 249970729cb0ef3589644e2896645e5dc5ba9c38.