Dashboard › publish › Distillation
45bdc0c0-b16e-476f-8c13-c4511429cce8["lore_tm_v1_9qVgsurZiojkxUtw-P63hbTWUUDk7aR7WSsRhcpXWEw","lore_tm_v1_Zpf5DJwgeyh7pxoDN4BbTFXT7vsGqHwcTTQxOShg9Fo","lore_tm_v1_GzGyhHL9djjPIjy0vNmaQKJjlzYYTBJNH967Sj4sqGQ","lore_tm_v1_lcLSJXwCyGEM7zeO0mT_DxWh6pGAKU8DWC8Y5VugiLw","lore_tm_v1_Rfqj5AQPtxuIekS5tKx-SDwAG33U71d8fwUj2reljZI","lore_tm_v1_tBu_o1bT1uVD2Q0PCEgPZ-ggXh9SPK_WJJrhS7JpqX4"]
Date: Aug 27, 2026
/home/byk/Code/getsentry/publish; instructed not to edit. Required threat-model checks: public workflow must never expose security-as-code; unauthorized actors with publish triage must not approve arbitrary target releases; GitHub API/token failures must fail closed and remove accepted; only getsantry[bot] auto-approvals for exact auto-approve-repos.txt entries may bypass the repository-permission check. Requested examination of parsing, allowlist, token use, GitHub Actions semantics, injection/data exposure, and regressions; findings must include severity and exact file:line, classify every item as PASS/CONCERN/MUST-FIX, and end exactly MERGE or DO-NOT-MERGE./home/byk/Code/getsentry/publish contains .eslintrc.js, .git/, .github/, .gitignore, .lore.md, AGENTS.md, auto-approve-repos.txt, docs/, LICENSE, node_modules/, package.json, README.md, src/, vitest.config.js, and yarn.lock (15 entries).ci-ready..github/workflows/publish.yml, AGENTS.md, src/libs/__tests__/github.js, src/libs/github.js, src/modules/post-workflow-details.js, src/modules/process-end-state.js, src/modules/update-issue.js, src/publish/inputs.js, src/publish/post-result.js, src/publish/post-workflow-details.js, and src/publish/update-issue.js; untracked .lore.md, src/modules/__tests__/approval-authorizer.js, src/modules/approval-authorizer.js, src/publish/__tests__/, and src/publish/authorize-approval.js..github/workflows/publish.yml adds a Get publish code step using actions/checkout@v6 with persist-credentials: false.Get release bot auth token, using actions/create-github-app-token@v3, configured with ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }} and a release-bot private-key secret; the release-token step uses continue-on-error: true. Comment states the release bot sees all target repositories and checks the actorβs current effective target-repository role without exposing RBAC data.node src/publish/authorize-approval.js with APPROVAL_TOKEN: ${{ steps.release-token.outputs.token }}; shown workflow logic removes the accepted label on authorization failure.ci-pending state and include adding ci-pending; another comment states the CI poller fires only on ci-ready label events, not accepted, to avoid racing with waiting-for-ci, and that the poller always adds ci-ready.src/modules/approval-authorizer.js exports authorizeApproval; displayed fragments show it accepts actor, derives repository as getsentry/${title.groups.repository}, uses getPermission, reads a returned role_name, and returns an authorization result including authorized and repository.src/modules/__tests__/approval-authorizer.js cover getsantry[bot], target-repository collaborators, a contractor actor, permission-role cases, and an unauthorized result { authorized: false, repository: null }.src/publish/authorize-approval.js reads APPROVAL_TOKEN, performs a fetch using an Authorization: Bearer release-bot-token header in tests, and has a test named fails closed when GitHub cannot return a permission.src/modules/details-from-context.js:4-5 defines TARGETS_SECTION_PARSER_REGEX as /^(?!### Targets$\s)(?: *- \[[ xX]\] \S+\s*$(?:\r?\n)?)+/m, intended to match the entire Targets section of a publish issue body.src/modules/details-from-context.js:11 defines TARGETS_PARSER_REGEX as /^\s*- \[[ x]\] (\S+)/gim; :17 defines CHECKED_TARGETS_PARSER_REGEX as /^\s*- \[x\] (\S+)/gim.src/modules/details-from-context.js:24-25 parses publish titles using ^publish: (?:getsentry\/)?(?<repo>[^/@]+)(?<path>\/[\w./-]+)?@(?<version>[\w.+-]+)$; :26 dereferences .groups from context.payload.issue.title.match(titleParser).src/modules/details-from-context.js:27-30 sets dry_run to "1" when issue labels contain dry-run, otherwise "", and sets path to "." + (titleMatch.path || "").src/modules/details-from-context.js:32-38 parses merge targets using ^Merge target: (?<merge_target>[\w.\-/]+)$ with multiline mode and defaults merge_target to "".src/modules/details-from-context.js:40-56 matches the issue body with TARGETS_SECTION_PARSER_REGEX; if present, maps checked target IDs from CHECKED_TARGETS_PARSER_REGEX, otherwise leaves targets undefined; returns title fields plus dry_run, merge_target, path, and targets.