DashboardcraftSession 1BWRXHTiC7F8

Session 1BWRXHTiC7F8

Full ID: 1BWRXHTiC7F8Lg9LG
Messages: 32
Distillations: 4
Time range: 2026-08-29 12:33:22 — 2026-08-29 12:37:38

Conversation (32 messages)

Perform a rigorous, read-only adversarial review of the current uncommitted compact workspace publish-contract changes in BOTH worktrees:

  • /home/byk/Code/getsentry/craft-workspace-action-propagation (branch feat/workspace-action-propagation)
  • /home/byk/Code/getsentry/publish-workspace-acceptance (branch feat/workspace-acceptance)

Do not modify files, stage, commit, or run destructive commands. Review the actual current worktrees against their branch bases. The Publish controller always uses getsentry/craft:latest; this is intentional and must not be reported as a mutable-image concern. Craft must release first so latest contains workspace list and craft publish --rev.

Inspect and assess: exact CI-approved revision extraction from issue check-runs link; checkout/state/location/publish all bound to that same revision; safe detached-SHA Craft checkout fallback; legacy title compatibility; compact single-path-segment workspace-first classification only after checkout/discovery; missing root config path-only behavior and discovery failure behavior; no workspace normalization; ASCII new workspace boundary; legacy JSON workspace parsing and rejection of workspace + non-root path; parser grammar/generated artifact freshness; state filename parity and state GitHub identity; workflow action expressions/YAML/shell injection/traversal; whether latest use correctly meets stated contract; test quality and regressions. Verify both new and old flows, potential CI lifecycle breakage, and current untracked/staged status. Note pnpm-lock.yaml in Publish is unrelated and must not be committed.

Return only an evidence-based review: findings ordered CRITICAL/MAJOR/MINOR with exact file:line citations and practical fixes; clearly distinguish intentional behavior. End with explicit MERGE or DO-NOT-MERGE verdict. If no findings, say so with remaining deployment/verification risks.

gateway · 2026-08-29 12:33:22
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 12:33:34
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 12:33:43
result
## feat/workspace-action-propagation...origin/feat/workspace-action-propagation
 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/
feat/workspace-action-propagation
6dae341f9bc1378abde7a9022108caded2d22226
21270a1d12a60b461c51fba93bd076b90d9cf4af
21270a1d12a60b461c51fba93bd076b90d9cf4af
6dae341 (HEAD -> feat/workspace-action-propagation, origin/feat/workspace-action-propagation) feat: propagate release workspaces
 .github/workflows/release.yml          |   9 +++
 action.yml                             |  35 +++++++-
 src/__tests__/action.test.ts           | 144 +++++++++++++++++++++++++++++++++
 src/commands/__tests__/publish.test.ts |  47 +++++++++++
 src/commands/publish.ts                |  33 +++++++-
 5 files changed, ...
gateway · 2026-08-29 12:33:49
result
## feat/workspace-acceptance...origin/feat/workspace-acceptance
 M .github/workflows/publish.yml
 M docs/publish-issue-format.md
 M package.json
 M src/modules/__tests__/details-from-context.js
 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
feat/workspace-acceptance
b658ffa0299fedf78c9dd9a2121cd740691ca157
fatal: Needed a single revision
gateway · 2026-08-29 12:33:54
result
origin	https://github.com/getsentry/publish.git (fetch)
origin	https://github.com/getsentry/publish.git (push)
  chore/fix-security-advisories                             2513c782a5a54da5921a87ce52fc357a78c8e263 [gone] fix: Update CI to use yarn test instead of yarn jest
* feat/workspace-acceptance                                 b658ffa0299fedf78c9dd9a2121cd740691ca157 fix: validate publish workspace JSON
  fix/add-workflow-permissions                              a58b7212cd8886308be5d742885271ebda2f81e7 [gone] Merge remote-tracking branch 'origin/main' into fix/add-workflow-permissions
+ main                                                      83d210b29553ea6f4d97508821724a834c43856e build(deps): bump js-yaml from 4.3.0 to 4.3.1 (#9174)
+ opencode/tidy-orchid                                      83d210b29553ea6f4d97508821724a834c43856e build(deps): bump js-yaml from 4.3.0 to 4.3.1 (#9174)
  security/dual-write-publish-state                         ...
gateway · 2026-08-29 12:34:02
result
83d210b29553ea6f4d97508821724a834c43856e
83d210b29553ea6f4d97508821724a834c43856e
b658ffa (HEAD -> feat/workspace-acceptance, origin/feat/workspace-acceptance) fix: validate publish workspace JSON
33de3f1 feat: accept workspace publish requests
 .github/workflows/cocoapods-keepalive.yml     |   2 +-
 .github/workflows/publish.yml                 |  27 ++-
 README.md                                     |   5 +
 docs/publish-issue-format.md                  |  81 +++++++++
 src/modules/__tests__/details-from-context.js | 230 +++++++++++++++++++++++++-
 src/modules/__tests__/publish-workflow.js     |  82 +++++++++
 src/modules/__tests__/update-issue.js         |  15 +-
 src/modules/details-from-context.js           |  33 +++-
 src/modules/update-issue.js                   |  54 +++---
 9 files changed, 488 insertions(+), 41 deletions(-)
 .github/workflows/publish.yml                 | 59 ++++++++++++++-------------
 docs/publish-issue-format.md                  | 55 ...
gateway · 2026-08-29 12:34:18
result
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/workspace_cmds/__tests__/list.test.ts
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/workspace_cmds/list.ts
gateway · 2026-08-29 12:34:27
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 12:34:33
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts</path>
<type>file</type>
<content>
1: import { Arguments, Argv, CommandBuilder } from 'yargs';
2: import chalk from 'chalk';
3: import { existsSync, mkdirSync, readFileSync } from 'fs';
4: 
5: import { safeFs } from '../utils/dryRun';
6: import { dirname, join } from 'path';
7: import * as shellQuote from 'shell-quote';
8: import stringLength from 'string-length';
9: 
10: import {
11:   getConfiguration,
12:   getStatusProviderFromConfig,
13:   getArtifactProviderFromConfig,
14:   DEFAULT_RELEASE_BRANCH_NAME,
15:   getGlobalGitHubConfig,
16:   expandWorkspaceTargets,
17:   getNoMergeConfig,
18:   getActiveWorkspace,
19: } from '../config';
20: import { formatTable, logger } from '../logger';
21: import {
22:   type GitHubGlobalConfig,
23:   TargetConfig,
24: } from '../schemas/project_config';
25: import { getAllTargetNames, getTargetByName, SpecialTarget } from '../targets';
26: import { ...
gateway · 2026-08-29 12:34:37
result
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts</path>
<type>file</type>
<content>
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 {
616:     const repoStatus = await git.status();
617:     if (isRepoDirty(repoStatus)) {
618:       reportError(
619:         'Your repository is in a dirty state. ' +
620:           'Please stash or commit the pending changes.',
621:         ...
gateway · 2026-08-29 12:34:45
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 12:34:48
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 12:34:51
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 12:34:57
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 12:35:01
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 12:35:06
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 12:35:13
result
Found 12 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/helpers.ts:
  Line 25:  * Extracts the `--workspace` selection from the raw argv (or the

  Line 30:  * config.targets) *before* middleware, so the workspace must be resolved up

  Line 33:  * Supports `--workspace foo` and `--workspace=foo`. It uses Node's built-in

  Line 35:  * `--workspace --dry-run`) is never mistaken for a workspace name. The CLI

  Line 42: export function extractWorkspaceSelection(

  Line 49:     options: { workspace: { type: 'string' } },

  Line 54:   let workspace: string | undefined;

  Line 56:     if (token.kind !== 'option' || token.name !== 'workspace') {

  Line 61:     workspace = undefined;

  Line 65:       // `--workspace=-foo` is a valid inline value; `--workspace --foo` is not.

  Line 68:       workspace = token.value;

  Line 71:   return workspace || envWorkspace;
gateway · 2026-08-29 12:35:19
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 12:35:22
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 12:35:26
result
/home/byk/Code/getsentry/publish-workspace-acceptance/scripts/generate-publish-issue-title-parser.js
gateway · 2026-08-29 12:35:31
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 12:35:37
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 12:35:44
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 12:35:51
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: const generatedParser = prettier.format(`/* eslint-disable */\n${parser}`, {
28:   filepath: outputPath,
29: });
30: 
31: if (process.argv.includes("--check")) {
32:   const currentParser = fs.readFileSync(outputPath, "utf8");
33:   ...
gateway · 2026-08-29 12:35:58
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:     "check:generated": "node scripts/generate-publish-issue-title-parser.js --check",
20:     "test": "yarn check:generated && vitest run",
21:     "test:watch": "vitest",
22:     "lint": "eslint src .github --ignore-pattern '!.github'",
23:     "prettier": "prettier --write src"
24:   },
25:   "devDependencies": {
26:     "eslint": ...
gateway · 2026-08-29 12:36:03
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 12:36:08
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:     if (path !== ".") {
8:       throw new Error("A publish workspace must use the repository root path.");
9:     }
10:     return { path, workspace };
11:   }
12: 
13:   if (!needsWorkspaceDiscovery({ path, workspace })) {
14:     return { path };
15:   }
16: 
17:   if (!workspaceNames.every(isWorkspaceName)) {
18:     throw new Error(
19:       "Craft workspace discovery returned an invalid workspace list."
20:     );
21:   }
22: 
23:   const segments = path.slice(2).split("/");
24:   if (
25:     path.startsWith("./") &&
26:     segments.length === 1 &&
27:     workspaceNames.includes(segments[0])
28:   ) {
29:     return { path: ...
gateway · 2026-08-29 12:36:14
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 12:36:48
result
/**
 * Matches the entire "Targets" section of a github publish issue body.
 */
const TARGETS_SECTION_PARSER_REGEX =
  /^(?!### Targets$\s)(?: *- \[[ xX]\] \S+\s*$(?:\r?\n)?)+/m;

/**
 * Matches all targets of a github publish issue body in a section that was already matched and extracted with `TARGETS_PARSER_REGEX`.
 * The "id" of the targets is captured within a capture group.
 */
const TARGETS_PARSER_REGEX = /^\s*- \[[ x]\] (\S+)/gim;

/**
 * Matches checked targets of a github publish issue body in a section that was already matched and extracted with `TARGETS_PARSER_REGEX`.
 * The "id" of the targets is captured within a capture group.
 */
const CHECKED_TARGETS_PARSER_REGEX = /^\s*- \[x\] (\S+)/gim;

async function detailsFromContext({ context }) {
  if (!context || !context.payload || !context.payload.issue) {
    throw new Error("Issue context is not defined");
  }

  const titleParser =
    /^publish: (?:getsentry\/)?(?<repo>[A-Za-z0-9_.-]+)(?<path>\/[\w./-]+)?(?: \[workspace: ...
gateway · 2026-08-29 12:37:05
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 12:37:10
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 12:37:38

Distillations (4)

Gen 0 2026-08-29 12:39:39 · 1235 tokens

Date: Aug 29, 2026 * 🔴 (12:35) User stated that the CI poller always adds the `ci-ready` label after CI passes; the publish job must therefore trigger only when `github.event.label.name == 'ci-ready'`, preventing a race with the `waiting-for-ci` job on the same event. * 🟡 (12:35) User provided a GitHub Actions publish workflow: `waiting-for-ci` handles approved `publish: ` issues, posts “Approv…

Gen 0 2026-08-29 12:38:28 · 958 tokens

Date: Aug 29, 2026 * 🟡 (12:34) User provided `src/commands/workspace.ts`: yargs command `workspace <command>` (“Manage release workspaces”) requires a subcommand via `yargs.demandCommand().command(list)` and has a no-op `handler`; it imports `./workspace_cmds/list`. * 🟡 (12:34) User provided `src/commands/workspace_cmds/list.ts`: `workspace list` (“List defined release workspaces as a JSON arra…

Gen 0 2026-08-29 12:37:07 · 247 tokens

Date: Aug 29, 2026 * 🟡 (12:34) User provided a partial, heavily elided excerpt of Craft file `src/commands/publish.ts`, showing `export async function publishMain(argv: PublishOptions): Promise<any>` at line 602. Visible implementation references include `getGitClient()`, `isRepoDirty(repoStatus)`, `findReleaseBranches`, handling special targets `"all"`/`"none"`, publish-state lookup/parsing via…

Gen 0 2026-08-29 12:35:56 · 2003 tokens

Date: Aug 29, 2026 * 🟡 [requested-read-only-review] (12:33) User requested a rigorous, read-only adversarial review of uncommitted compact workspace publish-contract changes in both worktrees: `/home/byk/Code/getsentry/craft-workspace-action-propagation` on `feat/workspace-action-propagation`, and `/home/byk/Code/getsentry/publish-workspace-acceptance` on `feat/workspace-acceptance`. * 🔴 (12:33…