Dashboard › publish › Distillation
1282e940-6a9e-4d6b-a1b5-d68d7f29b380["lore_tm_v1_nwi7MEvMcGNHinVCOWFPN3-WNVj_ApL4nAm8vU7vNss","lore_tm_v1_PqcnqpiwExlUkoD28zJcm3Eqt6yxKzTMNVxiT9oltGc","lore_tm_v1_ChYL-1RJoAbpteUrfLpQLdPjLcTYq3_i48Jf-EZvU1o","lore_tm_v1_CVZZCW0sD_W4xyITuYb3c3X4B7vbH9nAarKyDlzgQag","lore_tm_v1_t_gsiENGsUzM-QZ0fjaAv3AxNz896wui0l1j-FPxJeQ","lore_tm_v1_205YjnSM9NVNIcOHPTU_0q7p2rQzMiPgO-ZWGjAOkNo","lore_tm_v1_up7Oz_cWCI8NJ-P0caJ-7r2DJHSuxWcmdgD5Z8V1840","lore_tm_v1_1uC25D7lkEr98wcBCeTmkWNnARNUdukiX4lw8ZRbp4I","lore_tm_v1_GBU_iCEp9-zKjDbgjVueNhzurVGHg-ZEdK8GzWbdKfE","lore_tm_v1_FBSiiICFREgPdf8nUgMXke_2PqJ8fWHSb4ZdPTfzi2I","lore_tm_v1_0rTTgapoDFWDVE3eWT2k51VBUgIx53fEnCEQdQCENQ4","lore_tm_v1_lkuYQwgTBHZdsp5U9ZDQXgW7de_4bkpD5ECjBFg_F_8","lore_tm_v1_BDl8XOiG_0JM5ysL0m2SqLA_us_-ooG48IYqv4eVkM8","lore_tm_v1_MmI5gt2b8k8g0EfVv3FYFI8QyhMVKqc62eK2ew6G5K4","lore_tm_v1_FqZOyZEeuEZpWxgas1hsG3zVW0u-Upjd8ujHDUTwJHE","lore_tm_v1_4eOECAXwqlY67eCByL4yOkCrh4lKgeNzPUqXHg6scYA","lore_tm_v1_4JFXli8M2wF8W4wGR-oPlYZJrDKsfy66tv5IeqQJaKk","lore_tm_v1_Yx34C5HMgbz6Zd-iNXGAId5zsPrjCTf8P1nYgGBW_qI"]
Date: Aug 29, 2026
src/publish/validate-approval-attestation.js:8-52 defines authenticated GitHub REST helpers using APPROVAL_TOKEN, Accept: application/vnd.github+json, and X-GitHub-Api-Version: 2026-03-10; getIssue() fetches repos/${repository}/issues/${issueNumber}, and getAllPages() fetches events or comments with per_page=100&page=${page} until a page has fewer than 100 records, throwing resource-specific errors for non-OK responses.validateApprovalAttestation() in src/publish/validate-approval-attestation.js:55-100 concurrently retrieves current issue labels/title, all events, and all comments; approval is valid only when the title equals issueTitle, accepted remains labeled, a current accepted event exists and optionally matches expectedAcceptedEvent.actor/eventId, and a trusted approval attestation matches. With requireCiReadyAttestation=true, it additionally requires a current ci-ready event, current ci-ready label, and CI-ready attestation tied to the accepted event, CI-ready label actor, and title.src/publish/validate-approval-attestation.js:102-151 requires APPROVAL_TOKEN, APPROVAL_ISSUE_NUMBER, APPROVAL_ISSUE_REPOSITORY, APPROVAL_ISSUE_TITLE, and APPROVAL_ATTESTATION_AUTHOR; optional expected approval identity is read only if both EXPECTED_ACCEPTED_ACTOR and EXPECTED_ACCEPTED_EVENT_ID exist, and REQUIRE_CI_READY_ATTESTATION === "true" enables CI-ready verification. Invalid validation throws Error("The current accepted label has no matching approval attestation").src/modules/__tests__/approval-attestation.js tests: latest accepted event ID "200" is selected over "100" and matches an attestation authored by github-actions[bot]; numeric GitHub event ID 29503999078 normalizes to string "29503999078"; CI-ready attestations bind accepted event { actor: "contractor", eventId: "200" } and CI-ready actor sentry-internal-app[bot], rejecting changed accepted event "201" or changed CI-ready label actor contractor; malformed base64 and attestations authored by an untrusted comment user or tied to stale title/event are rejected.src/modules/__tests__/approval-authorizer.js tests that getsantry[bot] is authorized without a target-repository permission lookup only when exact allowlist membership includes getsentry/sentry-javascript; it is denied outside that allowlist even if a mocked lookup says write. Human contractor is authorized for target-repository roles write, maintain, and admin, and denied for none, read, triage, "Elevated Bot", or undefined.src/modules/__tests__/approval-authorizer.js confirms unqualified title publish: sentry-javascript/packages/core@10.0.0 authorizes against getsentry/sentry-javascript; malformed titles publish: @1.0.0 and publish: getsentry/sentry-javascript return { authorized: false, repository: null } without GitHub querying; permission lookup failures such as Error("Not Found") propagate.src/publish/__tests__/authorize-approval.js uses test environment GITHUB_OUTPUT="/tmp/github-output", APPROVAL_TOKEN="release-bot-token", issue number "123", and approval repository getsentry/publish; it verifies getAutoApprovedRepositories() parses exact paths getsentry/sentry-javascript and getsentry/objectstore/clients, successful write permission emits authorized=true plus approval_attestation=<!-- publish-approval .+ -->, and a GitHub 404 permission response fails closed without output: Could not retrieve contractor's permission for getsentry/sentry-javascript: GitHub returned 404.src/publish/__tests__/current-accepted-event.js verifies getCurrentAcceptedEvent() returns latest accepted event { actor: "contractor", eventId: "200" } and rejects an empty event list with Error("The issue has no current accepted label event").src/publish/__tests__/record-ci-ready-attestation.js verifies recordCiReadyAttestation() produces a CI-ready proof binding accepted actor contractor, accepted event ID "100", authenticated app sentry-internal-app[bot], and title publish: getsentry/sentry-javascript@10.0.0; it rejects a changed title or a current re-approval event "200" that differs from poller-observed event "100" with Error("The approval changed before CI could be marked ready").src/publish/__tests__/validate-approval-attestation.js verifies valid trusted approval attestation acceptance and rejects: issue-title changes from getsentry/sentry-javascript@10.0.0 to getsentry/sentry-python@10.0.0; removal of accepted; re-adding accepted as newer event "200" after attested event "100"; and an expected observed approval { actor: "contractor", eventId: "100" } when current attested approval is event "200".src/publish/__tests__/validate-approval-attestation.js verifies CI-ready validation succeeds only with labels accepted and ci-ready, accepted event "100" by contractor, ci-ready event "200" by sentry-internal-app[bot], and both trusted attestations. A manually added ci-ready label by contractor is rejected even when the CI-ready attestation claims sentry-internal-app[bot]..github/workflows/ci-poller.yml, .github/workflows/publish.yml, AGENTS.md, src/libs/__tests__/github.js, src/libs/github.js, src/modules/__tests__/details-from-context.js, src/modules/details-from-context.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 additions include .lore.md, approval-attestation/authorizer modules and tests, src/publish/__tests__/, authorize-approval.js, current-accepted-event.js, record-ci-ready-attestation.js, and validate-approval-attestation.js.ci-ready..github/workflows/ci-poller.yml changes elevate issues permission from read to write, add actions/checkout@v6 with persist-credentials: false, bind and validate the approval event before inspecting CI, remove accepted when approval binding/validation fails or changes during CI, record a CI-ready attestation before applying ci-ready, and revalidate after proof creation to prevent a changed approval from reaching ci-ready..github/workflows/auto-approve.yml is named auto-approve non-sdks; on issue opening, it runs only when github.actor is sentry-release-bot[bot] or getsantry[bot] and title starts publish: . It checks out only auto-approve-repos.txt using actions/checkout@v4, obtains a Sentry Internal App token via actions/create-github-app-token@v3, extracts REPO from the issue title, and adds accepted only when grep -qxF "$REPO" auto-approve-repos.txt matches.src/modules/details-from-context.js:18-23 parses publish titles with PUBLISH_TITLE_REGEX = /^publish: (?:getsentry\/)?(?<repo>[^/@]+)(?<path>\/[\w./-]+)?@(?<version>[\w.+-]+)$/; parsePublishTitle() returns named groups or null.detailsFromContext() in src/modules/details-from-context.js:25-75 requires context.payload.issue, rejects invalid publish titles, emits dry_run: "1" only when label dry-run is present, emits path as "." + (titleMatch.path || ""), optionally extracts merge_target from Merge target: <[\\w.\\-/]+>, and extracts checked target IDs from the matched Targets checklist section.auto-approve-repos.txt contains 46 exact auto-approval allowlist entries: 1. getsentry/arroyo; 2. getsentry/auto-type-annotate; 3. getsentry/devenv; 4. getsentry/infra-event-notifier; 5. getsentry/jest-sentry-environment; 6. getsentry/json-schema-diff; 7. getsentry/js-source-scopes; 8. getsentry/objectstore/clients; 9. getsentry/ophio; 10. getsentry/pdb; 11. getsentry/pyo3-python-tracing-subscriber; 12. getsentry/pytest-sentry; 13. getsentry/relay/py; 14. getsentry/responses; 15. getsentry/rust-proguard; 16. getsentry/rust-sourcemap; 17. getsentry/rust-usage-accountant; 18. getsentry/script-runner; 19. getsentry/sentry-api-schema; 20. getsentry/sentry-forked-djangorestframework-stubs; 21. getsentry/sentry-forked-django-stubs; 22. getsentry/sentry-forked-jsonnet; 23. getsentry/sentry-infra-tools; 24. getsentry/sentry-kafka-management; 25. getsentry/sentry-kafka-schemas; 26. getsentry/sentry-protos; 27. getsentry/sentry-redis-tools; 28. getsentry/service-registry; 29. getsentry/skrooge; 30. getsentry/snuba-sdk; 31. getsentry/statsdproxy; 32. getsentry/status-page-list; 33. getsentry/streams/sentry_streams; 34. getsentry/symbolic; 35. getsentry/taskbroker/clients; 36. getsentry/usage-accountant; 37. getsentry/watto; 38. getsentry/sentry; 39. getsentry/snuba; 40. getsentry/vroom; 41. getsentry/relay; 42. getsentry/symbolicator; 43. getsentry/taskbroker; 44. getsentry/uptime-checker; 45. getsentry/launchpad; 46. getsentry/self-hosted.src/publish/inputs.js calls detailsFromContext({ context: github.context }) and publishes the resulting parsed issue details through core.setOutput("result", result).docs/rfc.md states the central publish repository design goals: recycle publishing tokens without disrupting releases, limit token access to authorized personnel, require SDK release approval by a manager or senior engineer for SOC/ISO compliance, and avoid divergent per-project publishing configurations. Proposed flow uses a central repository, structured issue templates, per-repository craft prepare, and accepted to trigger release; OSS CalVer releases are automatically approved unless blocked.