Dashboard › craft › Distillation
0da764a1-e7b7-466a-b090-a7f49b06cedc["lore_tm_v1_vE-IGRVezhvWkR_TB2UwrOfojqP-FZkrpA5OwYLspZA","lore_tm_v1_fJOHRdCcvV-7nJIxEIM7MfDnJu1r5kqTHt81zRDz17c","lore_tm_v1_LNWNvZmo_3Vcjr4i04OLW-zSU2KYsNsYvyYp5Tw9hXw","lore_tm_v1_I1ygK37yd_pwq-vqDAJqOcriGJT9zxs0TljbxicrJd8","lore_tm_v1_FmnU1qJNczFTu6sdCb27oJy1-mVWTvyqbhuimBQQlK4","lore_tm_v1_UKH4wPcsb3kZEvMdFZ3tBxHxaiQidfscYvS35UV-7xA","lore_tm_v1_rjfpfebzGDs58RILgu2jOJNB2z10j8PmBCW-3lfugHk","lore_tm_v1_0zn5wICTsgH15L0ZOSE1kMMCqy6xA2zLovtbXZ9W8do","lore_tm_v1_XBVd0f55KMviNcSHLFBu_p7O3z1MYmQk9KtZj6cd5qk","lore_tm_v1_2y3cEo1ZBxRhOQrMBv2EmsdHilFPkPwgzg3zHo0dliw","lore_tm_v1_DuEJayC_m57gIxXBT9d59icdR3osTQXGCyW5-H9VpmA","lore_tm_v1_T8ZThHoRWlQYoFccZSDE39txevUPBCw6EYuZa23_HSk","lore_tm_v1_f_d2wIKM7MQ3jEkSI60QWOrLxqhP5hy8-YrRoeLyQi0","lore_tm_v1_QZGAp_jJtq_SIJ7U71cr2NwkHFUqej_SqepK2Fq7oYo","lore_tm_v1_HVLCDsU2aFAiiSSz7Bb1eW8aS0kMCWpNdBTYVac0WZE"]
Date: September 8, 2026
workflow_dispatch for manual recovery..github/workflows/ci-poller.yml runs on schedule */5 * * * * and workflow_dispatch, with optional attempt input defaulting to "0"; its check-ci job gate is vars.CI_POLLER_HAS_PENDING == 'true' || github.event_name == 'workflow_dispatch', enabling manual recovery when the pending variable is false..github/workflows/ci-poller.yml uses concurrency.group: ci-status-poller with cancel-in-progress: false; it only lists open issues carrying both ci-pending and accepted, up to 200.actions/create-github-app-token@v3 creates the sentry-internal-app token for local issue-label changes and a sentry-release-bot token with owner: getsentry for cross-repository status/check-suite/check-run API calls, including private repositories such as sentry-xbox, sentry-playstation, sentry-switch, and service-registry.gh_api_release() invokes gh api with GH_TOKEN="$RELEASE_TOKEN" in command substitution, captures stderr, emits ::warning::gh api failed: $output on nonzero exit, and returns the API failure code; this prevents token override leakage and makes cross-repo API failures detectable.repos/${repo}/commits/${issue_sha}/check-suites using .check_suites[0].head_branch // empty, then resolves repos/${repo}/git/ref/heads/${branch} .object.sha; each failure falls back non-fatally to the original issue SHA.success, neutral, and skipped check conclusions passing; regards CI as ready only when commit status is success or there are 0 statuses, 0 pending checks, and 0 unsuccessful checks. If both check-run and status counts are 0, it treats CI as not started and skips the issue.ci-pending, adds ci-ready, and comments CI checks passed for ${repo}@${version}. Publishing is starting now.; completed unsuccessful checks instead remove ci-pending and accepted, add ci-failed, list failed check names, link to ${sha}/checks/, and instruct the author to re-add accepted after fixing CI.commit_status == "failure" with no pending/unsuccessful check runs as a failure: removes ci-pending and accepted, adds ci-failed, comments failed status contexts (with target URLs where available), and links check runs.1 remaining open issue with both ci-pending and accepted; with a successful CI_POLLER_APP token, it sets repository variable CI_POLLER_HAS_PENDING to "false" when none remain and "true" otherwise.gh workflow run ci-poller.yml -R "$GITHUB_REPOSITORY" -f attempt="${attempt}" while pending issues remain, incrementing ATTEMPT; it caps self-dispatch at 60 attempts (about 30 minutes), then relies on cron fallback because */5 cron can drift to 30–40 minutes under load. The concurrency policy permits at most 1 running and 1 queued run.src/modules/publish-issue-title.peggy canonical title grammar permits optional getsentry/ prefix, repository characters [A-Za-z0-9_.-], optional slash-separated paths using those same characters, and versions [A-Za-z0-9_.+-]+; comments clarify path suffixes are syntactic and the controller resolves the complete suffix as a workspace only after checking out the CI-approved revision.src/modules/ci-poller-input.js parses and validates title repository, version, and path = \.${parsedTitle.path}`before any CI API calls; it returnsrepo: `getsentry/${repo}`, canonical issue revision, and version, and conditionally returns rewritten issueBodywhen passed a replacementrevision`.src/modules/__tests__/ci-poller-input.js verifies root and nested titles (publish: getsentry/toolkit/cli@1.2.3 and publish: toolkit/packages/cli/v2@1.2.3) both resolve to repo: "getsentry/toolkit", revision 7e5ca7ed5581552de066e2a8bc295b8306be38ac, and version "1.2.3".src/modules/__tests__/ci-poller-input.js tests rejection before CI API calls for unsafe repository identities -toolkit, ., .., __proto__; invalid versions --config, 1.2; malformed titles publish: getsentry/@1.2.3, publish: getsentry/toolkit$@1.2.3; and unsafe paths containing ../other, ./other, __proto__/other, or --config.src/modules/__tests__/release-revision.js tests canonical revision extraction for LF and CRLF bodies, acceptance of /checks with or without terminal slash, repository mismatch rejection, rejection when /checks is absent, rejection of decoy/embedded duplicate check-run links, rejection of headers not at body start, and replacement validation for uppercase or 39-/41-character SHAs.src/modules/__tests__/ci-poller-workflow.js executes the extracted YAML shell script using mocked node, mktemp, and gh; tests prove resolver failure and resolver rewrite output lacking issueBody exit successfully without gh issue edit, clean all temporary files, and preserve all rewrite-body bytes outside the revision.src/publish/discover-location.js getWorkspaceNames() returns [] without ${repositoryDirectory}/.craft.yml; otherwise executes Docker getsentry/craft:latest workspace list mounting path.resolve(repositoryDirectory) at /github/workspace/__repo__ with workdir /github/workspace/__repo__. It requires parsed output to be an array or throws Craft workspace discovery returned an invalid workspace list.src/publish/discover-location.js parses PUBLISH_ARGS || "{}", requires input.path (Publish input must define a path.), defaults PUBLISH_REPOSITORY_DIRECTORY to "__repo__", resolves location via resolvePublishLocation, and JSON-serializes the result to the GitHub Actions output result.src/publish/__tests__/discover-location.js verifies that absent root .craft.yml retains path ./packages/cli; a discovered workspace list ["packages/CLI"] maps ./packages/CLI to { path: ".", workspace: "packages/CLI" }; object JSON {} and blank Docker output are rejected as invalid workspace lists.src/publish/__tests__/resolve-location.js verifies blank PUBLISH_ARGS: "" with CRAFT_WORKSPACE_NAMES: "[]" fails location validation with Invalid publish path., not Unexpected end of JSON input.src/publish/__tests__/resolve-release-revision.js verifies blank PUBLISH_ARGS: "" and PUBLISH_ISSUE_BODY: "" fail with Publish input must define a repository., not Unexpected end of JSON input.src/modules/__tests__/generate-publish-issue-title-parser.js tests generateDocumentation() rejects documentation without grammar markers, duplicated generated grammar blocks, and malformed marker <!-- BEGIN GENERATED TITLE GRAMMAR -- >, each with Could not find the generated title grammar in the documentation.