Dashboard › publish › Distillation
1f29a11a-ddf8-478e-87fb-0381c3b2fca8["lore_tm_v1_kU5urIrVILyTN_ZddFny8srDwyXjerutvRAMxVKdGy4","lore_tm_v1_qM4N_tE4cCAo5pJx609rDdJhRidWXpnfXQ72DfikuE4","lore_tm_v1_v5mFSENXbNUagnorNF_xFAGAzGkpz2NLEB_d9qKroDI","lore_tm_v1_9De1ebYWxncI6r_1ldLOKw3jFnMXdfnU-qtQ0nY0mPY","lore_tm_v1_rB52NXU3_i5hBazXc0NxhQ-4YPyd3qczh3rVbCwV6ko","lore_tm_v1_c2YarlOarGf_Azn4SsSSsXxLeDStutYEuuwGJ8VQFig","lore_tm_v1_zQqbvXQlxZcNEePuxgS1NpIVELFbK-FwJ3ppthfvWN8","lore_tm_v1_2LUsMwKFwPS9qtWZ3QIOodb5980orHQWeqplJVMDEjU"]
π΄ (12:08) Working tree contains new src/publish/request-digest-from-event.js: requestDigestFromEvent(event) rejects events without an issue object, computes requestDigest(event.issue) via src/modules/approval-attestation.js, and main() reads JSON from GITHUB_EVENT_PATH and appends request_digest=β¦ to GITHUB_OUTPUT; missing environment variables fail closed.
π΄ (12:08) .github/workflows/auto-approve.yml now grants issues: write, places auto-approve behind the production environment, disables persisted checkout credentials, and pins actions/checkout to 11d5960a326750d5838078e36cf38b85af677262 and actions/create-github-app-token to bcd2ba49218906704ab6c1aa796996da409d3eb1.
π΄ (12:08) Automated approval flow in .github/workflows/auto-approve.yml now runs src/publish/request-digest-from-event.js, records request-bound proof with src/publish/record-auto-approval-attestation.js, posts AUTO_APPROVAL_ATTESTATION as a GitHub issue comment using github.token, and only performs app-token auto-approval if attestation creation succeeds.
π΄ (12:08) .github/workflows/cocoapods-keepalive.yml currently removes its workflow_dispatch trigger, leaving the daily 0 0 * * * schedule.
π΄ (12:08) .github/workflows/test.yml pins actions/checkout to d23441a48e516b6c34aea4fa41551a30e30af803, actions/setup-node to 249970729cb0ef3589644e2896645e5dc5ba9c38, and actions/cache to 0057852bfaa89a56745cba8c7296529d2fc39830; Node remains version 24.
π΄ (12:09) User directive: always allow workflow_dispatch for manual recovery.
π΄ (12:09) User directive: always run trusted code.
π΄ (12:09) User directive: never move a release to ci-ready after it changes.
π΄ (12:09) User requires a renamed or re-approved issue to never reach ci-ready.
π΄ (12:09) .github/workflows/ci-poller.yml currently replaces direct workflow_dispatch plus its attempt input with repository_dispatch type ci-poller and a completed workflow_run handoff from the checked-in workflow named Run CI Status Poller; permissions change from issues: read to issues: write.
π΄ (12:09) The check-ci job in .github/workflows/ci-poller.yml runs when vars.CI_POLLER_HAS_PENDING == 'true', on repository_dispatch, or after a successful workflow_run whose head_branch equals the repository default branch; comments identify the latter two as trusted manual-recovery paths.
π΄ (12:09) The CI-poller diff adds live approval-event and request-digest validation before inspecting CI, removes accepted when canonical publish input cannot be updated or decoded, rechecks renamed/re-approved issues before advancing, and explicitly removes stale ci-ready before the deliberate transition.
π΄ (12:09) .github/workflows/publish.yml adds a trusted-code checkout with persist-credentials: false, pins actions/checkout and actions/create-github-app-token, binds the triggering request snapshot with src/publish/request-digest-from-event.js, obtains a separate Sentry Release Bot token with continue-on-error: true, authorizes the approverβs target-repository access, and validates approval attestations attributed to github-actions[bot].
π΄ (12:09) The publish job adds its own checked-out code and request-snapshot binding, rejects invalid approval before setup or publication, pins actions/setup-node to 249970729cb0ef3589644e2896645e5dc5ba9c38 with Node 24, and adds final-approval-validation immediately before later privileged publication steps.
π΄ (12:10) src/modules/ci-poller-input.js changes getCiPollerInput() to accept labels, compute resolvedIssueBody after any revision substitution, and return requestDigest: requestDigest({ body: resolvedIssueBody, labels, title }); src/publish/resolve-ci-poller-input.js supplies labels from JSON.parse(process.env.PUBLISH_ISSUE_LABELS || "").
π΄ (12:10) src/modules/details-from-context.js adds parsePublishTitle(title), which returns parsed title details only when the repository, version, and "." + path pass isPublishRepository(), isReleaseVersion(), and isPublishPath(); parse or validation failures return null, and the function is exported.
π΄ (12:10) src/publish/discover-location.js replaces mutable getsentry/craft:latest with immutable CRAFT_IMAGE = "getsentry/craft@sha256:9a4a5d5efa44a00c2215078ead39800d4aaa5a97908b94f45a64d7d506d6e14b" for Craft workspace discovery.
π΄ (12:10) src/modules/process-end-state.js now defaults inputs = {}, validates terminal status via sentryInfoFromDetails({ status, repo }) before state changes, and on success closes the issue before workflow-run lookup, commenting, or session reporting.
π΄ (12:10) src/publish/post-result.js moves PUBLISH_ARGS parsing into exported async main(), defaults missing or malformed input to {}, warns "Could not parse publish inputs; reporting without them", awaits processEndState, and catches top-level failures by setting process.exitCode = 1.
π΄ (12:10) src/publish/update-issue.js moves runtime setup into exported async main(); missing or malformed PUBLISH_ARGS leaves inputs as undefined, malformed JSON warns "Could not parse publish inputs; skipping target update", and updateIssue({ context, octokit, inputs }) is still invoked so cleanup can proceed.
π΄ (12:11) src/modules/__tests__/process-end-state.js adds regression test "closes the issue before workflow lookup and comments": even when getWorkflowRun rejects with "unavailable", issue getsentry/publish#211 must already have been updated to state: "closed", verified through invocation ordering.
π΄ (12:11) src/modules/__tests__/update-issue.js adds regression test "removes accepted without parsed publish inputs": with no CRAFT_STATE_FILE_PATH and no parsed inputs, it performs no state-file read, issue fetch, or issue-body update, but removes label accepted from getsentry/publish#211.
π΄ (12:11) AGENTS.md adds a lore-managed Long-term Knowledge section pointing to project-root .lore.md and https://github.com/BYK/loreai.
π΄ (12:11) README.md now documents that secret-bearing jobs use the protected production environment, only main may deploy there, administrator bypass is disabled, and environment-scoped credentials are protected from arbitrary workflow refs.
π΄ (12:11) README.md documents that SENTRY_INTERNAL_APP_PRIVATE_KEY and SENTRY_RELEASE_BOT_PRIVATE_KEY are organization-level secrets whose cross-repository availability is an organization-wide security boundary that Security must manage separately.
π΄ (12:11) docs/key_rotation_vault_changes.md and docs/rfc.md contain Markdown indentation/formatting cleanup without substantive changes to their listed credential-management plan or release RFC.