DashboardcraftSession 000yOoAdhHVY

Session 000yOoAdhHVY

Full ID: 000yOoAdhHVYRdj4g
Messages: 69
Distillations: 8
Time range: 2026-08-29 08:38:33 — 2026-08-29 08:50:12

Conversation (69 messages)

Perform a rigorous read-only adversarial review of the uncommitted compact workspace-title contract across BOTH worktrees. Do not edit files or run destructive commands. Worktrees: Craft /home/byk/Code/getsentry/craft-workspace-action-propagation and Publish /home/byk/Code/getsentry/publish-workspace-acceptance. Review exact current diffs against base, relevant full source/tests/workflows. Verify: (1) title grammar/parser and legacy JSON-qualified title compatibility; (2) compact single-segment workspace classification happens only after checkout at exact CI-approved SHA from the View check runs link; (3) CI poller actually adds ci-ready and updates link to approved SHA; (4) same resolved revision/path/workspace governs checkout, state filename/cwd, CRAFT_WORKSPACE, and craft publish --rev; (5) safe ASCII exact workspace identifiers, no normalization or option injection, no workspace + non-root path, no workspace github.projectPath ambiguity; (6) detached SHA checkout works; (7) secure XDG state and checkout repo state identity parity; (8) generated Peggy parser/reproducibility/dependency lock correctness; (9) legacy workflows are not unnecessarily blocked on the new Craft image; (10) deployability: immutable craft:2.31.0 availability and safe gate. Report only concrete findings ordered CRITICAL/MAJOR/MINOR with precise file:line evidence and tests. End MERGE or DO-NOT-MERGE. Do not rubber-stamp.

gateway · 2026-08-29 08:38:33
result
<path>/home/byk/Code/getsentry</path>
<type>directory</type>
<entries>
cli-api-1423/
cli-wt/
cli/
codecov-action/
craft-vercel-prebuilt-output/
craft-vercel-project-config/
craft-workspace-action-propagation/
craft-workspaces-schema/
craft/
devinfra-coder-infra/
devinfra-deployment-service/
getsentry/
ops/
package_grant_publish_repo/
publish-workspace-acceptance/
publish/
security-as-code/
self-hosted/
sentry-api-schema/
sentry-docs/
sentry-forge/
sentry-go/
sentry-javascript/
sentry-orbital/
sentry-python/
sentry-release-registry/
sentry-wizard/
sentry/
snuba/
spotlight/
sqlish/
static-sites/
stripe-app/
symbolic/

(34 entries)
</entries>
gateway · 2026-08-29 08:38:41
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation</path>
<type>directory</type>
<entries>
.craft.yml
.dockerignore
.eslintcache
.git
.github/
.gitignore
.lore.md
.nojekyll
.npmignore
.prettierignore
.prettierrc.yml
.tsbuildinfo
.vscode/
action.yml
AGENTS.md
blog-post-draft.md
build.mjs
CHANGELOG.md
CONTRIBUTING.md
dist/
Dockerfile
docs/
eslint.config.mjs
img/
LICENSE
node_modules/
package.json
pnpm-lock.yaml
README.md
src/
tsconfig.build.json
tsconfig.json
vitest.config.mts

(33 entries)
</entries>
gateway · 2026-08-29 08:39:38
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance</path>
<type>directory</type>
<entries>
.eslintrc.js
.git
.github/
.gitignore
AGENTS.md
auto-approve-repos.txt
docs/
LICENSE
node_modules/
package.json
pnpm-lock.yaml
README.md
scripts/
src/
vitest.config.js
yarn.lock

(16 entries)
</entries>
gateway · 2026-08-29 08:39:43
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/AGENTS.md</path>
<type>file</type>
<content>
1: # AGENTS.md
2: 
3: This file provides guidance for AI coding assistants working with the Craft codebase.
4: 
5: ## Package Management
6: 
7: - **Always use `pnpm`** for package management. Never use `npm` or `yarn`.
8: - Node.js version is managed by [Volta](https://volta.sh/) (currently v22.12.0).
9: - Install dependencies with `pnpm install --frozen-lockfile`.
10: 
11: ## Development Commands
12: 
13: | Command      | Description                                 |
14: | ------------ | ------------------------------------------- |
15: | `pnpm build` | Build the project (outputs to `dist/craft`) |
16: | `pnpm test`  | Run tests                                   |
17: | `pnpm lint`  | Run ESLint                                  |
18: | `pnpm fix`   | Auto-fix lint issues                        |
19: 
20: To manually test changes:
21: 
22: ```bash
23: pnpm build && ...
gateway · 2026-08-29 08:39:46
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/AGENTS.md</path>
<type>file</type>
<content>
1: # AGENTS.md - Coding Agent Guidelines
2: 
3: This document provides guidelines for AI coding agents working in this repository.
4: 
5: ## Project Overview
6: 
7: This is the **Sentry Publish Repository** - a GitHub Actions-based approval system for publishing releases across multiple Sentry projects using [Craft](https://github.com/getsentry/craft). It's a pure JavaScript (Node.js 24.0.0) project using CommonJS modules.
8: 
9: ## Build/Lint/Test Commands
10: 
11: ### Package Manager
12: 
13: - **Yarn 1.22.22** (classic) - Do NOT use npm
14: - Version management via Volta (pinned in package.json)
15: 
16: ### Commands
17: 
18: ```bash
19: # Install dependencies
20: yarn install
21: 
22: # Run all tests
23: yarn test
24: 
25: # Run tests in watch mode
26: yarn test:watch
27: 
28: # Run a single test file
29: yarn test src/modules/__tests__/update-issue.js
30: 
31: # Run tests ...
gateway · 2026-08-29 08:39:53
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/.git</path>
<type>file</type>
<content>
1: gitdir: /home/byk/Code/getsentry/craft/.git/worktrees/craft-workspace-action-propagation

(End of file - total 1 lines)
</content>

<system-reminder>
Instructions from: /home/byk/Code/getsentry/craft-workspace-action-propagation/AGENTS.md
# AGENTS.md

This file provides guidance for AI coding assistants working with the Craft codebase.

## Package Management

- **Always use `pnpm`** for package management. Never use `npm` or `yarn`.
- Node.js version is managed by [Volta](https://volta.sh/) (currently v22.12.0).
- Install dependencies with `pnpm install --frozen-lockfile`. ...
gateway · 2026-08-29 08:39:58
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/.git</path>
<type>file</type>
<content>
1: gitdir: /home/byk/Code/getsentry/publish/.git/worktrees/publish-workspace-acceptance

(End of file - total 1 lines)
</content>
gateway · 2026-08-29 08:40:08
result
 M action.yml
 M docs/src/content/docs/targets/github.md
 M src/__tests__/action.test.ts
 M src/__tests__/config.test.ts
 M src/commands/__tests__/publish.test.ts
 M src/commands/publish.ts
 M src/config.ts
 M src/index.ts
 M src/schemas/project_config.ts
?? src/commands/workspace.ts
?? src/commands/workspace_cmds/

-- branch/base --
feat/workspace-action-propagation
6dae341f9bc1378abde7a9022108caded2d22226
8cc54254f2e9489abbfdc028df15e7effbbc6bb8
8cc54254f2e9489abbfdc028df15e7effbbc6bb8

-- diff stat vs master --
 .github/workflows/release.yml            |   9 +
 CHANGELOG.md                             |  26 +++
 action.yml                               |  33 ++-
 docs/package.json                        |   4 +-
 docs/pnpm-lock.yaml                      |  24 +-
 docs/src/content/docs/targets/github.md  |  36 ++-
 docs/src/content/docs/targets/vercel.md  |   6 +-
 package.json                             |  16 +-
 pnpm-lock.yaml                           | 382 ...
gateway · 2026-08-29 08:40:13
result
 M .github/workflows/publish.yml
 M docs/publish-issue-format.md
 M package.json
 M src/modules/__tests__/publish-workflow.js
 M src/modules/details-from-context.js
 M src/modules/post-workflow-details.js
 M src/publish/inputs.js
 M yarn.lock
?? pnpm-lock.yaml
?? scripts/
?? src/modules/__tests__/publish-location.js
?? src/modules/__tests__/release-revision.js
?? src/modules/publish-issue-title.js
?? src/modules/publish-issue-title.peggy
?? src/modules/publish-location.js
?? src/modules/release-revision.js
?? src/publish/resolve-location.js
?? src/publish/resolve-release-revision.js

-- branch/base --
feat/workspace-acceptance
b658ffa0299fedf78c9dd9a2121cd740691ca157
master
fatal: ambiguous argument 'master': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
gateway · 2026-08-29 08:40:19
result
-- refs --
error: unknown option `remotes'
usage: git show-ref [--head] [-d | --dereference]
                    [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]
                    [--heads] [--] [<pattern>...]
   or: git show-ref --verify [-q | --quiet] [-d | --dereference]
                    [-s | --hash[=<n>]] [--abbrev[=<n>]]
                    [--] [<ref>...]
   or: git show-ref --exclude-existing[=<pattern>]
   or: git show-ref --exists <ref>

    --[no-]tags           only show tags (can be combined with heads)
    --[no-]heads          only show heads (can be combined with tags)
    --[no-]exists         check for reference existence without resolving
    --[no-]verify         stricter reference checking, requires exact ref path
    --[no-]head           show the HEAD reference, even if it would be filtered out
    -d, --[no-]dereference
                          dereference tags into object IDs
    -s, --[no-]hash[=<n>] only show SHA1 hash using <n> digits
    ...
gateway · 2026-08-29 08:40:25
result
-- refs --
chore/fix-security-advisories 2513c782a5a54da5921a87ce52fc357a78c8e263
feat/workspace-acceptance b658ffa0299fedf78c9dd9a2121cd740691ca157
fix/add-workflow-permissions a58b7212cd8886308be5d742885271ebda2f81e7
main 83d210b29553ea6f4d97508821724a834c43856e
opencode/tidy-orchid 83d210b29553ea6f4d97508821724a834c43856e
security/dual-write-publish-state 83d9383368ee750b828da30943768a1956966e4e
security/remove-legacy-publish-state-write 1b279b935f2213dac175660877449772a2342dbb
origin 83d210b29553ea6f4d97508821724a834c43856e
origin/feat/ci-poller-variable-gate 6658aa8c3e2b9c8eb3bf109deea22829f467cae4
origin/feat/ci-status-poller 2c7373d7bb2db42781b44ea89d9ed784dc165918
origin/feat/workspace-acceptance b658ffa0299fedf78c9dd9a2121cd740691ca157
origin/fix/ci-poller-gh-token 9ad4740dbc053a3fe240f9f8c8128184f6e534a9
origin/fix/ci-poller-variable-auth 2b8fda0274845e73aa8d1ee1b8f3a2ccde5a17c0
origin/fix/react-native-release-8-14-craft-config ...
gateway · 2026-08-29 08:40:33
result
...output truncated...

Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_04cad8080001fU5phjX53iObRK

         # We avoid GitHub search API to bypass indexing delays and query syntax edge cases.
diff --git a/docs/package.json b/docs/package.json
index d073084..35d43bd 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -18,12 +18,12 @@
       "h3": "^1.15.6",
       "devalue": "^5.8.1",
       "rollup": "^4.59.0",
-      "svgo": "^4.0.1",
+      "svgo": "^4.0.2",
       "postcss": "^8.5.18",
       "smol-toml": "^1.6.1",
       "defu": "^6.1.5",
       "vite": "^8.0.0",
-      "js-yaml": "^4.2.0"
+      "js-yaml": "^4.3.1"
     }
   }
 }
diff --git a/docs/src/content/docs/targets/vercel.md b/docs/src/content/docs/targets/vercel.md
index 51e170a..3e7b81a 100644
--- a/docs/src/content/docs/targets/vercel.md
+++ b/docs/src/content/docs/targets/vercel.md
@@ -13,6 +13,8 @@ The target extracts a ZIP artifact and deploys it via the Vercel deploy API (usi
 ...
gateway · 2026-08-29 08:40:41
result
<path>/home/byk/.local/share/opencode/tool-output/tool_04cad8080001fU5phjX53iObRK</path>
<type>file</type>
<content>
1: -- recent commits --
2: 6dae341 (HEAD -> feat/workspace-action-propagation, origin/feat/workspace-action-propagation) feat: propagate release workspaces
3: 21270a1 (origin/master, origin/HEAD) feat(config): add release workspaces
4: 32f5462 fix(git): prevent fatal error for missing 'origin' remote (#871)
5: 5d0ec43 fix(registry): retry registry push with backoff on concurrent updates (#870)
6: 35e8063 meta: Bump new development version
7: b2524ef Merge branch 'release/2.30.1'
8: cd1e829 (tag: 2.30.1) release: 2.30.1
9: 06180e3 fix(vercel): pass prebuilt output directory
10: 29ad5c3 meta: Bump new development version
11: c02eb03 Merge branch 'release/2.30.0'
12: c79aff0 (tag: 2.30.0) release: 2.30.0
13: 76adb48 feat(vercel): allow project ID in target config (#867)
14: 78bc73b meta: Bump new development version
15: be1613d Merge branch 'release/2.29.0'
16: 50bb44a ...
gateway · 2026-08-29 08:40:46
result
<path>/home/byk/.local/share/opencode/tool-output/tool_04cad8080001fU5phjX53iObRK</path>
<type>file</type>
<content>
1160: +        'separate .craft.yml), each with a single "github" target and its own ' +
1161: +        '"tagPrefix".',
1162:      );
1163:    }
1164:  
1165: diff --git a/src/index.ts b/src/index.ts
1166: index 9dfec11..ca25418 100644
1167: --- a/src/index.ts
1168: +++ b/src/index.ts
1169: @@ -10,9 +10,14 @@ import {
1170:    sanitizeDynamicLinkerEnv,
1171:    warnIfCraftEnvFileExists,
1172:  } from './utils/env';
1173: -import { envToBool, setGlobals } from './utils/helpers';
1174: +import {
1175: +  envToBool,
1176: +  setGlobals,
1177: +  extractWorkspaceSelection,
1178: +} from './utils/helpers';
1179:  import { getPackageVersion } from './utils/version';
1180:  import { withTracing } from './utils/tracing';
1181: +import { setActiveWorkspace } from './config';
1182:  
1183:  // Commands
1184:  import * as prepare from './commands/prepare';
1185: @@ -83,6 +88,15 @@ ...
gateway · 2026-08-29 08:40:53
result
-- commits since main --
b658ffa (HEAD -> feat/workspace-acceptance, origin/feat/workspace-acceptance) fix: validate publish workspace JSON
33de3f1 feat: accept workspace publish requests
-- branch diff excluding lockfiles --
diff --git a/.github/workflows/cocoapods-keepalive.yml b/.github/workflows/cocoapods-keepalive.yml
index 21c0696..9c11b0e 100644
--- a/.github/workflows/cocoapods-keepalive.yml
+++ b/.github/workflows/cocoapods-keepalive.yml
@@ -1,4 +1,4 @@
-name: "CocoaPods Token Keep-Alive"
+name: CocoaPods Token Keep-Alive
 
 on:
   schedule:
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index cff6bc3..c283b79 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -184,12 +184,14 @@ jobs:
           fetch-depth: 0
 
       - name: Set targets
+        id: craft-state
         shell: bash
         if: fromJSON(steps.inputs.outputs.result).targets
         env:
           CRAFT_PUBLISH_REPO: ${{ ...
gateway · 2026-08-29 08:41:04
result
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/release-revision.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-location.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-title.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-title.peggy
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/update-issue.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/process-end-state.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/post-workflow-details.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/details-from-context.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/release-revision.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-location.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-workflow.js
/home/byk...
gateway · 2026-08-29 08:41:09
result
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/resolve-release-revision.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/resolve-location.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/update-issue.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/post-workflow-details.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/post-result.js
/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/inputs.js
gateway · 2026-08-29 08:41:21
result
/home/byk/Code/getsentry/publish-workspace-acceptance/scripts/generate-publish-issue-title-parser.js
gateway · 2026-08-29 08:41:25
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-title.peggy</path>
<type>file</type>
<content>
1: {
2:   function join(characters) {
3:     return characters.join("");
4:   }
5: }
6: 
7: // Canonical grammar for publish issue titles. A path suffix is syntactic only:
8: // the controller resolves a single segment as a workspace after checking out
9: // the CI-approved revision.
10: PublishIssueTitle
11:   = "publish: " "getsentry/"? repo:Repository path:Path? workspace:LegacyWorkspace? "@" version:Version !. {
12:       return {
13:         repo,
14:         path: path || "",
15:         version,
16:         ...(workspace ? { workspace } : {}),
17:       };
18:     }
19: 
20: Repository
21:   = characters:RepositoryCharacter+ { return join(characters); }
22: 
23: RepositoryCharacter
24:   = [A-Za-z0-9_.-]
25: 
26: Path
27:   = segments:("/" segment:PathSegment { return `/${segment}`; })+ { return join(segments); }
28: 
29: PathSegment
30:   = ...
gateway · 2026-08-29 08:41:29
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-issue-title.js</path>
<type>file</type>
<content>
1: /* eslint-disable */
2: // @generated by Peggy 5.1.0.
3: //
4: // https://peggyjs.org/
5: 
6: "use strict";
7: 
8: class peg$SyntaxError extends SyntaxError {
9:   constructor(message, expected, found, location) {
10:     super(message);
11:     this.expected = expected;
12:     this.found = found;
13:     this.location = location;
14:     this.name = "SyntaxError";
15:   }
16: 
17:   format(sources) {
18:     let str = "Error: " + this.message;
19:     if (this.location) {
20:       let src = null;
21:       const st = sources.find((s) => s.source === this.location.source);
22:       if (st) {
23:         src = st.text.split(/\r\n|\n|\r/g);
24:       }
25:       const s = this.location.start;
26:       const offset_s =
27:         this.location.source &&
28:         typeof this.location.source.offset === "function"
29:           ? ...
gateway · 2026-08-29 08:41:34
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/publish-location.js</path>
<type>file</type>
<content>
1: function needsWorkspaceDiscovery({ path, workspace }) {
2:   return !workspace && /^\.\/[A-Za-z0-9_.-]+$/.test(path);
3: }
4: 
5: function resolvePublishLocation({ path, workspace, workspaceNames }) {
6:   if (workspace) {
7:     return { path, workspace };
8:   }
9: 
10:   if (!needsWorkspaceDiscovery({ path, workspace })) {
11:     return { path };
12:   }
13: 
14:   if (!workspaceNames.every(isWorkspaceName)) {
15:     throw new Error(
16:       "Craft workspace discovery returned an invalid workspace list."
17:     );
18:   }
19: 
20:   const segments = path.slice(2).split("/");
21:   if (
22:     path.startsWith("./") &&
23:     segments.length === 1 &&
24:     workspaceNames.includes(segments[0])
25:   ) {
26:     return { path: ".", workspace: segments[0] };
27:   }
28: 
29:   return { path };
30: }
31: 
32: function isWorkspaceName(name) {
33:   ...
gateway · 2026-08-29 08:41:39
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/release-revision.js</path>
<type>file</type>
<content>
1: const CHECK_RUNS_LINK =
2:   /^- \[View check runs\]\(https:\/\/github\.com\/getsentry\/(?<repo>[A-Za-z0-9_.-]+)\/commit\/(?<revision>[0-9a-f]{40})\/checks\/?\)\r?$/m;
3: 
4: function getReleaseRevision({ issueBody, repo }) {
5:   const match = issueBody.match(CHECK_RUNS_LINK);
6:   if (!match?.groups || match.groups.repo !== repo) {
7:     throw new Error(
8:       `Expected a View check runs link for getsentry/${repo} in the publish issue body.`
9:     );
10:   }
11: 
12:   return match.groups.revision;
13: }
14: 
15: module.exports = { getReleaseRevision };

(End of file - total 15 lines)
</content>
gateway · 2026-08-29 08:41:44
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/resolve-release-revision.js</path>
<type>file</type>
<content>
1: const core = require("@actions/core");
2: const { getReleaseRevision } = require("../modules/release-revision");
3: 
4: function resolveReleaseRevision() {
5:   const { repo } = JSON.parse(process.env.PUBLISH_ARGS || "");
6:   core.setOutput(
7:     "revision",
8:     getReleaseRevision({
9:       issueBody: process.env.PUBLISH_ISSUE_BODY || "",
10:       repo,
11:     })
12:   );
13: }
14: 
15: resolveReleaseRevision();

(End of file - total 15 lines)
</content>
gateway · 2026-08-29 08:41:48
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/resolve-location.js</path>
<type>file</type>
<content>
1: const core = require("@actions/core");
2: const {
3:   needsWorkspaceDiscovery,
4:   resolvePublishLocation,
5: } = require("../modules/publish-location");
6: 
7: function resolveLocation() {
8:   const input = JSON.parse(process.env.PUBLISH_ARGS || "");
9:   const workspaceNames = needsWorkspaceDiscovery(input)
10:     ? JSON.parse(process.env.CRAFT_WORKSPACE_NAMES || "")
11:     : [];
12: 
13:   if (!Array.isArray(workspaceNames)) {
14:     throw new Error(
15:       "Craft workspace discovery returned an invalid workspace list."
16:     );
17:   }
18: 
19:   core.setOutput(
20:     "result",
21:     resolvePublishLocation({
22:       path: input.path,
23:       workspace: input.workspace,
24:       workspaceNames,
25:     })
26:   );
27: }
28: 
29: resolveLocation();

(End of file - total 29 lines)
</content>
gateway · 2026-08-29 08:41:53
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/scripts/generate-publish-issue-title-parser.js</path>
<type>file</type>
<content>
1: const fs = require("fs");
2: const path = require("path");
3: const peggy = require("peggy");
4: const prettier = require("prettier");
5: 
6: const grammarPath = path.join(
7:   __dirname,
8:   "..",
9:   "src",
10:   "modules",
11:   "publish-issue-title.peggy"
12: );
13: const outputPath = path.join(
14:   __dirname,
15:   "..",
16:   "src",
17:   "modules",
18:   "publish-issue-title.js"
19: );
20: const grammar = fs.readFileSync(grammarPath, "utf8");
21: const parser = peggy.generate(grammar, {
22:   format: "commonjs",
23:   grammarSource: "publish-issue-title.peggy",
24:   output: "source",
25: });
26: 
27: fs.writeFileSync(
28:   outputPath,
29:   prettier.format(`/* eslint-disable */\n${parser}`, { filepath: outputPath })
30: );

(End of file - total 30 lines)
</content>
gateway · 2026-08-29 08:41:58
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-location.js</path>
<type>file</type>
<content>
1: import { expect, test } from "vitest";
2: 
3: const {
4:   needsWorkspaceDiscovery,
5:   resolvePublishLocation,
6: } = require("../publish-location.js");
7: 
8: test.each([
9:   [{ path: "./cli" }, true],
10:   [{ path: "./packages/cli" }, false],
11:   [{ path: "." }, false],
12:   [{ path: "./cli", workspace: "cli" }, false],
13: ])("workspace discovery is %s for %j", (input, expected) => {
14:   expect(needsWorkspaceDiscovery(input)).toBe(expected);
15: });
16: 
17: test("classifies an exact one-segment workspace without normalizing it", () => {
18:   expect(
19:     resolvePublishLocation({
20:       path: "./CLI",
21:       workspaceNames: ["cli", "CLI"],
22:     })
23:   ).toStrictEqual({ path: ".", workspace: "CLI" });
24: });
25: 
26: test("keeps a non-workspace suffix as a checkout path", () => {
27:   expect(
28:     ...
gateway · 2026-08-29 08:42:04
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/release-revision.js</path>
<type>file</type>
<content>
1: import { expect, test } from "vitest";
2: 
3: const { getReleaseRevision } = require("../release-revision.js");
4: 
5: const REVISION = "7e5ca7ed5581552de066e2a8bc295b8306be38ac";
6: 
7: test("gets the CI-approved revision for the publish repository", () => {
8:   expect(
9:     getReleaseRevision({
10:       repo: "toolkit",
11:       issueBody: `Quick links:
12: - [View check runs](https://github.com/getsentry/toolkit/commit/${REVISION}/checks/)`,
13:     })
14:   ).toBe(REVISION);
15: });
16: 
17: test("gets the CI-approved revision from a CRLF issue body", () => {
18:   expect(
19:     getReleaseRevision({
20:       repo: "toolkit",
21:       issueBody: `Quick links:\r\n- [View check runs](https://github.com/getsentry/toolkit/commit/${REVISION}/checks/)\r\n`,
22:     })
23:   ).toBe(REVISION);
24: });
25: 
26: test("rejects a check-runs link ...
gateway · 2026-08-29 08:42:10
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/action.yml</path>
<type>file</type>
<content>
1: name: 'Craft Prepare Release'
2: description: 'Prepare a new release using Craft'
3: 
4: inputs:
5:   version:
6:     description: >
7:       Version to release. Can be a semver string (e.g., "1.2.3"),
8:       a bump type ("major", "minor", "patch"), or "auto" for automatic detection.
9:     required: false
10:   merge_target:
11:     description: Target branch to merge into. Uses the default branch as a fallback. ...
gateway · 2026-08-29 08:42:21
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/schemas/project_config.ts</path>
<type>file</type>
<content>
1: import { z } from 'zod';
2: 
3: /**
4:  * DEPRECATED: Use changelog.policy instead. Different policies for changelog management
5:  */
6: export const enum ChangelogPolicy {
7:   Auto = 'auto',
8:   Simple = 'simple',
9:   None = 'none',
10: }
11: 
12: /**
13:  * Name of the status provider
14:  */
15: export const enum StatusProviderName {
16:   GitHub = 'github',
17: }
18: 
19: /**
20:  * Name of the artifact provider
21:  */
22: export const enum ArtifactProviderName {
23:   GCS = 'gcs',
24:   GitHub = 'github',
25:   None = 'none',
26: }
27: 
28: /**
29:  * Default versioning policy when no version argument is provided. ...
gateway · 2026-08-29 08:42:25
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/config.ts</path>
<type>file</type>
<content>
1: import { existsSync, lstatSync, readFileSync } from 'fs';
2: import path from 'path';
3: 
4: import { load } from 'js-yaml';
5: import GitUrlParse from 'git-url-parse';
6: import { createGitClient } from './utils/git';
7: import { ZodError } from 'zod';
8: 
9: import { logger } from './logger';
10: import {
11:   CraftProjectConfig,
12:   CraftProjectConfigSchema,
13:   GitHubGlobalConfig,
14:   ArtifactProviderName,
15:   StatusProviderName,
16:   TargetConfig,
17:   ChangelogPolicy,
18:   VersioningPolicy,
19:   Workspace,
20: } from './schemas/project_config';
21: import { ConfigurationError } from './utils/errors';
22: import { isCompiledGitHubAction } from './utils/detection';
23: import {
24:   getPackageVersion,
25:   parseVersion,
26:   versionGreaterOrEqualThan,
27:   SemVer,
28: } from './utils/version';
29: // Note: We import getTargetByName lazily in ...
gateway · 2026-08-29 08:42:31
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/workspace.ts</path>
<type>file</type>
<content>
1: import { Argv, CommandBuilder } from 'yargs';
2: 
3: import * as list from './workspace_cmds/list';
4: 
5: export const command = ['workspace <command>'];
6: export const description = 'Manage release workspaces';
7: 
8: export const builder: CommandBuilder = (yargs: Argv) =>
9:   yargs.demandCommand().command(list);
10: 
11: export const handler = (): void => {
12:   /* pass */
13: };

(End of file - total 13 lines)
</content>
gateway · 2026-08-29 08:42:35
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/workspace_cmds/list.ts</path>
<type>file</type>
<content>
1: import { getWorkspaceNames } from '../../config';
2: import { formatJson } from '../../utils/strings';
3: 
4: export const command = ['list'];
5: export const description = 'List defined release workspaces as a JSON array';
6: 
7: export function handler(): void {
8:   console.log(formatJson(getWorkspaceNames()));
9: }

(End of file - total 9 lines)
</content>
gateway · 2026-08-29 08:42:42
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/index.ts</path>
<type>file</type>
<content>
1: #!/usr/bin/env node
2: // Import Sentry instrumentation first, before any other code
3: import './instrument';
4: 
5: import isCI from 'is-ci';
6: import yargs from 'yargs';
7: 
8: import { logger, LogLevel } from './logger';
9: import {
10:   sanitizeDynamicLinkerEnv,
11:   warnIfCraftEnvFileExists,
12: } from './utils/env';
13: import {
14:   envToBool,
15:   setGlobals,
16:   extractWorkspaceSelection,
17: } from './utils/helpers';
18: import { getPackageVersion } from './utils/version';
19: import { withTracing } from './utils/tracing';
20: import { setActiveWorkspace } from './config';
21: 
22: // Commands
23: import * as prepare from './commands/prepare';
24: import * as publish from './commands/publish';
25: import * as targets from './commands/targets';
26: import * as config from './commands/config';
27: import * as artifacts from './commands/artifacts';
28: ...
gateway · 2026-08-29 08:42:47
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/helpers.ts</path>
<type>file</type>
<content>
1: import { appendFileSync, mkdirSync, writeFileSync } from 'fs';
2: import path from 'path';
3: import { parseArgs } from 'node:util';
4: 
5: import prompts from 'prompts';
6: import { logger, LogLevel, setLevel } from '../logger';
7: 
8: /**
9:  * Maximum size (in bytes) for step output values passed through GITHUB_OUTPUT.
10:  * Values exceeding this are truncated to avoid E2BIG errors when GitHub Actions
11:  * expands them into environment variables for subsequent steps.
12:  *
13:  * 64 KB is well under the ~2 MB ARG_MAX kernel limit and also under GitHub's
14:  * ~65 536-character issue body limit, so truncated changelogs still render. ...
gateway · 2026-08-29 08:42:55
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/__tests__/action.test.ts</path>
<type>file</type>
<content>
1: import {
2:   chmodSync,
3:   mkdtempSync,
4:   mkdirSync,
5:   readFileSync,
6:   rmSync,
7:   writeFileSync,
8: } from 'fs';
9: import { tmpdir } from 'os';
10: import { join } from 'path';
11: import { spawnSync } from 'child_process';
12: 
13: import { load } from 'js-yaml';
14: import { afterEach, expect, test } from 'vitest';
15: 
16: interface ActionStep {
17:   env?: Record<string, string>;
18:   name?: string;
19:   run?: string;
20: }
21: 
22: function getActionSteps(): ActionStep[] {
23:   const action = load(
24:     readFileSync(join(__dirname, '../../action.yml'), 'utf8'),
25:   ) as {
26:     runs?: { steps?: ActionStep[] };
27:   };
28:   return action.runs?.steps || [];
29: }
30: 
31: function getActionStep(name: string): ActionStep {
32:   const step = getActionSteps().find(step => step.name === name);
33:   if (!step?.run) {
34:     ...
gateway · 2026-08-29 08:43:03
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/__tests__/config.test.ts</path>
<type>file</type>
<content>
100:     expect(result.success).toBe(true);
101:   });
102: 
103:   test('schema rejects invalid minVersion', () => {
104:     const data = {
105:       minVersion: 'not-a-version',
106:     };
107: 
108:     const result = CraftProjectConfigSchema.safeParse(data);
109:     expect(result.success).toBe(false);
110:   });
111: });
112: 
113: describe('noMerge config', () => {
114:   test('parses configuration with noMerge: true', () => {
115:     const data = { noMerge: true };
116:     expect(validateConfiguration(data)).toEqual(data);
117:   });
118: 
119:   test('parses configuration with noMerge: false', () => {
120:     const data = { noMerge: false };
121:     expect(validateConfiguration(data)).toEqual(data);
122:   });
123: 
124:   test('noMerge defaults to undefined when not specified', () => {
125:     const data = { github: { owner: 'getsentry', ...
gateway · 2026-08-29 08:43:09
result
/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/ci-poller.yml
gateway · 2026-08-29 08:43:13
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/ci-poller.yml</path>
<type>file</type>
<content>
1: name: CI Status Poller
2: 
3: on:
4:   schedule:
5:     - cron: "*/5 * * * *"
6:   workflow_dispatch:
7:     inputs:
8:       attempt:
9:         description: Self-dispatch attempt counter (internal use)
10:         required: false
11:         default: "0"
12: 
13: permissions:
14:   contents: read
15:   issues: read
16: 
17: jobs:
18:   check-ci:
19:     runs-on: ubuntu-latest
20:     environment: production
21:     # Skip entirely (no runner provisioned) when there's nothing to check.
22:     # Set to "true" by ci-pending.yml, reset to "false" here when done.
23:     # Always allow workflow_dispatch for manual recovery.
24:     if: vars.CI_POLLER_HAS_PENDING == 'true' || github.event_name == 'workflow_dispatch'
25:     concurrency:
26:       group: ci-status-poller
27:       cancel-in-progress: false
28:     steps:
29:       # sentry-internal-app token ...
gateway · 2026-08-29 08:43:23
result
/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/test.yml
/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/publish.yml
/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/cocoapods-keepalive.yml
/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/ci-poller.yml
/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/auto-approve.yml
gateway · 2026-08-29 08:43:27
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/publish.yml</path>
<type>file</type>
<content>
1: name: Publish
2: on:
3:   issues:
4:     types: [labeled]
5: 
6: concurrency:
7:   # Use the issue title (e.g. "publish: getsentry/foo@1.2.3") so duplicate
8:   # issues for the same repo@version share a concurrency group.
9:   group: ${{ github.event.issue.title }}
10:   cancel-in-progress: false
11: 
12: permissions:
13:   contents: read
14:   issues: write
15:   packages: write
16: 
17: jobs:
18:   # When accepted is added to a publish issue:
19:   #   - Add ci-pending (and remove ci-failed if retrying)
20:   #   - Enable the poller via CI_POLLER_HAS_PENDING=true
21:   #   - Comment on the issue
22:   #   - Trigger the poller immediately so we don't wait for the next cron tick
23:   # The publish job below requires ci-ready, so it will not fire until the
24:   # poller flips ci-pending → ci-ready (which also prevents publishing without
25:   # CI ...
gateway · 2026-08-29 08:43:49
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/publishState.ts</path>
<type>file</type>
<content>
1: /**
2:  * Helpers for locating Craft's publish-state file in a path that is NOT
3:  * writable by the repository being published.
4:  *
5:  * Background: `craft publish` writes a small JSON file listing targets
6:  * that have completed so a resumed run can skip them. Before this module
7:  * existed, the file lived at `.craft-publish-<version>.json` in the
8:  * project's cwd. That path is inside the repository checkout, so any
9:  * committed file at the same path (or any earlier CI step) could
10:  * pre-populate the "published" set and trick Craft into silently
11:  * skipping targets.
12:  *
13:  * The file now lives under `$XDG_STATE_HOME/craft/` (falling back to
14:  * `$HOME/.local/state/craft/`). The filename is keyed on
15:  * owner, repo, a hash of cwd (to disambiguate monorepo subpaths), and
16:  * the version being published. ...
gateway · 2026-08-29 08:44:06
result
no such manifest: docker.io/getsentry/craft:2.31.0
craft:2.31.0 manifest: unavailable (exit 1)
gateway · 2026-08-29 08:44:20
result
No files found
gateway · 2026-08-29 08:44:25
result
Found 5 matches
/home/byk/Code/getsentry/publish-workspace-acceptance/yarn.lock:
  Line 538: "@peggyjs/from-mem@3.1.3":

  Line 540:   resolved "https://registry.yarnpkg.com/@peggyjs/from-mem/-/from-mem-3.1.3.tgz#2956c3c68ec2e08e55178049a327009ee61541b8"

  Line 1538: peggy@5.1.0:

  Line 1540:   resolved "https://registry.yarnpkg.com/peggy/-/peggy-5.1.0.tgz#8e2a681128cf776648417f60394a40b4a712f503"

  Line 1543:     "@peggyjs/from-mem" "3.1.3"
gateway · 2026-08-29 08:44:30
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/yarn.lock</path>
<type>file</type>
<content>
1518: path-exists@^4.0.0:
1519:   version "4.0.0"
1520:   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
1521:   integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
1522: 
1523: path-is-absolute@^1.0.0:
1524:   version "1.0.1"
1525:   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
1526:   integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
1527: 
1528: path-key@^3.1.0:
1529:   version "3.1.1"
1530:   resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
1531:   integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
1532: ...
gateway · 2026-08-29 08:44:39
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/test.yml</path>
<type>file</type>
<content>
1: name: Test
2: on:
3:   push:
4:     branches:
5:       - main
6:   pull_request:
7: 
8: permissions:
9:   contents: read
10: 
11: defaults:
12:   run:
13:     shell: bash
14: jobs:
15:   unit-test:
16:     runs-on: ubuntu-latest
17:     name: unit tests
18:     steps:
19:       - uses: actions/checkout@v6
20:       - uses: actions/setup-node@v6
21:         with:
22:           node-version: 24
23:       - uses: actions/cache@v4
24:         id: cache
25:         with:
26:           path: node_modules
27:           key: ${{ runner.os }}-node_modules-${{ hashFiles('package.json', 'yarn.lock') }}
28: 
29:       - name: Install Dependencies
30:         if: steps.cache.outputs.cache-hit != 'true'
31:         run: yarn install --frozen-lockfile
32: 
33:       - name: Test
34:         run: yarn test

(End of file - total 34 lines)
</content>
gateway · 2026-08-29 08:44:56
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/inputs.js</path>
<type>file</type>
<content>
1: const github = require('@actions/github');
2: const core = require('@actions/core');
3: const { detailsFromContext } = require('../modules/details-from-context');
4: 
5: async function inputs() {
6:     const result = await detailsFromContext({
7:       context: github.context,
8:     });
9:     core.setOutput('result', result);
10: }
11: 
12: 
13: inputs();

(End of file - total 13 lines)
</content>
gateway · 2026-08-29 08:45:02
result
Found 37 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts:
  Line 96:     .option('rev', {

  Line 99:         'Source revision (git SHA or tag) to publish (if not release branch head)',

  Line 147:   rev?: string;

  Line 218:  * @param revision Git commit SHA of the commit to be published

  Line 223:   revision: string,

  Line 235:       await target.publish(version, revision);

  Line 244:         revision,

  Line 251:  * Prints summary for the revision, including available artifacts

  Line 254:  * @param revision Git revision SHA

  Line 258:   revision: string,

  Line 260:   const artifacts = await artifactProvider.listArtifactsForRevision(revision);

  Line 289:         `No artifacts found for the revision, but your .craft.yml defines artifact patterns.\n\n` +

  Line 296:       logger.warn('No artifacts found for the revision.');

  Line 334:  * Check that for every provided pattern there's an artifact for the revision

  Line ...
gateway · 2026-08-29 08:45:09
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts</path>
<type>file</type>
<content>
48:   getDefaultBranch,
49:   isRepoDirty,
50:   findReleaseBranches,
51: } from '../utils/git';
52: import { withTracing } from '../utils/tracing';
53: import { buildReleaseCommandEnv } from '../utils/releaseCommandEnv';
54: import { getPublishStatePath } from '../utils/publishState';
55: 
56: /** Default path to post-release script, relative to project root */
57: const DEFAULT_POST_RELEASE_SCRIPT_PATH = join('scripts', 'post-release.sh');
58: 
59: export const command = ['publish NEW-VERSION'];
60: export const aliases = ['pp', 'publish'];
61: export const description = '🛫 Publish artifacts';
62: 
63: export const builder: CommandBuilder = (yargs: Argv) => {
64:   // Compute the allowed --target choices from the (workspace-resolved) config.
65:   // The active workspace is selected before parsing (see index.ts), so this
66:   // reflects the selected ...
gateway · 2026-08-29 08:45:14
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts</path>
<type>file</type>
<content>
590:   logger.info(`Running the post-release command...`);
591:   await spawnProcess(sysCommand as string, args as string[], {
592:     env: buildReleaseCommandEnv({ CRAFT_RELEASED_VERSION: newVersion }),
593:   });
594:   return true;
595: }
596: 
597: /**
598:  * Body of 'publish' command
599:  *
600:  * @param argv Command-line arguments
601:  */
602: export async function publishMain(argv: PublishOptions): Promise<any> {
603:   // Get publishing configuration
604:   const config = getConfiguration() || {};
605: 
606:   const newVersion = argv.newVersion;
607: 
608:   logger.info(`Publishing version: "${newVersion}"`);
609: 
610:   const git = await getGitClient();
611: 
612:   // Check for dirty repository state before any git operations
613:   if (argv.noGitChecks) {
614:     logger.info('Not checking the status of the local repository');
615:   } else ...
gateway · 2026-08-29 08:45:19
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts</path>
<type>file</type>
<content>
905:       logger.warn(lines.join('\n'));
906:     }
907: 
908:     // XXX(BYK): intentionally DO NOT await unlinking as we do not want
909:     // to block (both in terms of waiting for IO and the success of the
910:     // operation) finishing the publish flow on the removal of a temporary
911:     // file. If unlinking fails, we honestly don't care, at least to fail
912:     // the final steps. And it doesn't make sense to wait until this op
913:     // finishes then as nothing relies on the removal of this file.
914:     safeFs
915:       .unlink(publishStateFile)
916:       .catch((err: unknown) =>
917:         logger.trace("Couldn't remove publish state file: ", err),
918:       );
919:     logger.success(`Version ${newVersion} has been published!`);
920:   } else {
921:     const msg = [
922:       'The release branch was not merged because you published ...
gateway · 2026-08-29 08:45:27
result
Found 6 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/__tests__/publish.test.ts:
  Line 6:   getRevisionBranchName,

  Line 213: describe('getRevisionBranchName', () => {

  Line 219:     await expect(getRevisionBranchName(git, 'abc123')).resolves.toBe(

  Line 223:       'name-rev',

  Line 230:   test('allows a detached CI-approved revision', async () => {

  Line 235:     await expect(getRevisionBranchName(git, 'abc123')).resolves.toBe('');
gateway · 2026-08-29 08:45:31
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/__tests__/publish.test.ts</path>
<type>file</type>
<content>
1: import { vi, describe, test, expect, beforeEach, type Mock } from 'vitest';
2: import { join as pathJoin } from 'path';
3: import { spawnProcess, hasExecutable } from '../../utils/system';
4: import {
5:   getPublishStateGitHubConfig,
6:   getRevisionBranchName,
7:   runPostReleaseCommand,
8:   handleReleaseBranch,
9:   MergeConflictError,
10:   PushError,
11: } from '../publish';
12: import { getPublishStateFilename } from '../../utils/publishState';
13: import type { SimpleGit } from 'simple-git';
14: 
15: vi.mock('../../utils/system');
16: vi.mock('../../utils/git', () => ({
17:   getDefaultBranch: vi.fn().mockResolvedValue('main'),
18:   getGitClient: vi.fn(),
19:   isRepoDirty: vi.fn(),
20:   findReleaseBranches: vi.fn(),
21: }));
22: 
23: describe('runPostReleaseCommand', () => {
24:   const newVersion = '2.3.4';
25:   const ...
gateway · 2026-08-29 08:45:54
result
Found 17 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts:
  Line 630:   let checkoutTarget;

  Line 631:   let branchName;

  Line 634:     branchName = await getRevisionBranchName(git, rev);

  Line 635:     checkoutTarget = branchName || rev;

  Line 636:     logger.debug('Checking out revision', checkoutTarget);

  Line 637:     await git.checkout(checkoutTarget);

  Line 640:     branchName = `${branchPrefix}/${newVersion}`;

  Line 641:     checkoutTarget = branchName;

  Line 644:       logger.debug('Checking out release branch', branchName);

  Line 645:       await git.checkout(checkoutTarget);

  Line 653:         `Could not find the release branch "${branchName}".\n\n` +

  Line 833:   } else if (!branchName) {

  Line 847:         branchName,

  Line 858:         `Failed to merge release branch "${branchName}" into the target branch.`,

  Line 878:           `  2. Delete the release branch: git push ${argv.remote} --delete ...
gateway · 2026-08-29 08:46:04
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/.github/workflows/release.yml</path>
<type>file</type>
<content>
1: name: Release
2: concurrency: ${{ github.workflow }}-${{ github.ref }}
3: 
4: on:
5:   # For Craft's own releases (dogfooding)
6:   workflow_dispatch:
7:     inputs:
8:       version:
9:         description: Version to release
10:         required: true
11:         default: 'auto'
12:       force:
13:         description: Force a release even when there are release-blockers (optional)
14:         required: false
15:       workspace:
16:         description: Named Craft release workspace to prepare and publish
17:         required: false
18: 
19:   # For external repos to call this workflow
20:   workflow_call:
21:     inputs:
22:       version:
23:         description: Version to release (semver, bump type, or "auto")
24:         type: string
25:         required: false
26:       force:
27:         description: Force a release even when there are ...
gateway · 2026-08-29 08:46:16
result
getsentry/craft:2.30.1: available
getsentry/craft:latest: available
gateway · 2026-08-29 08:46:27
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/package.json</path>
<type>file</type>
<content>
1: {
2:   "name": "publish",
3:   "private": true,
4:   "version": "0.0.1",
5:   "description": "Approval-based publishing system for Sentry",
6:   "main": "index.js",
7:   "repository": "git@github.com:getsentry/publish.git",
8:   "author": "Sentry Open Source <oss@sentry.io>",
9:   "license": "Apache-2.0",
10:   "volta": {
11:     "node": "24.0.0",
12:     "yarn": "1.22.22"
13:   },
14:   "resolutions": {
15:     "undici": "^6.23.0"
16:   },
17:   "scripts": {
18:     "generate": "node scripts/generate-publish-issue-title-parser.js",
19:     "test": "yarn generate && vitest run",
20:     "test:watch": "vitest",
21:     "lint": "eslint src .github --ignore-pattern '!.github'",
22:     "prettier": "prettier --write src"
23:   },
24:   "devDependencies": {
25:     "eslint": "^8.9.0",
26:     "eslint-config-prettier": "^8.3.0",
27:     "eslint-plugin-yml": "^0.13.0",
28:     ...
gateway · 2026-08-29 08:46:31
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/pnpm-lock.yaml</path>
<type>file</type>
<content>
1: lockfileVersion: '9.0'
2: 
3: settings:
4:   autoInstallPeers: true
5:   excludeLinksFromLockfile: false
6: 
7: overrides:
8:   undici: ^6.23.0
9: 
10: importers:
11: 
12:   .:
13:     dependencies:
14:       '@actions/core':
15:         specifier: ^2.0.0
16:         version: 2.0.3
17:       '@actions/github':
18:         specifier: ^7.0.0
19:         version: 7.0.0
20:       '@sentry/node':
21:         specifier: ^10.0.0
22:         version: 10.71.0(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))
23:     devDependencies:
24:       eslint:
25:         specifier: ^8.9.0
26:         version: 8.57.1
27:       eslint-config-prettier:
28:         specifier: ^8.3.0
29:         version: 8.10.2(eslint@8.57.1)
30:       eslint-plugin-yml:
31:         specifier: ^0.13.0
32:         version: 0.13.0(eslint@8.57.1)
33:       peggy:
34:         specifier: 5.1.0
35:         version: ...
gateway · 2026-08-29 08:47:19
result
583-  }
584-
585-  const branchPrefix =
586-    config.releaseBranchPrefix || DEFAULT_RELEASE_BRANCH_NAME;
587-
588:  const rev = argv.rev;
589-  let checkoutTarget;
590-  let branchName;
591-  if (rev) {
592-    logger.debug(`Trying to get branch name for provided revision: "${rev}"`);
593-    branchName = (
gateway · 2026-08-29 08:47:24
result
574-  } else {
575-    const repoStatus = await git.status();
576-    if (isRepoDirty(repoStatus)) {
577-      reportError(
578-        'Your repository is in a dirty state. ' +
579-          'Please stash or commit the pending changes.',
580-        logger,
581-      );
582-    }
583-  }
584-
585-  const branchPrefix =
586-    config.releaseBranchPrefix || DEFAULT_RELEASE_BRANCH_NAME;
587-
588:  const rev = argv.rev;
589-  let checkoutTarget;
590-  let branchName;
591-  if (rev) {
592-    logger.debug(`Trying to get branch name for provided revision: "${rev}"`);
593-    branchName = (
594-      await git.raw('name-rev', '--name-only', '--no-undefined', rev)
595-    ).trim();
596-    checkoutTarget = branchName || rev;
597-    logger.debug('Checking out revision', checkoutTarget);
598-    await git.checkout(checkoutTarget);
599-  } else {
600-    // Find the remote branch
601-    branchName = `${branchPrefix}/${newVersion}`;
602-    checkoutTarget = branchName;
gateway · 2026-08-29 08:48:10
result
Usage: realpath [OPTION]... FILE...
Print the resolved absolute file name;
all but the last component must exist

  -e, --canonicalize-existing  all components of the path must exist
  -m, --canonicalize-missing   no path components need exist or be a directory
  -L, --logical                resolve '..' components before symlinks
  -P, --physical               resolve symlinks as encountered (default)
  -q, --quiet                  suppress most error messages
      --relative-to=DIR        print the resolved path relative to DIR
      --relative-base=DIR      print absolute paths unless paths below DIR
  -s, --strip, --no-symlinks   don't expand symlinks
  -z, --zero                   end each output line with NUL, not newline
      --help        display this help and exit
      --version     output version information and exit

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation <https://www.gnu.org/software/coreutils/realpath>
or available ...
gateway · 2026-08-29 08:48:36
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/__tests__/publishState.test.ts</path>
<type>file</type>
<content>
1: import { describe, test, expect, beforeEach, afterEach } from 'vitest';
2: import { homedir } from 'os';
3: import { join } from 'path';
4: 
5: import {
6:   getCraftStateDir,
7:   getPublishStateFilename,
8:   getPublishStatePath,
9: } from '../publishState';
10: 
11: describe('publishState', () => {
12:   const savedEnv = { ...process.env };
13: 
14:   beforeEach(() => {
15:     delete process.env.XDG_STATE_HOME;
16:   });
17: 
18:   afterEach(() => {
19:     process.env = { ...savedEnv };
20:   });
21: 
22:   describe('getCraftStateDir', () => {
23:     test('defaults to $HOME/.local/state/craft when XDG_STATE_HOME is unset', () => {
24:       expect(getCraftStateDir()).toBe(
25:         join(homedir(), '.local', 'state', 'craft'),
26:       );
27:     });
28: 
29:     test('honours XDG_STATE_HOME when set', () => {
30:       ...
gateway · 2026-08-29 08:48:54
result
(no output)
gateway · 2026-08-29 08:49:00
result
(no output)
gateway · 2026-08-29 08:49:09
result
(no output)
gateway · 2026-08-29 08:49:16
result
(no output)
gateway · 2026-08-29 08:49:54
result
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/details-from-context.js</path>
<type>file</type>
<content>
1: const { parse: parsePublishIssueTitle } = require("./publish-issue-title");
2: 
3: /**
4:  * Matches the entire "Targets" section of a github publish issue body.
5:  */
6: const TARGETS_SECTION_PARSER_REGEX =
7:   /^(?!### Targets$\s)(?: *- \[[ xX]\] \S+\s*$(?:\r?\n)?)+/m;
8: 
9: /**
10:  * Matches all targets of a github publish issue body in a section that was already matched and extracted with `TARGETS_PARSER_REGEX`.
11:  * The "id" of the targets is captured within a capture group.
12:  */
13: const TARGETS_PARSER_REGEX = /^\s*- \[[ x]\] (\S+)/gim;
14: 
15: /**
16:  * Matches checked targets of a github publish issue body in a section that was already matched and extracted with `TARGETS_PARSER_REGEX`.
17:  * The "id" of the targets is captured within a capture group. ...
gateway · 2026-08-29 08:50:12

CRITICAL

  • Unavailable image blocks every publish. .github/workflows/publish.yml:239-250 unconditionally runs getsentry/craft:2.31.0, although only compact-title discovery needs it (:180-184). docker manifest inspect getsentry/craft:2.31.0 returns no such manifest; 2.30.1 exists. Legacy releases therefore fail before publishing, with no availability gate or fallback. The structural test at src/modules/__tests__/publish-workflow.js:58-88 asserts the hard pin but does not verify availability or legacy isolation.

MAJOR

  • Legacy JSON workspace titles allow a workspace with a non-root path. The grammar accepts both Path? and LegacyWorkspace? together (src/modules/publish-issue-title.peggy:11,26-33). details-from-context returns both fields without rejecting the combination (src/modules/details-from-context.js:34-55,76-83), and resolvePublishLocation explicitly preserves both (src/modules/publish-location.js:5-8). Thus publish: getsentry/toolkit/packages/cli [workspace: "cli/v2"] @1.2.3 reaches the publish container with a non-root cwd and CRAFT_WORKSPACE, violating the contract. Existing tests cover only a root legacy workspace (src/modules/__tests__/publish-location.js:53-70).

MINOR

  • Generated parser drift is not detected. package.json:18-19 regenerates the parser before tests, and CI only runs yarn test (.github/workflows/test.yml:33-34). Production installs dependencies and directly loads the committed generated parser (.github/workflows/publish.yml:131-149, src/modules/details-from-context.js:1). A stale generated file can therefore pass CI while production runs different parsing code. No post-generation clean-tree check exists.

  • An unrelated pnpm lockfile is untracked. pnpm-lock.yaml:1 is present despite Publish using Yarn (package.json:10-13; .github/workflows/test.yml:27-31). It creates a second, unused dependency resolution and should not enter the change.

DO-NOT-MERGE

gpt-5.6-terra · 2026-08-29 08:50:12 · ~473 tokens

Distillations (8)

Gen 0 2026-08-29 08:51:12 · 1528 tokens

Date: Aug 29, 2026 * 🔴 (08:42) User stated that prerelease compatibility relaxation applies only to the current Craft version side, never the configured `minVersion` side. * 🟡 (08:42) `src/commands/workspace.ts` defines the `workspace <command>` yargs command, described as `Manage release workspaces`; its builder requires a subcommand and registers `./workspace_cmds/list`, while its handler is …

Gen 0 2026-08-29 08:49:34 · 1288 tokens

Date: Aug 29, 2026 * 🟡 (08:41) `src/modules/publish-location.js` defines `needsWorkspaceDiscovery({ path, workspace })` as true only when no explicit `workspace` exists and `path` matches `^\\./[A-Za-z0-9_.-]+$`; `resolvePublishLocation({ path, workspace, workspaceNames })` preserves explicit `{ path, workspace }`, otherwise only performs discovery for that one-segment path form. * 🟡 (08:41) `r…

Gen 0 2026-08-29 08:48:16 · 1018 tokens

Date: Aug 29, 2026 * 🔴 (08:41) User stated that new Craft publish requests always include the checkout repository identity. * 🔴 (08:41) User stated that the controller never normalizes names; workspace names retain exact spelling. * 🟡 (08:41) Branch `feat/workspace-acceptance` at `b658ffa` (`fix: validate publish workspace JSON`) includes prior commit `33de3f1` (`feat: accept workspace publish…

Gen 0 2026-08-29 08:46:52 · 404 tokens

Date: Aug 29, 2026 * 🟡 (08:40) Craft `src/index.ts` diff imports and uses `setGlobals`; it resolves workspace-selection globals from raw argv/environment early, including `CRAFT_WORKSPACE`, before command parsing/configuration processing. * 🟡 (08:40) Craft configuration documentation distinguishes a release `"workspace"` as a named, independently-versioned release unit. * 🟡 (08:40) Craft confi…

Gen 0 2026-08-29 08:46:15 · 290 tokens

Date: Aug 29, 2026 * 🟡 (08:40) Craft diff adds GitHub Actions workflow/action test coverage that locates action steps via `getActionStep(name)` and verifies the `Read Craft Targets` step receives `env.WORKSPACE`. * 🟡 (08:40) Craft action/workflow test setup imports `tmpdir` from `os`, creates a temporary `binDirectory`, writes a `craft` executable, and applies `chmodSync(join(binDirectory, 'cra…

Gen 0 2026-08-29 08:45:02 · 622 tokens

Date: Aug 29, 2026 * 🔴 (08:40) User stated Craft release-version validation may relax only the CURRENT version side when handling a build heading toward the release targeted by `minVersion`; it must never relax the configured `minVersion` side. * 🟡 (08:40) Craft diff documents Vercel target configuration fields `orgId` and `projectId` in `docs/src/content/docs/targets/vercel.md`: repository-spe…

Gen 0 2026-08-29 08:41:34 · 1990 tokens

Date: Aug 29, 2026 * 🔴 [package-manager-preference] (08:39) User stated package management must always use `pnpm`; `npm` and `yarn` must never be used. * 🔴 (08:39) User stated Craft uses Volta-managed Node.js `v22.12.0`; dependencies install with `pnpm install --frozen-lockfile`. * 🔴 (08:39) User stated Craft development commands are `pnpm build` (outputs `dist/craft`), `pnpm test`, `pnpm lint…

Gen 0 2026-08-29 08:40:54 · 514 tokens

Date: Aug 29, 2026 * 🟡 [requested-review] [requested-read-only] (08:38) User requested a rigorous adversarial, read-only review of the uncommitted compact workspace-title contract across both worktrees: Craft at `/home/byk/Code/getsentry/craft-workspace-action-propagation` and Publish at `/home/byk/Code/getsentry/publish-workspace-acceptance`. User prohibited file edits and destructive commands,…