Dashboard › publish › Distillation
0688a350-43c7-4820-bba3-b9ff958b3287["lore_tm_v1_SaUFkmbJSQVU-RL0JsqdmcEkNq9xPJScWemEJn-KAR4","lore_tm_v1_aCKB-SbKE0t4_J86-WzebAZJUvUV97l1QbGftvJ1o7Y","lore_tm_v1_c5LjrnpFdtgrMjnS73kl4MGBpo4b3Lxz-1EkOJeKOSg","lore_tm_v1_e4lCItlygJBpOdyPnjTkmxIHjh6jXjM2_-2bsMHqWdw","lore_tm_v1_belKKQ3kbRlt7JVCUlG3mi2wokq0fpwJn_omy_lb9Zs","lore_tm_v1_jNr2wYLL65ZY7GL4eJqnc7wMkwlh9DtN3EVyBISfn-4","lore_tm_v1_cEyxGIwZmaLVPqXCuFxKWM9oF5Qdd91AsGeZJ9ygOOI","lore_tm_v1_tyOmy6coSCLQGxfdQjoq58agqa4qrHBR3RdAQqBQwkI","lore_tm_v1_GZgykV6IOTof1T8AMZeR4SwvnPpqPsDUEmQORpexRns"]
Date: September 10, 2026
src/config.ts defines CONFIG_FILE_NAME = '.craft.yml' and DEFAULT_RELEASE_BRANCH_NAME = 'release'; getConfigFilePath() throws ConfigurationError with Cannot find Craft configuration file. Have you added ".craft.yml" to your project? when discovery fails.src/config.ts caches parsed configuration in _configCache; getConfiguration(clearCache = false) returns the cache unless explicitly cleared.getVersioningPolicy() supports 'auto', 'manual', and 'calver'; absent explicit configuration, it defaults to 'auto' when minVersion >= 2.14.0, otherwise 'manual' for backward compatibility.createGitClient(configDir), prefers the origin remote and otherwise uses the first remote, parsing its push URL or fetch URL with GitUrlParse; remote lookup failures are logged with logger.warn('Error when trying to get git remotes: ', error).github targets have conflicting tagPrefix values, configuration uses the first prefix and warns that independently versioned monorepo products should have separate .craft.yml files, each with one github target and its own tagPrefix.getChangelogConfig() normalizes both legacy changelogPolicy and the newer changelog object, emitting a deprecation warning for changelogPolicy.getNoMergeConfig() resolves noMerge in this order: 1. explicit .craft.yml noMerge; 2. auto-detection of compiled GitHub Actions with a dist/ folder; 3. default false, meaning merge the release branch. Compiled actions avoid merging release branches because generated dist/ content needed on release branches could overwrite a clean main branch.expandWorkspaceTargets(targets: TargetConfig[]): Promise<TargetConfig[]> lazily imports target lookup to avoid the circular dependency config -> targets -> registry -> utils/registry -> symlink -> version -> config; it expands target classes exposing a static expand method, including npm-workspace targets.src/modules/ci-poller-input.js changed getCiPollerInput() to accept labels; it computes resolvedIssueBody after an optional revision replacement and emits requestDigest: requestDigest({ body: resolvedIssueBody, labels, title }), binding poller input to the exact title, labels, and effective issue body.src/modules/ci-poller-input.js still returns revision: currentRevision even when a replacement revision is supplied; only the optional returned issueBody uses updateReleaseRevision({ issueBody, repo, revision }).src/publish/resolve-ci-poller-input.js now passes labels: JSON.parse(process.env.PUBLISH_ISSUE_LABELS || "") into getCiPollerInput(), alongside PUBLISH_TITLE, PUBLISH_REVISION, and the issue body.src/modules/details-from-context.js added parsePublishTitle(title): it parses with parsePublishIssueTitle(), reconstructs the path as "." + titleDetails.path, and returns null on parsing failure or unless isPublishRepository(titleDetails.repo), isReleaseVersion(titleDetails.version), and isPublishPath(path) all pass; the function is exported.src/publish/discover-location.js pins workspace discovery to CRAFT_IMAGE = "getsentry/craft@sha256:9a4a5d5efa44a00c2215078ead39800d4aaa5a97908b94f45a64d7d506d6e14b" instead of getsentry/craft:latest; Docker invokes that image with workspace list.src/publish/discover-location.js requires Craft workspace discovery output to parse as JSON and be an array; either invalid JSON or a non-array throws Craft workspace discovery returned an invalid workspace list.src/publish/update-issue.js now wraps execution in async main(), parses process.env.PUBLISH_ARGS only when present, warns Could not parse publish inputs; skipping target update on invalid JSON, awaits updateIssue({ context, octokit, inputs }), executes only under require.main === module, sets process.exitCode = 1 after logging uncaught errors, and exports { main }.src/publish/__tests__/authorize-approval.js contains 8 authorization-entry-point tests: 1. exact allowlist paths load as getsentry/sentry-javascript and getsentry/objectstore/clients; 2. a successful GitHub write permission lookup for contractor produces authorized=true plus a <!-- publish-approval ... --> attestation; 3. requester contractor cannot approve their own release; 4. a live approval is rejected when body/labels differ from the accepted-label snapshot; 5. an allowlisted automated request by getsantry[bot], approved by sentry-internal-app[bot], is authorized when a github-actions[bot] request proof exists; 6. automated approval without that request proof is rejected; 7. direct approval by automated opener sentry-release-bot[bot] is rejected without fetching GitHub; 8. a GitHub permission lookup returning HTTP 404 fails closed with Could not retrieve contractor's permission for getsentry/sentry-javascript: GitHub returned 404 and writes no output.EXPECTED_REQUEST_DIGEST to requestDigest({ body: "Merge target: main", labels: [{ name: "accepted" }], title: issueTitle }), use issue number "123" and repository "getsentry/publish", and expect output at /tmp/github-output.src/publish/__tests__/record-auto-approval-attestation.js contains 3 tests: 1. recordAutoApprovalAttestation() binds getsantry[bot] to the live request and parses to { autoApprover, requestDigest, title }; 2. a changed author (contractor instead of getsantry[bot]) is rejected; 3. a changed opened-event snapshot ("old request" versus "changed request" plus dry-run) is rejected. Both rejection cases use The automated approval request changed before approval.src/publish/__tests__/record-ci-ready-attestation.js contains 4 tests: 1. an attestation binds accepted actor contractor, accepted event ID "100", and CI-ready actor sentry-internal-app[bot] to the request digest/title; 2. a changed issue title is rejected; 3. a re-approval changing accepted event ID from "100" to "200" is rejected; 4. a different poller snapshot ("old revision"/accepted versus "new revision"/accepted+dry-run) is rejected. All three rejection scenarios use The approval changed before CI could be marked ready.src/publish/__tests__/current-accepted-event.js verifies getCurrentAcceptedEvent() selects the latest accepted-label eventβevent ID "200" over "100" for actor contractorβand rejects an empty event list with The issue has no current accepted label event.src/libs/github.js exports getGitHubToken(), which returns process.env.GITHUB_TOKEN or throws No "GITHUB_TOKEN" environment variable found. Please ensure the workflow is configured correctly.src/modules/post-workflow-details.js posts Publishing: [run#${run_id}](${workflowInfo.html_url}) to the current issue after retrieving the workflow run through octokit.rest.actions.getWorkflowRun().src/modules/process-end-state.js retrieves workflow-run details, posts an end-state issue comment, closes the issue only when status === "success", and then reports the release session to Sentry.githubIssueComment() in src/modules/process-end-state.js maps statuses as follows: 1. "failure" β Failed to publish. with run logs and a branch-deletion link; 2. "cancelled" β Publish workflow cancelled. with the same run-log/branch-deletion guidance; 3. "success" β Published successfully: [run#${run_id}](${workflowInfo.html_url}); unknown values throw Unknown status: '${status}'.reportSession() initializes Sentry with dsn: process.env.SENTRY_DSN and release: "${repo}@${version}", tags repository, stores issue_number and inputs in release context, captures a status-specific message/severity, starts and ends a session, then awaits Sentry.close().sentryInfoFromDetails() maps "failure" to message Release failed: ${repo}, severity "error", session status "crashed"; "cancelled" to Release cancelled: ${repo}, severity "warn", status "crashed"; and "success" to Release succeeded: ${repo}, severity "info", status "ok".