Dashboard › publish › Distillation
4914f4fa-ff88-4213-9485-73c4b1574ae7["lore_tm_v1_QRloY_ZLi5xlxEDNTyD2L0ZLEFW8upKWkyE6NABcjDI","lore_tm_v1_3hry8iKIAFS6Ug_PfLmXz6LzGLzjsOo2pDxBgks2mMg","lore_tm_v1_vNbaqC0u-JD_GH1sNLGAxLmxkJfsTlP1CudKgp08Ns0","lore_tm_v1__nLGfhptd_6m-kH_LZX-5i8FgbL13VPJ_PkXpxUM1cs","lore_tm_v1_-P3PDg4uYfxXhCsRfOL0q8AKPmSv6xF_1rIRedX5Wgc","lore_tm_v1_xXtP2CQjRs2x_G5WGXpd1QcmWf6l5KBJBk2HSX_nEEI","lore_tm_v1_osuCrVSGkNvIPPIWrUaFp6dbPrX3NXYCImjkzpCttBg","lore_tm_v1_CeO60B8jxYmafgi1IcSpdj3CU9v9siuBfhkNKa-ldWg","lore_tm_v1_q1NHP5eps8HCQ70IieKkdnO_OM6ZoKTwFiPPlL9OsmY"]
Date: Sep 8, 2026
src/modules/approval-authorizer.js defines ALLOWED_ROLE_NAMES as new Set(["write", "maintain", "admin"]), AUTO_APPROVAL_LABELER as "sentry-internal-app[bot]", and AUTO_APPROVERS as new Set(["getsantry[bot]", "sentry-release-bot[bot]"]).isAutoApprovedRepository({ actor, autoApprovedRepositories, issueTitle }) returns false unless actor is in AUTO_APPROVERS and parsePublishTitle(issueTitle) succeeds; it then checks whether autoApprovedRepositories contains getsentry/${title.repo}${title.path || ""}.authorizeApproval({ actor, issueTitle, getPermission }) returns { authorized: false, repository: null } for an unparseable publish title; otherwise derives repository as getsentry/${title.repo}, rejects all AUTO_APPROVERS and AUTO_APPROVAL_LABELER, calls getPermission({ owner: "getsentry", repository: title.repo, username: actor }), and authorizes only write, maintain, or admin role_name values.src/publish/authorize-approval.js getAutoApprovedRepositories() synchronously reads auto-approve-repos.txt as UTF-8, splits on /\r?\n/, removes empty lines, and returns a Set.src/publish/authorize-approval.js accesses GitHub through getGitHubResponse(path), fetching https://api.github.com/${path} with Accept: "application/vnd.github+json", Authorization: Bearer ${process.env.APPROVAL_TOKEN}, and "X-GitHub-Api-Version": "2026-03-10".src/publish/authorize-approval.js, getPermission() requests repos/{owner}/{repository}/collaborators/{username}/permission with URL-encoded components and throws Could not retrieve ${username}'s permission for ${owner}/${repository}: GitHub returned ${response.status} for a non-OK response.src/publish/authorize-approval.js, getIssue() fetches repos/${repository}/issues/${issueNumber} and throws Could not retrieve issue #${issueNumber}: GitHub returned ${response.status} on failure; getIssueEvents() and getIssueComments() paginate their respective resources at per_page=100, accumulating pages until a page contains fewer than 100 records.authorize-approval.js main() requires GITHUB_OUTPUT, APPROVAL_TOKEN, APPROVAL_ISSUE_NUMBER, and APPROVAL_ISSUE_REPOSITORY; missing values throw No "{name}" environment variable found.authorize-approval.js, when APPROVAL_ACTOR === AUTO_APPROVAL_LABELER, the workflow concurrently fetches the live issue, all events, and all comments; it authorizes only if the issue is open, its title exactly equals APPROVAL_ISSUE_TITLE, requester login is an AUTO_APPROVER, the repository is listed by isAutoApprovedRepository(), the current accepted event actor equals the labeler, and hasAutoApprovalAttestation() finds a matching attestation authored by "github-actions[bot]".AUTO_APPROVAL_LABELER path, authorize-approval.js delegates to authorizeApproval({ actor, issueTitle, getPermission, autoApprovedRepositories }); autoApprovedRepositories is passed although authorizeApproval() accepts only actor, issueTitle, and getPermission.authorize-approval.js fetches live issue/events if not already fetched and rejects authorization if the issue is not open, live title differs from APPROVAL_ISSUE_TITLE, requester login is missing, a non-auto-labeler actor is also the requester (case-insensitive), no current accepted event exists, or its actor differs from the actor. It appends authorized=false\n to GITHUB_OUTPUT on rejection; otherwise it appends authorized=true\napproval_attestation=${createApprovalAttestation({ actor: event.actor, eventId: event.eventId, issue })}\n.src/publish/current-accepted-event.js getCurrentAcceptedEvent({ getIssueEvents, issueNumber, repository }) runs currentAcceptedEvent(await getIssueEvents(...)), throws Error("The issue has no current accepted label event") when absent, and otherwise returns { actor, eventId }.current-accepted-event.js main() requires APPROVAL_TOKEN, APPROVAL_ISSUE_NUMBER, and APPROVAL_ISSUE_REPOSITORY; it gets event pages through getAllPages({ repository, issueNumber, resource: "events" }) and writes the selected event to stdout as JSON.src/publish/record-auto-approval-attestation.js recordAutoApprovalAttestation({ autoApprover, getIssue, issueNumber, issueTitle, repository }) fetches the live issue and throws Error("The automated approval request changed before approval") unless it is open, its title exactly matches issueTitle, and its requester login equals autoApprover case-insensitively; it then returns createAutoApprovalAttestation({ autoApprover, issue }).record-auto-approval-attestation.js main() requires GITHUB_OUTPUT, APPROVAL_TOKEN, APPROVAL_ISSUE_NUMBER, APPROVAL_ISSUE_REPOSITORY, APPROVAL_ISSUE_TITLE, and AUTO_APPROVER; it appends auto_approval_attestation=${attestation}\n to GITHUB_OUTPUT.src/publish/record-ci-ready-attestation.js getAuthenticatedLogin() calls getGitHubResponse("user"), throws Could not retrieve the authenticated user: GitHub returned ${response.status} for a non-OK response and GitHub returned no authenticated user login unless response login is a string.recordCiReadyAttestation({ expectedAcceptedEvent, getAuthenticatedLogin, getIssue, getIssueEvents, issueNumber, issueTitle, repository }) concurrently retrieves the issue, issue events, and authenticated GitHub login; it selects currentAcceptedEvent(events) and throws Error("The approval changed before CI could be marked ready") unless the issue is open, title matches, an "accepted" label remains, a current accepted event exists, andβwhen suppliedβits actor and event ID match expectedAcceptedEvent.recordCiReadyAttestation() returns createCiReadyAttestation({ acceptedEvent, ciReadyActor, issue }). Its CLI requires GITHUB_OUTPUT, APPROVAL_TOKEN, APPROVAL_ISSUE_NUMBER, APPROVAL_ISSUE_REPOSITORY, and APPROVAL_ISSUE_TITLE, optionally constructs expectedAcceptedEvent only when both EXPECTED_ACCEPTED_ACTOR and EXPECTED_ACCEPTED_EVENT_ID exist, and appends ci_ready_attestation=${attestation}\n.src/publish/validate-approval-attestation.js provides getGitHubResponse() with the same GitHub API headers/version "2026-03-10", getIssue() for repos/${repository}/issues/${issueNumber}, and generic getAllPages({ repository, issueNumber, resource }) for repos/${repository}/issues/${issueNumber}/${resource}?per_page=100&page=${page}; pagination ends below 100 records.validateApprovalAttestation({ attestationAuthor, expectedAcceptedEvent, issueNumber, issueTitle, repository, requireCiReadyAttestation = false }) concurrently fetches the issue, events, and comments; base approval requires an open issue, exact title, present "accepted" label, current accepted event, optional exact accepted actor/event-ID match, and hasApprovalAttestation() for attestationAuthor.requireCiReadyAttestation is false, validateApprovalAttestation() returns base approval; if true, it additionally requires a current "ci-ready" labeled event, a current "ci-ready" issue label, and hasCiReadyAttestation({ acceptedEvent: event, attestationAuthor, comments, ciReadyEvent, issue }).validate-approval-attestation.js main() requires APPROVAL_TOKEN, APPROVAL_ISSUE_NUMBER, APPROVAL_ISSUE_REPOSITORY, APPROVAL_ISSUE_TITLE, and APPROVAL_ATTESTATION_AUTHOR; REQUIRE_CI_READY_ATTESTATION === "true" enables CI-ready validation. It throws Error("The current accepted label has no matching approval attestation") when validation returns false.src/modules/update-issue.js updateTargets({ octokit, version, publishRepo, issue_number }) looks for ${process.env.GITHUB_WORKSPACE}/__repo__/.craft-publish-${version}.json; it returns without change when absent, otherwise concurrently retrieves the publish issue and parses the Craft state JSON, transforms the issue body, and updates the GitHub issue body.transformIssueBody(craftState, issueBody) rewrites matched target checklist lines in TARGETS_SECTION_PARSER_REGEX: each TARGETS_PARSER_REGEX target becomes - [x] ${targetId} when craftState.published[targetId] is truthy or - [ ] ${targetId} otherwise; it also appends all craftState.published keys not already declared as checklist lines, followed by newlines.updateIssue({ context, octokit, inputs }) derives publishRepo from context.repo and issue_number from context.payload.issue.number, then concurrently removes the "accepted" label and, only when inputs?.version exists, invokes updateTargets().src/publish/update-issue.js gets an Octokit client via github.getOctokit(getGitHubToken()); it parses PUBLISH_ARGS as JSON when present, logs Could not parse publish inputs; skipping target update if parsing fails, then calls updateIssue({ context: github.context, octokit, inputs }).src/publish/inputs.js invokes detailsFromContext({ context: github.context }) and sets its result as the GitHub Actions output named "result" through core.setOutput("result", result).