Dashboard › craft › Distillation
20ae2e59-da33-442f-9c75-14ec94d96103["lore_tm_v1_kBRWQhe7hABOluhFbZlRRB7d79AtxbJiagJzgNqcfqg","lore_tm_v1_yaI9-0qJpMx6GOamqAojzcN-f4AwbKyE5pJX8VdNaUw","lore_tm_v1_M5beKyAYVlSCtqLj7s_FZO6GxVs0iMbS_8DvDU2SNhE","lore_tm_v1_5Rs4cqnb4BffK83PVjzGU7Ae4Qyq_P9uy2re7a72RnQ"]
Date: Aug 29, 2026
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-location.js: needsWorkspaceDiscovery() is tested true only for { path: "./cli" }, and false for { path: "./packages/cli" }, { path: "." }, and { path: "./cli", workspace: "cli" }.publish-location.js tests require exact, case-preserving workspace matching: resolvePublishLocation({ path: "./CLI", workspaceNames: ["cli", "CLI"] }) returns { path: ".", workspace: "CLI" }; nonmatching ./packages, multi-segment ./packages/cli, and root . remain checkout paths.publish-location.js tests preserve legacy explicit workspace "cli/v2" only at root path ".", do not validate discovery names for that explicit legacy workspace even when workspaceNames: ["invalid/workspace"], reject explicit workspace with path: "./packages/cli" using A publish workspace must use the repository root path., and reject discovered invalid workspace "cli-ζ₯ζ¬θͺ" with Craft workspace discovery returned an invalid workspace list.src/modules/details-from-context.js: it imports parse from ./publish-issue-title; missing context.payload.issue throws Issue context is not defined; parser failures throw Invalid publish issue title: '<title>'.detailsFromContext() parses legacy workspace JSON from the title; malformed JSON throws Invalid publish workspace JSON in title: '<title>'; decoded workspace must be nonempty and cannot match /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u, otherwise it throws Workspace names must be nonempty and cannot contain Unicode control, format, or separator characters.detailsFromContext() constructs path as "." + parsedTitleDetails.path, rejects a .. path segment with Invalid publish issue path: '<path>', and rejects any workspace paired with a non-root path with A publish workspace must use the repository root path..detailsFromContext() emits dry_run: "1" only when an issue label is exactly "dry-run"; extracts optional merge_target from a line matching ^Merge target: (?<merge_target>[\w.\-/]+)$; parses checked target IDs using CHECKED_TARGETS_PARSER_REGEX; returns parsed title fields, dry_run, merge_target, path, targets, and workspace only when present.ci-ready label..github/workflows/cocoapods-keepalive.yml, .github/workflows/publish.yml, README.md, docs/publish-issue-format.md, package.json, src/modules/__tests__/details-from-context.js, src/modules/__tests__/publish-workflow.js, src/modules/__tests__/update-issue.js, src/modules/details-from-context.js, src/modules/post-workflow-details.js, src/modules/update-issue.js, src/publish/inputs.js, and yarn.lock..github/workflows/publish.yml: replaced the branch allowlist-based Set target repo checkout branch step with Resolve CI-approved release revision, which runs node .__publish__/src/publish/resolve-release-revision.js using PUBLISH_ARGS and PUBLISH_ISSUE_BODY; target checkout __repo__ now uses ref: ${{ steps.release-revision.outputs.revision }} with repository: getsentry/${{ fromJSON(steps.inputs.outputs.result).repo }} and fetch-depth: 0.Resolve publish location determines requires_workspace_discovery by requiring ./.__publish__/src/modules/publish-location and calling needsWorkspaceDiscovery(input); only when true and __repo__/.craft.yml exists, it runs getsentry/craft:latest workspace list in Docker and passes its output as CRAFT_WORKSPACE_NAMES to node .__publish__/src/publish/resolve-location.js.Set targets now has id: craft-state, uses resolved CRAFT_PUBLISH_PATH and CRAFT_PUBLISH_WORKSPACE, resolves container CWD with realpath -m "/github/workspace/__repo__/$CRAFT_PUBLISH_PATH", and fails with ::error::Publish path must remain inside the target checkout. if CWD is outside /github/workspace/__repo__.= padding and prefixes the filename with workspace-<encoded>-; writes state under $GITHUB_WORKSPACE/.craft-state/craft/publish-state-${owner_sanitised}-${repo_sanitised}-${cwd_hash}-${workspace_prefix}${version_sanitised}.json, outputs state_file, and writes the already-published payload there.__repo__/${{ fromJSON(steps.location.outputs.result).path }} using craft publish ${{ fromJSON(steps.inputs.outputs.result).version }} --rev ${{ steps.release-revision.outputs.revision }}; it sets CRAFT_WORKSPACE from resolved location and sets CRAFT_PUBLISH_STATE_GITHUB_REPO to getsentry/${{ fromJSON(steps.inputs.outputs.result).repo }} so state follows issue checkout identity rather than any workspace GitHub release-repository override.CRAFT_STATE_FILE_PATH: ${{ steps.craft-state.outputs.state_file }} to node .__publish__/src/publish/update-issue.js.docs/publish-issue-format.md and README link. Documentation defines canonical title EBNF: publish: , optional getsentry/, repository, optional slash path, optional legacy JSON workspace, @, and version; repository/path tokens allow ASCII letters, digits, ., _, -; versions additionally allow +.publish: getsentry/sentry@21.3.1 and publish: getsentry/toolkit/cli@1.2.3; one trailing suffix is resolved as a workspace only after checkout of the exact CI-approved View check runs revision and exact key discovery via root .craft.yml plus craft workspace list; absent root .craft.yml means checkout-path behavior, and discovery errors with root configuration fail the release.publish: getsentry/toolkit [workspace: "cli/v2"] @1.2.3 and publish: getsentry/toolkit [workspace: "cli [preview] \"next\""] @1.2.3; legacy workspace must use root path; decoded legacy workspace must be nonempty and exclude Unicode Cc, Cf, Zl, and Zp; optional getsentry/ remains parse-compatible; paths cannot include ...Merge target is optional, (default) selects the target repositoryβs default branch, and valid branch characters are letters, digits, _, ., /, -; checked ### Targets entries are skipped and retained during Craft refresh; secure publish-state updates target checkboxes after failures; accepted triggers publishing and dry-run enables dry-run mode.package.json changes: added scripts "generate": "node scripts/generate-publish-issue-title-parser.js" and "check:generated": "node scripts/generate-publish-issue-title-parser.js --check"; "test" now runs yarn check:generated && vitest run; added dev dependency "peggy": "5.1.0".details-from-context tests cover parsing legacy workspace "cli/v2", escaped workspace cli [preview] "next", and Unicode "cli-ζ₯ζ¬θͺ"; reject non-root legacy workspace, unqualified title with unexpected space before @, invalid JSON escape \q, empty/newline/NUL/tab/bidi U+202E/line-separator U+2028/paragraph-separator U+2029 workspaces, and checkout-escaping publish: getsentry/toolkit/../other@1.2.3.src/modules/__tests__/publish-workflow.js reads .github/workflows/publish.yml, extracts and runs the Set targets Bash script in temporary directories, and verifies ordering checkout β location resolution β state setup β publish; verifies exact revision checkout, getsentry/craft:latest workspace list, absence of getsentry/craft:2.31.0, resolved location inputs, and craft publish ... --rev ....publish-workflow.js state-file tests expect root release (path: ".", repo: "sentry", version: "21.3.1") to produce publish-state-getsentry-sentry-c232c383e26f-21.3.1.json, and workspace release (path: "./cli", repo: "toolkit", version: "1.2.3", workspace: "cli") to produce publish-state-getsentry-toolkit-21cf7beaeda4-workspace-Y2xp-1.2.3.json; both state contents are {"published":{"github":true}}.src/modules/update-issue.js bug fix: state-file lookup previously derived an insecure/ambiguous ${GITHUB_WORKSPACE}/__repo__/.craft-publish-${version}.json; it now receives explicit stateFilePath, returns without reading when absent/nonexistent, and updateIssue() supplies process.env.CRAFT_STATE_FILE_PATH. This binds issue updates to the secure workflow-generated state-file path and supports target setup being skipped.update-issue tests set CRAFT_STATE_FILE_PATH to .craft-state/craft/publish-state-getsentry-sentry-c232c383e26f-21.3.1.json, expect exactly that existsSync() path, and verify no state-file read or issue update when CRAFT_STATE_FILE_PATH is unset.