Dashboard › craft › Distillation
30dabc70-b5ce-417b-be17-cb1a8949434e["lore_tm_v1_YbTBLzoylU6fcRMjxt-DAn7uOQ3YxSzQ5XM6AyNHLDY","lore_tm_v1_aB50s64eeeZg77lzrASdG4mY9U3dYggPvmSlKcK2ye0","lore_tm_v1_lJRxuEjGCGXjidRIjA1dXt_tt7xYupQ7rQG0ofAhNUQ","lore_tm_v1_ClF8kQMD30qTV9m8dVcwsGLVDM114xzz1P_6lwVaMGc","lore_tm_v1_3W6--7DASIli7eMH867I0zTTP7Vj_QHwtXDPhK2YrEA","lore_tm_v1_kqzUsfqFsR-tUH-CCuvKhjU5oXSSVkSbh5u0gx5kQmE","lore_tm_v1_9v4D_RSqMQBJq4SDHjF5JaR_JK2lFIvCGo4QjUiw2UE","lore_tm_v1_t8IGLL8E4trNNbfqvgZssTBfpptORkfxjmdsBj7Euq0","lore_tm_v1_WPauHI2pWrRtrw2NtMSEM-5-58r_R3rtTbkjb7lrL0Y","lore_tm_v1_rDJLkG4mRJc-64EP3LK-3SH1h5sm-I3FVNUI59TpQuY","lore_tm_v1_gNuXm_P5GMEwsxS7MiCW6MSK8foh-ZkAJDdHqhUQG_k","lore_tm_v1_2h8FcNxWh59Q2GPmhRPJCckpDmA0RyzQ2qBQJz7AUu0","lore_tm_v1_JjchcdRKbeUXCdLBspazOM7U5_DtcyDuj6lM13eew70","lore_tm_v1_7_VNZLqH-SWDWaHwNZfyFn7GB2Rg2aE2oDmTI_oXfHg","lore_tm_v1_LIYEKoae9e_dcNMa7HXvRaVwKdXn0DnBDV_RqioTlO8","lore_tm_v1_km1qBKcKELXZdNvTN21lGnH-r3RMK6A00ymJymJ2uMw"]
Date: Sep 8, 2026
/home/byk/Code/getsentry/publish-workspace-acceptance: Sentry Publish Repository is a pure CommonJS JavaScript project on Node.js 24.0.0; use Yarn 1.22.22 via Volta and do not use npm; primary commands are yarn test, yarn test:watch, yarn lint, and yarn prettier.require/module.exports, camelCase functions/variables, UPPER_SNAKE_CASE constants/regexes, double-quoted strings, and required semicolons; test files are ESM in __tests__/ and Vitest v4.0.0 globals are enabled.default branch of switch statements.@getsentry/releng (Release Engineering)..github/workflows/ci-poller.yml, .github/workflows/publish.yml, docs/publish-issue-format.md, scripts/generate-publish-issue-title-parser.js, src/modules/__tests__/details-from-context.js, src/modules/__tests__/publish-workflow.js, src/modules/__tests__/release-revision.js, src/modules/details-from-context.js, src/modules/publish-issue-title.js, src/modules/publish-issue-title.peggy, src/modules/release-revision.js, src/publish/inputs.js, src/publish/resolve-ci-poller-input.js, src/publish/resolve-location.js, and src/publish/resolve-release-revision.js; untracked artifacts are src/modules/__tests__/generate-publish-issue-title-parser.js, src/publish/__tests__/discover-location.js, src/publish/__tests__/resolve-location.js, src/publish/__tests__/resolve-release-revision.js, and src/publish/discover-location.js.feat/workspace-acceptance at a81ab033098f151fbc291b7b0c934901405bb162 / a81ab03 and tracks origin/feat/workspace-acceptance; compared baseline shown as 83d210b29553ea6f4d97508821724a834c43856e; recent branch commits are a81ab03 feat: resolve workspace publish paths, 52ef600 feat: resolve compact workspace publish requests, b658ffa fix: validate publish workspace JSON, and 33de3f1 feat: accept workspace publish requests.src/modules/ci-poller-input.js, src/modules/publish-issue-title.js, src/modules/publish-issue-title.peggy, src/modules/publish-issue-validation.js, src/modules/publish-location.js, src/modules/release-revision.js, src/publish/resolve-ci-poller-input.js, src/publish/resolve-location.js, and src/publish/resolve-release-revision.js.src/modules/publish-issue-title.peggy defines canonical title grammar publish: with optional getsentry/, repository [A-Za-z0-9_.-]+, optional slash-delimited path segments using the same character set, and version [A-Za-z0-9_.+-]+; parser output is { repo, path: path || "", version }.src/modules/publish-issue-title.peggy defines RequestHeader as the initial issue-body header: Requested by: @..., Merge target: ..., Quick links:, a View changes link, then a View check-runs link exactly matching https://github.com/getsentry/<repo>/commit/<revision>/checks, with optional trailing slash; CheckRunsRevision requires exactly 40 lowercase [0-9a-f] characters and captures source offsets for replacement.src/modules/publish-issue-title.peggy defines CheckRunsLinkCount by scanning the entire body for literal - [View check runs]( entries and returns the count, intended to prevent appended decoy check-runs links.src/modules/release-revision.js implements getReleaseRevisionDetails({ issueBody, repo }): it requires parse(issueBody, { startRule: "CheckRunsLinkCount" }) === 1, parses ReleaseRevision, validates parsed details.repo === repo, and otherwise throws errors referencing getsentry/${repo}; getReleaseRevision() returns .revision.value.src/modules/release-revision.js validates replacement revisions with /^[0-9a-f]{40}$/; updateReleaseRevision({ issueBody, repo, revision }) rejects invalid values with "Release revision must be a lowercase 40-character SHA." and replaces only the captured revision range via issueBody.slice(0, currentRevision.start), revision, and issueBody.slice(currentRevision.end).src/modules/details-from-context.js parses the issue title through parsePublishIssueTitle, validates repository with isPublishRepository, version with isReleaseVersion, converts title path to "." + titleDetails.path, validates it using isPublishPath, obtains mergeTarget solely through getReleaseRevisionDetails({ issueBody, repo: titleDetails.repo }), and returns merge_target: mergeTarget === "(default)" ? "" : mergeTarget.src/modules/details-from-context.js sets dry_run to "1" when an issue label named dry-run exists, otherwise ""; it parses checked targets from the leading Targets section using TARGETS_SECTION_PARSER_REGEX and CHECKED_TARGETS_PARSER_REGEX, returning { ...titleDetails, dry_run, merge_target, path, targets }.src/modules/publish-issue-validation.js accepts repositories matching /^[A-Za-z0-9_.-]+$/ except ., .., __proto__, and names beginning -; isReleaseVersion() uses a case-insensitive semver-like regex requiring numeric major/minor/patch and optional prerelease/build components.src/modules/publish-location.js accepts publish path "." or "./" plus slash-separated safe segments; safe workspace segments match [A-Za-z0-9_.-]+ but reject ., .., __proto__, and leading -. resolvePublishLocation({ path, workspaceNames }) validates path and all workspace names, returns { path } for root or nonmatching paths, and maps a direct matching ./<workspace> request to { path: ".", workspace: <workspace> }.src/modules/ci-poller-input.js parses and validates title repo/version/path, reads canonical current revision with getReleaseRevision({ issueBody, repo }), and returns { repo: "getsentry/<repo>", revision: currentRevision, version }; when optional revision is supplied, it additionally returns issueBody: updateReleaseRevision({ issueBody, repo, revision }).src/publish/inputs.js calls detailsFromContext({ context: github.context }) and emits core.setOutput('result', JSON.stringify(result)).src/publish/resolve-ci-poller-input.js reads issue body from UTF-8 file path PUBLISH_ISSUE_BODY_FILE when set, otherwise PUBLISH_ISSUE_BODY || ""; it writes JSON from getCiPollerInput() to stdout using PUBLISH_TITLE || "" and PUBLISH_REVISION || "".src/publish/resolve-release-revision.js parses PUBLISH_ARGS || "{}", throws "Publish input must define a repository." when .repo is absent, and outputs canonical revision from getReleaseRevision({ issueBody: process.env.PUBLISH_ISSUE_BODY || "", repo }) as Action output revision.src/publish/resolve-location.js parses PUBLISH_ARGS || "{}" and CRAFT_WORKSPACE_NAMES || "[]", requires workspace names to be an array, resolves via resolvePublishLocation({ path: input.path, workspaceNames }), and emits JSON as Action output result.src/publish/discover-location.js conditionally performs Craft workspace discovery only when <repositoryDirectory>/.craft.yml exists; absent root .craft.yml returns [].src/publish/discover-location.js runs docker run --rm --volume <absolute repositoryDirectory>:/github/workspace/__repo__ --workdir /github/workspace/__repo__ getsentry/craft:latest workspace list, parses its UTF-8 JSON output as an array, and throws "Craft workspace discovery returned an invalid workspace list." for invalid JSON or non-array output. main() requires input.path, defaults PUBLISH_REPOSITORY_DIRECTORY to "__repo__", and emits the resolved location as output result.ci-ready after checking CI; the waiting-for-ci workflow removes existing ci-ready first so a fresh labeled event is generated..github/workflows/publish.yml waiting-for-ci runs for open issues when accepted is newly labeled and title starts publish: ; it uses actions/create-github-app-token@v3, removes ci-failed and ci-ready, adds ci-pending, comments on retry versus new approval, best-effort sets repository variable CI_POLLER_HAS_PENDING to "true", and dispatches ci-poller.yml using the app token..github/workflows/publish.yml publish job requires an open issue, event label ci-ready, labels accepted and ci-ready, and absence of ci-pending and ci-failed; comments describe this as a fresh CI gate that prevents acceptance/publish auto-approve races. The job timeout is 90 minutes..github/workflows/publish.yml checks out the publish repository to .__publish__ using actions/checkout@v6, sets up Node 24 with Yarn cache, installs with yarn install --cwd ".__publish__", parses inputs, resolves the canonical CI-approved revision from the issue body, then checks out getsentry/${{ fromJSON(steps.inputs.outputs.result).repo }} into __repo__ at exact steps.release-revision.outputs.revision with fetch-depth: 0..github/workflows/publish.yml resolves the target checkoutβs publish location via node .__publish__/src/publish/discover-location.js with PUBLISH_ARGS and PUBLISH_REPOSITORY_DIRECTORY: __repo__..github/workflows/publish.yml target-state setup serializes selected targets to {"published": ...}, stores the state outside the target checkout at $GITHUB_WORKSPACE/.craft-state/craft/publish-state-<owner>-<repo>-<cwd_hash>-<workspace_prefix><version_component>.json, calculates cwd_hash as the first 12 characters of SHA-1 over canonical container cwd, validates that cwd remains within /github/workspace/__repo__, and emits the state-file path through $GITHUB_OUTPUT..github/workflows/publish.yml encodes non-sanitized version components as URL-safe base64 version-<encoded> and optional workspace identity as workspace-<base64>- to isolate Craft publish state; comments state the state must follow issue checkout identity rather than a workspaceβs optional release-repository override..github/workflows/publish.yml invokes docker://getsentry/craft:latest, changes to __repo__/${{ fromJSON(steps.location.outputs.result).path }}, and executes craft publish <version> --rev <canonical revision> with XDG_STATE_HOME: /github/workspace/.craft-state, CRAFT_MERGE_TARGET from parsed inputs, CRAFT_WORKSPACE from resolved location, and CRAFT_PUBLISH_STATE_GITHUB_REPO: getsentry/<issue repo>..github/workflows/publish.yml uses actions/checkout@v6 at lines 120 and 159, despite the audit request explicitly requiring actions/checkout@v7.