Dashboard › publish › Distillation
2abe52cb-6d20-425e-9e42-96a465381c06["lore_tm_v1_vQOkT6jaS50iFGD041751-gLwhXMew1p9019OYPJWok","lore_tm_v1_N_47Ans1Vhv_OnW9i8AsAnG8RqYu462IzxMnfwJy9jE"]
π΄ (12:56) /home/byk/Code/getsentry/publish/src/publish/authorize-approval.js is 241 lines. It imports createApprovalAttestation, currentAcceptedEvent, and hasAutoApprovalAttestation from ../modules/approval-attestation.js, plus AUTO_APPROVAL_LABELER, AUTO_APPROVERS, authorizeApproval, and isAutoApprovedRepository from ../modules/approval-authorizer.js.
π΄ (12:56) getAutoApprovedRepositories() in src/publish/authorize-approval.js synchronously reads auto-approve-repos.txt as UTF-8, splits on /\r?\n/, removes empty lines, and returns the entries as a Set.
π΄ (12:56) getGitHubResponse(path) calls https://api.github.com/${path} with headers Accept: application/vnd.github+json, Authorization: Bearer ${process.env.APPROVAL_TOKEN}, and X-GitHub-Api-Version: 2026-03-10.
π΄ (12:56) getPermission({ owner, repository, username }) requests repos/${encodeURIComponent(owner)}/${encodeURIComponent(repository)}/collaborators/${encodeURIComponent(username)}/permission; a non-OK response throws Could not retrieve ${username}'s permission for ${owner}/${repository}: GitHub returned ${response.status}.
π΄ (12:56) getIssue({ repository, issueNumber }) requests repos/${repository}/issues/${issueNumber} and throws Could not retrieve issue #${issueNumber}: GitHub returned ${response.status} for a non-OK response.
π΄ (12:56) getIssueEvents({ repository, issueNumber }) and getIssueComments({ repository, issueNumber }) paginate GitHub issue events and comments respectively with per_page=100&page=${page}, accumulate every page, and stop when a page contains fewer than 100 records. Their non-OK errors identify the issue number and returned HTTP status.
π΄ (12:56) main() in src/publish/authorize-approval.js requires environment variables GITHUB_OUTPUT, APPROVAL_TOKEN, APPROVAL_ISSUE_NUMBER, and APPROVAL_ISSUE_REPOSITORY, throwing a specific No "<NAME>" environment variable found error when any is absent. It also reads APPROVAL_ACTOR and APPROVAL_ISSUE_TITLE.
π΄ (12:56) When APPROVAL_ACTOR === AUTO_APPROVAL_LABELER, main() concurrently fetches the live issue, all issue events, and all issue comments. Authorization requires: the issue is "open"; its live title equals APPROVAL_ISSUE_TITLE; liveIssue.user?.login is a string and belongs to AUTO_APPROVERS; isAutoApprovedRepository() approves that requester and title against auto-approve-repos.txt; the current accepted event actor equals AUTO_APPROVAL_LABELER; and hasAutoApprovalAttestation() finds a matching attestation authored by "github-actions[bot]".
π΄ (12:56) For actors other than AUTO_APPROVAL_LABELER, main() delegates preliminary authorization to authorizeApproval({ actor, issueTitle, getPermission, autoApprovedRepositories }); although autoApprovedRepositories is passed, authorizeApproval() currently destructures only actor, issueTitle, and getPermission.
π΄ (12:56) If preliminary authorization fails, main() appends exactly authorized=false\n to GITHUB_OUTPUT and returns.
π΄ (12:56) After preliminary authorization, main() fetches the live issue and events if they were not already loaded, then revalidates that the issue remains open, its title still equals APPROVAL_ISSUE_TITLE, its requester login is a string, the non-auto-labeler actor is not the requester under case-insensitive comparison, a current accepted event exists, and that eventβs actor equals the approval actor. Any failure appends authorized=false\n.
π΄ (12:56) Successful approval creates a hidden approval proof with createApprovalAttestation({ actor: event.actor, eventId: event.eventId, issue }) and appends authorized=true\napproval_attestation=${attestation}\n to GITHUB_OUTPUT.
π΄ (12:56) src/publish/authorize-approval.js invokes main() only when run directly; rejected execution logs the error and sets process.exitCode = 1. It exports getAutoApprovedRepositories, getGitHubResponse, getIssue, getIssueComments, getIssueEvents, getPermission, and main.
π΄ (12:56) /home/byk/Code/getsentry/publish/src/modules/approval-authorizer.js is 57 lines. ALLOWED_ROLE_NAMES is exactly new Set(["write", "maintain", "admin"]); AUTO_APPROVAL_LABELER is "sentry-internal-app[bot]"; and AUTO_APPROVERS is exactly new Set(["getsantry[bot]", "sentry-release-bot[bot]"]).
π΄ (12:56) isAutoApprovedRepository({ actor, autoApprovedRepositories, issueTitle }) first rejects actors not in AUTO_APPROVERS, then parses the title with parsePublishTitle(), rejects invalid titles, and otherwise tests whether autoApprovedRepositories contains getsentry/${title.repo}${title.path || ""}.
π΄ (12:56) authorizeApproval({ actor, issueTitle, getPermission }) parses issueTitle using parsePublishTitle(). An invalid title returns { authorized: false, repository: null }; a valid title derives repository as getsentry/${title.repo}.
π΄ (12:56) authorizeApproval() explicitly rejects actors in AUTO_APPROVERS and rejects AUTO_APPROVAL_LABELER, returning { authorized: false, repository } in either case. Other actors are checked through getPermission({ owner: "getsentry", repository: title.repo, username: actor }) and are authorized only when the returned role_name is "write", "maintain", or "admin".
π΄ (12:56) src/modules/approval-authorizer.js exports AUTO_APPROVAL_LABELER, AUTO_APPROVERS, authorizeApproval, and isAutoApprovedRepository.