Dashboard › craft › Session 18UTILhVVpbG
18UTILhVVpbGX9eg4Read-only, adversarial review. Do not edit anything. Inspect current uncommitted changes in BOTH /home/byk/Code/getsentry/craft-workspace-action-propagation (vs origin/master) and /home/byk/Code/getsentry/publish-workspace-acceptance (vs origin/main). Verify the exact cross-repo workspace contract end-to-end: (1) legacy title and state filename byte compatibility when unscoped; (2) readable and lossless workspace title grammar and parser; (3) option-looking workspace cannot inject a Craft option; (4) all controller-unsafe values reject before action side effects; (5) selected workspace flows through prepare, target listing, issue parsing, CRAFT_WORKSPACE, state filename, retries; (6) state prepopulation and failure handler reference exactly the same secure state path; (7) no external/worktree dependency artifact will be committed. Inspect tests and diffs. Return a concise report with CRITICAL/MAJOR/MINOR findings including precise file:line and an explicit MERGE/DO-NOT-MERGE verdict. A clean report must state 'No findings'.
I’ll inspect both worktrees and their diffs against the stated remote bases, then trace the workspace value across Craft and Publish without modifying either tree.
<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 .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 (32 entries) </entries>
<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 && ...
<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 README.md src/ vitest.config.js yarn.lock (14 entries) </entries>
<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 ...
/home/byk/Code/getsentry/craft-workspace-action-propagation M .github/workflows/release.yml M action.yml ?? src/__tests__/action.test.ts .github/workflows/release.yml | 9 +++++++++ action.yml | 30 +++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) M .github/workflows/release.yml M action.yml 21270a1d12a60b461c51fba93bd076b90d9cf4af 21270a1d12a60b461c51fba93bd076b90d9cf4af
/home/byk/Code/getsentry/publish-workspace-acceptance M .github/workflows/publish.yml M src/modules/__tests__/details-from-context.js M src/modules/__tests__/update-issue.js M src/modules/details-from-context.js M src/modules/update-issue.js .github/workflows/publish.yml | 24 +++-- src/modules/__tests__/details-from-context.js | 145 +++++++++++++++++++++++++- src/modules/__tests__/update-issue.js | 15 ++- src/modules/details-from-context.js | 27 ++++- src/modules/update-issue.js | 54 +++++----- 5 files changed, 225 insertions(+), 40 deletions(-) M .github/workflows/publish.yml M src/modules/__tests__/details-from-context.js M src/modules/__tests__/update-issue.js M src/modules/details-from-context.js M src/modules/update-issue.js 83d210b29553ea6f4d97508821724a834c43856e 83d210b29553ea6f4d97508821724a834c43856e
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 4e6c11e..323e8ba 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,142 +1,151 @@
name: Release
concurrency: ${{ github.workflow }}-${{ github.ref }}
on:
# For Craft's own releases (dogfooding)
workflow_dispatch:
inputs:
version:
description: Version to release
required: true
default: 'auto'
force:
description: Force a release even when there are release-blockers (optional)
required: false
+ workspace:
+ description: Named Craft release workspace to prepare and publish
+ required: false
# For external repos to call this workflow
workflow_call:
inputs:
version:
description: Version to release (semver, bump type, or "auto")
type: string
required: false
force:
description: Force a release even when there are ...
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index cff6bc3..5fddfac 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -87,226 +87,234 @@ jobs:
run: |
gh variable set CI_POLLER_HAS_PENDING -R "$GITHUB_REPOSITORY" -b "true"
# Trigger the CI poller immediately instead of waiting for the next cron tick.
# Uses the app token — GITHUB_TOKEN workflow_dispatch events are suppressed.
- name: Trigger CI poller
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
gh workflow run ci-poller.yml -R "$GITHUB_REPOSITORY"
publish:
runs-on: ubuntu-latest
environment: production
name: Publish a new version
# Publish when ci-ready is present (added by the poller after CI passes).
# Fires ONLY on ci-ready label events — not accepted — to avoid racing
# with waiting-for-ci on the same event. ...
Found 100 matches (more matches available)
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/workspaces.ts:
Line 15: /** Information about a workspace package */
Line 25: /** Dependencies that are also workspace packages */
Line 26: workspaceDependencies: string[];
Line 29: /** Result of workspace discovery */
Line 31: /** The type of workspace manager detected */
Line 37: /** Structure of pnpm-workspace.yaml */
Line 45: workspaces?: string[] | { packages?: string[] };
Line 93: * Extract workspaces array from package.json workspaces field
Line 97: workspaces: string[] | { packages?: string[] } | undefined,
Line 99: if (!workspaces) {
Line 102: if (Array.isArray(workspaces)) {
Line 103: return workspaces;
Line 105: return workspaces.packages || [];
Line 115: // First: collect all workspace package names and locations
Line 116: const workspaceLocations: Array<{
Line 120: const workspaceNames = ...
<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. ...
<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. ...
Found 100 matches (more matches available)
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/workspaces.ts:
Line 15: /** Information about a workspace package */
Line 25: /** Dependencies that are also workspace packages */
Line 26: workspaceDependencies: string[];
Line 29: /** Result of workspace discovery */
Line 31: /** The type of workspace manager detected */
Line 37: /** Structure of pnpm-workspace.yaml */
Line 45: workspaces?: string[] | { packages?: string[] };
Line 93: * Extract workspaces array from package.json workspaces field
Line 97: workspaces: string[] | { packages?: string[] } | undefined,
Line 99: if (!workspaces) {
Line 102: if (Array.isArray(workspaces)) {
Line 103: return workspaces;
Line 105: return workspaces.packages || [];
Line 115: // First: collect all workspace package names and locations
Line 116: const workspaceLocations: Array<{
Line 120: const workspaceNames = ...
Found 20 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/helpers.ts:
Line 42: export function extractWorkspaceSelection(
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/index.ts:
Line 16: extractWorkspaceSelection,
Line 97: // of truth for the selection (see extractWorkspaceSelection for precedence).
Line 98: setActiveWorkspace(extractWorkspaceSelection(argv));
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/__tests__/helpers.test.ts:
Line 10: extractWorkspaceSelection,
Line 37: describe('extractWorkspaceSelection', () => {
Line 42: extractWorkspaceSelection(['publish', '1.0.0'], NO_ENV),
Line 48: extractWorkspaceSelection(['publish', '--workspace', 'cli'], NO_ENV),
Line 53: expect(extractWorkspaceSelection(['--workspace=mcp'], NO_ENV)).toBe('mcp');
Line 57: expect(extractWorkspaceSelection(['--workspace=-cli'], NO_ENV)).toBe(
Line 61: ...
<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: ...
Found 29 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/index.ts:
Line 20: import { setActiveWorkspace } from './config';
Line 98: setActiveWorkspace(extractWorkspaceSelection(argv));
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/config.ts:
Line 71: * (single implicit release unit). Set once via `setActiveWorkspace` from the
Line 74: let _activeWorkspaceName: string | undefined;
Line 83: export function setActiveWorkspace(name: string | undefined): void {
Line 84: _activeWorkspaceName = name;
Line 94: return _activeWorkspaceName;
Line 110: function resolveWorkspaceConfig(
Line 212: if (_activeWorkspaceName) {
Line 214: `--workspace "${_activeWorkspaceName}" was given but no "workspaces" ` +
Line 222: if (!_activeWorkspaceName) {
Line 239: return resolveWorkspaceConfig(config, ...
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/config.ts</path> <type>file</type> <content> 60: /** 61: * The minimum craft version required to use the top-level `workspaces` config. 62: * 63: * This is the release the workspaces feature ships in. A dev build of that 64: * release (e.g. `2.29.0-dev.0`) satisfies it via the pre-release relaxation in 65: * `checkMinimalConfigVersion`. 66: */ 67: export const WORKSPACES_MIN_VERSION = '2.29.0'; 68: 69: /** 70: * The name of the currently-selected workspace, or undefined for the default 71: * (single implicit release unit). Set once via `setActiveWorkspace` from the 72: * `--workspace` CLI option / `CRAFT_WORKSPACE` env before any config access. 73: */ 74: let _activeWorkspaceName: string | undefined; 75: 76: /** 77: * Selects the active workspace for subsequent configuration reads. 78: * 79: * Passing `undefined` (or omitting) clears the selection (default behavior). ...
<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>
<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. ...
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/package.json</path>
<type>file</type>
<content>
1: {
2: "name": "@sentry/craft",
3: "version": "2.31.0-dev.0",
4: "description": "The universal sentry workflow CLI",
5: "main": "dist/craft",
6: "repository": "https://github.com/getsentry/craft",
7: "author": "Sentry",
8: "license": "MIT",
9: "bin": {
10: "craft": "dist/craft",
11: "sentry-craft": "dist/craft"
12: },
13: "devDependencies": {
14: "@aws-sdk/client-lambda": "^3.984.0",
15: "@eslint/js": "^9.17.0",
16: "@google-cloud/storage": "^7.14.0",
17: "@octokit/plugin-retry": "^7.1.2",
18: "@octokit/request-error": "^7.0.0",
19: "@octokit/rest": "^21.0.2",
20: "@sentry/esbuild-plugin": "^2.23.0",
21: "@sentry/node": "^10.27.0",
22: "@types/async": "^3.0.1",
23: "@types/aws4": "^1.5.1",
24: "@types/cli-table": "^0.3.0",
25: "@types/git-url-parse": "^9.0.0",
26: "@types/is-ci": "^2.0.0",
27: ...
> @sentry/craft@2.31.0-dev.0 test /home/byk/Code/getsentry/craft-workspace-action-propagation > vitest run -- src/__tests__/action.test.ts RUN v4.1.8 /home/byk/Code/getsentry/craft-workspace-action-propagation [info] [[target/github]] No previous release found [info] [[target/github]] Deleted orphaned draft release: v1.0.0 [info] [[target/github]] No previous release found [warn] [[target/github]] Failed to clean up release "v1.0.0": Error: Cleanup failed [info] [[target/github]] No previous release found [info] [[target/github]] No previous release found [info] [[target/github]] Release for tag "1.0.0" already exists and is published. Skipping GitHub release creation (likely from a previous run). [info] [[target/github]] No previous release found [info] [[target/github]] createRelease returned 422 for tag "1.0.0". Looking for a leftover draft release to clean up... [info] [[target/github]] Deleting leftover draft release (id=789) for tag "1.0.0"... ...
<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: "test": "vitest run",
19: "test:watch": "vitest",
20: "lint": "eslint src .github --ignore-pattern '!.github'",
21: "prettier": "prettier --write src"
22: },
23: "devDependencies": {
24: "eslint": "^8.9.0",
25: "eslint-config-prettier": "^8.3.0",
26: "eslint-plugin-yml": "^0.13.0",
27: "prettier": "^2.2.1",
28: "vitest": "^4.1.0"
29: },
30: "dependencies": {
31: ...
yarn run v1.22.22
$ vitest run src/modules/__tests__/details-from-context.js src/modules/__tests__/update-issue.js
(!) Your Vite config uses features that are unsupported by `configLoader: 'native'`, which is planned to become the default in a future major version of Vite:
- ESM syntax in a file loaded as CommonJS (vitest.config.js:1:1). Use a `.mjs` extension or set `"type": "module"` in the closest package.json
Set `VITE_CONFIG_NATIVE_IGNORE_WARNING=true` to suppress this warning.
RUN v4.1.11 /home/byk/Code/getsentry/publish-workspace-acceptance
Test Files 2 passed (2)
Tests 15 passed (15)
Start at 17:14:58
Duration 459ms (transform 111ms, setup 0ms, import 186ms, tests 36ms, environment 0ms)
Done in 1.08s.
<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: ...
No files found
Found 9 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/publishState.ts:
Line 111: export function getPublishStatePath(
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/__tests__/publishState.test.ts:
Line 8: getPublishStatePath,
Line 147: describe('getPublishStatePath', () => {
Line 150: const path = getPublishStatePath(
Line 165: const path = getPublishStatePath('1.2.3', { owner: 'o', repo: 'r' }, cwd);
Line 173: const path = getPublishStatePath('1.2.3', null, cwd);
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts:
Line 51: import { getPublishStatePath } from '../utils/publishState';
Line 693: // Fall through with null — getPublishStatePath() handles this by
Line 697: const publishStateFile = getPublishStatePath(
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts</path>
<type>file</type>
<content>
640: fuzzyMatches.map(b => ` - ${b}`).join('\n');
641: }
642:
643: if (exactMatches.length === 0 && fuzzyMatches.length === 0) {
644: message += `\n\nNo release branches found on the remote.`;
645: }
646:
647: message += `\n\nOriginal error: ${err instanceof Error ? err.message : String(err)}`;
648:
649: throw new ConfigurationError(message);
650: }
651: }
652:
653: const revision = await git.revparse('HEAD');
654: logger.debug('Revision to publish: ', revision);
655:
656: const statusProvider = await getStatusProviderFromConfig();
657: const artifactProvider = await getArtifactProviderFromConfig();
658:
659: // Check status of all CI builds linked to the revision
660: await checkRevisionStatus(statusProvider, revision, argv.noStatusCheck);
661:
662: await ...
<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. ...
Found 1 matches /home/byk/Code/getsentry/craft-workspace-action-propagation/src/config.ts: Line 471: export async function getGlobalGitHubConfig(
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/config.ts</path>
<type>file</type>
<content>
440: *
441: * The policy determines how versions are resolved when no explicit version
442: * is provided to `craft prepare`:
443: * - 'auto': Analyze commits to determine the bump type
444: * - 'manual': Require an explicit version argument
445: * - 'calver': Use calendar versioning
446: *
447: * If not explicitly configured, defaults to:
448: * - 'auto' if minVersion >= 2.14.0
449: * - 'manual' otherwise (for backward compatibility)
450: *
451: * @returns The versioning policy
452: */
453: export function getVersioningPolicy(): VersioningPolicy {
454: const config = getConfiguration();
455:
456: // Use explicitly configured policy if available
457: if (config.versioning?.policy) {
458: return config.versioning.policy as VersioningPolicy;
459: }
460:
461: // Default based on minVersion
462: return ...
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/__tests__/helpers.test.ts</path>
<type>file</type>
<content>
1: import { existsSync, mkdirSync, readFileSync, rmSync } from 'fs';
2: import path from 'path';
3: import { tmpdir } from 'os';
4:
5: import { afterEach, beforeEach, describe, expect, test } from 'vitest';
6:
7: import {
8: disableChangelogMentions,
9: envToBool,
10: extractWorkspaceSelection,
11: MAX_STEP_OUTPUT_BYTES,
12: setGitHubActionsOutput,
13: truncateForOutput,
14: writeGitHubActionsFile,
15: } from '../helpers';
16:
17: describe('envToBool', () =>
18: test.each([
19: [undefined, false],
20: [null, false],
21: [false, false],
22: ['undefined', false],
23: ['null', false],
24: ['', false],
25: ['0', false],
26: ['no', false],
27: [true, true],
28: ['true', true],
29: [1, true],
30: ['1', true],
31: ['yes', true],
32: ['dogs are great!', true],
33: ])('From %j we ...
M .github/workflows/release.yml M action.yml ?? src/__tests__/action.test.ts
M .github/workflows/publish.yml M src/modules/__tests__/details-from-context.js M src/modules/__tests__/update-issue.js M src/modules/details-from-context.js M src/modules/update-issue.js
c232c383e26fc1be21ea27342217e1a22acef35c - 42840c7f95205357a9ed1230a9e27f24de92ccc1 - c232c383e26f cli Y2xp c232c383e26f cli [preview] "next" Y2xpIFtwcmV2aWV3XSAibmV4dCI c232c383e26f --config-from=untrusted LS1jb25maWctZnJvbT11bnRydXN0ZWQ c232c383e26f
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/publish.yml</path>
<type>file</type>
<content>
140: env:
141: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
142: run: node .__publish__/src/publish/post-workflow-details.js
143:
144: # Setting the target repo branch will cause the craft config (.craft.yml) to be taken from the checked out branch
145: # By default, we check out the default branch of the repo.
146: # If you need to maintain diverging craft configs on different branches, add your repo and the merge target branch
147: # (i.e. the branch craft will merge the release branch into) into the if condition below.
148: - name: Set target repo checkout branch
149: # Note: Branches registered here MUST BE protected in the target repo!
150: if: |
151: fromJSON(steps.inputs.outputs.result).repo == 'sentry-migr8' && fromJSON(steps.inputs.outputs.result).merge_target == ...
{"invalid":false,"codePoints":["63","6c","69","202e","64","65","76"]}
{"workspace":"clidev","codePoints":["63","6c","69","202e","64","65","76"]}
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/details-from-context.js</path>
<type>file</type>
<content>
15: * The "id" of the targets is captured within a capture group.
16: */
17: const CHECKED_TARGETS_PARSER_REGEX = /^\s*- \[x\] (\S+)/gim;
18:
19: async function detailsFromContext({ context }) {
20: if (!context || !context.payload || !context.payload.issue) {
21: throw new Error("Issue context is not defined");
22: }
23:
24: const titleParser =
25: /^publish: (?:getsentry\/)?(?<repo>[A-Za-z0-9_.-]+)(?<path>\/[\w./-]+)?(?: \[workspace: (?<workspace>"(?:[^"\\]|\\.)*")\] )?@(?<version>[\w.+-]+)$/;
26: const titleMatch = context.payload.issue.title.match(titleParser);
27: if (!titleMatch || !titleMatch.groups) {
28: throw new Error(
29: `Invalid publish issue title: '${context.payload.issue.title}'`
30: );
31: }
32: const { workspace: workspaceJson, ...titleDetails } = titleMatch.groups;
33: let workspace = "";
34: ...
CRITICAL: None.
MAJOR
State prepopulation diverges for valid workspace GitHub overrides.
Craft permits a workspace to override github.owner/repo (src/schemas/project_config.ts:204-211) and uses that resolved config to name its state file (src/commands/publish.ts:697-701). Publish always prepopulates and later reads a getsentry/<title repo> filename (.github/workflows/publish.yml:221-230,297).
A workspace that overrides GitHub identity will not see checked targets, and the failure handler will not restore completed targets. Retries can re-publish targets.
Unicode bidi-format characters create unreadable, deceptive workspace titles.
Both validators reject only Cc, Zl, and Zp (action.yml:171-174; src/modules/details-from-context.js:34-40). They accept U+202E and other Cf characters. The title writer emits workspace JSON directly (action.yml:258-265), so a controller can create a visually misleading approval title that still parses and reaches CRAFT_WORKSPACE.
Invalid workspace input is validated after composite-action side effects.
action.yml:74-158 can query/cancel workflows, set environment state, download artifacts, and install Craft before the workspace check at action.yml:171-174. This fails the required reject-before-side-effects invariant. The new test only runs the isolated Craft Prepare shell step (src/__tests__/action.test.ts:56-80,103-110), so it cannot catch ordering regressions.
MINOR: None.
Verified
publish: repo/path@version (action.yml:258-265).CRAFT_WORKSPACE, and the failure handler path.--workspace=<value>. ...Date: Aug 25, 2026 * 🟡 (17:20) `src/config.ts` lines 471–514 define cached async `getGlobalGitHubConfig(clearCache = false): Promise<GitHubGlobalConfig>`: it returns the cached configuration unless cleared; a cached `null` throws `ConfigurationError('GitHub configuration not found in the config file and cannot be determined from Git')`; otherwise it reads top-level `getConfiguration(clearCache).…
Date: Aug 25, 2026 * 🟡 (17:13) `/home/byk/Code/getsentry/craft-workspace-action-propagation/package.json` identifies Craft as `@sentry/craft` version `2.31.0-dev.0`, with CLI bins `craft` and `sentry-craft` both mapped to `dist/craft`; Node `24.18.0` and pnpm `10.27.0` are pinned through Volta. * 🟡 (17:13) Craft package scripts: `build:fat` = `tsc -p tsconfig.build.json`; `build:watch` = `tsc -…
Date: Aug 25, 2026 * 🟡 (17:09) `src/index.ts` imports `extractWorkspaceSelection` from `./utils/helpers` and `setActiveWorkspace` from `./config`; after `fixGlobalBooleanFlags(process.argv.slice(2))`, it calls `setActiveWorkspace(extractWorkspaceSelection(argv))` before yargs parsing/builders, because command builders can resolve config (notably `publish` derives `--target` choices from `config.…
Date: Aug 25, 2026 * 🔴 (17:06) User/project requirement: a following option such as `--workspace --dry-run` is never mistaken for a workspace name. * 🟡 (17:06) Search results in `/home/byk/Code/getsentry/craft-workspace-action-propagation` identified workspace-related implementation in `src/utils/workspaces.ts`, publish-resume state isolation in `src/utils/publishState.ts`, raw CLI workspace ex…
Date: Aug 25, 2026 * 🔴 (17:05) User/project directive: the CI poller always adds the `ci-ready` label after checking CI; when `ci-ready` was already present, `waiting-for-ci` removes it first so a fresh `ci-ready` labeled event triggers. * 🟡 (17:05) `.github/workflows/publish.yml` `publish` job is gated to run only for open issues whose triggering label is `ci-ready`, which also have `accepted`…
Date: Aug 25, 2026 * 🔴 (17:05) User/project directive: always throw for unexpected values in switch statements; use a `default` case that throws a descriptive error such as `throw new Error(\`Unknown status: '${status}'\`)`. * 🟢 (17:05) Publish repository guidance in `/home/byk/Code/getsentry/publish-workspace-acceptance/AGENTS.md`: it is the Sentry Publish Repository, a GitHub Actions approval…
Date: Aug 25, 2026 * 🟡 [requested-review] (17:01) User requested a read-only adversarial review with no edits of uncommitted changes in `/home/byk/Code/getsentry/craft-workspace-action-propagation` versus `origin/master` and `/home/byk/Code/getsentry/publish-workspace-acceptance` versus `origin/main`. Required end-to-end verification of: (1) legacy title and state-filename byte compatibility whe…