Dashboard › craft › Session 0PGLiyEaZV8D
0PGLiyEaZV8DN2YfGConduct a fresh, rigorous, read-only adversarial review of the CURRENT uncommitted changes in BOTH worktrees. Do not modify files.
Craft: /home/byk/Code/getsentry/craft-workspace-action-propagation, branch feat/workspace-action-propagation, base 21270a1. Publish: /home/byk/Code/getsentry/publish-workspace-acceptance, branch feat/workspace-acceptance, base 83d210b.
Prior review found a critical invalid action.yml mapping (WORKSPACE outside env) and weak tests. Those should now be fixed. Inspect actual full diffs, surrounding code, action/workflow YAML structures, and regression tests. Validate with exact file:line evidence:
action.yml remains a valid composite-action manifest, and an invalid workspace is rejected BEFORE every side effect. Ensure WORKSPACE wiring reaches Craft Prepare and Read Craft Targets.Findings first, severity ordered; give PASS/FAIL for all five; cite exact lines; conclude MERGE or DO-NOT-MERGE. Do not provide general praise.
<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/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 ...
<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>
<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>
M .github/workflows/release.yml M action.yml M src/commands/__tests__/publish.test.ts M src/commands/publish.ts ?? src/__tests__/action.test.ts .github/workflows/release.yml | 9 +++++++ action.yml | 35 ++++++++++++++++++++++--- src/commands/__tests__/publish.test.ts | 47 ++++++++++++++++++++++++++++++++++ src/commands/publish.ts | 33 ++++++++++++++++++++++-- 4 files changed, 119 insertions(+), 5 deletions(-) M .github/workflows/release.yml M action.yml M src/commands/__tests__/publish.test.ts M src/commands/publish.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 ?? src/modules/__tests__/publish-workflow.js .github/workflows/publish.yml | 27 +++- src/modules/__tests__/details-from-context.js | 212 +++++++++++++++++++++++++- src/modules/__tests__/update-issue.js | 15 +- src/modules/details-from-context.js | 27 +++- src/modules/update-issue.js | 54 ++++--- 5 files changed, 295 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
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 ...
<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: ...
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/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. ...
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/index.ts</path>
<type>file</type>
<content>
60: * not via the positional argument notation (`--flag no`). The only way to do
61: * this is to define them as string arguments and then _inject_ a truthy string
62: * if we notice the flag is passed standalone (ie `--flag`).
63: * @param argv The raw process.argv array
64: * @returns The processed, injected version of the argv array to pass to yargs
65: */
66: function fixGlobalBooleanFlags(argv: string[]): string[] {
67: const result = [];
68: for (const arg of argv) {
69: result.push(arg);
70: if (arg.slice(2) in GLOBAL_BOOLEAN_FLAGS) {
71: result.push('1');
72: }
73: }
74: return result;
75: }
76:
77: /**
78: * Main entrypoint
79: */
80: async function main(): Promise<void> {
81: // Strip dynamic-linker env vars (LD_PRELOAD, DYLD_*, ...) before anything
82: // else so they cannot leak into subprocesses Craft spawns. ...
rg: regex parse error:
(?:\p\{C|\p\{Z|Unicode|control)
^
error: invalid Unicode character class
Found 7 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/utils/helpers.ts:
Line 65: // `--workspace=-foo` is a valid inline value; `--workspace --foo` is not.
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/config.ts:
Line 197: * Applies workspace selection + validation to a freshly-parsed config.
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts:
Line 67: // at parse time (e.g. missing/invalid file, or a workspaces config with no
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/__tests__/action.test.ts:
Line 126: expect(getActionSteps()[0]?.name).toBe('Validate workspace');
Line 128: runActionStep('Validate workspace', workspace, environment).status,
Line 141: runActionStep('Validate workspace', workspace, environment).status,
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/targets/npm.ts:
Line 219: // Validate: public packages ...
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/config.ts</path>
<type>file</type>
<content>
150: if (mergedGithub.owner && mergedGithub.repo) {
151: resolved.github = mergedGithub as GitHubGlobalConfig;
152: } else {
153: delete (resolved as { github?: unknown }).github;
154: }
155: } else {
156: (resolved as Record<string, unknown>)[key] = value;
157: }
158: }
159:
160: return resolved;
161: }
162:
163: /**
164: * Pure check: is `minVersionRaw` (a configured minVersion) >= `requiredVersion`?
165: *
166: * Unlike `requiresMinVersion`, this does not read the (possibly not-yet-resolved)
167: * global configuration, so it is safe to call during config resolution.
168: */
169: function isVersionGteMinVersion(
170: minVersionRaw: string | undefined,
171: requiredVersion: string,
172: ): boolean {
173: if (!minVersionRaw) {
174: return false;
175: }
176: const configuredMinVersion = ...
Found 3 matches /home/byk/Code/getsentry/craft-workspace-action-propagation/src/schemas/project_config.ts: Line 171: * unit) and each entry under the top-level `workspaces` map (an explicit, Line 176: * different concept from the `npm` target's `workspaces: true` field, which Line 232: workspaces: z.record(z.string(), WorkspaceSchema).optional(),
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/schemas/project_config.ts</path>
<type>file</type>
<content>
130: */
131: export const CalVerConfigSchema = z.object({
132: /**
133: * Days to go back for date calculation (default: 14)
134: */
135: offset: z.number().optional(),
136: /**
137: * strftime-like format for date part (default: %y.%-m).
138: * Supports: %y (2-digit year), %m (zero-padded month), %-m (month without padding)
139: */
140: format: z.string().optional(),
141: });
142:
143: export type CalVerConfig = z.infer<typeof CalVerConfigSchema>;
144:
145: /**
146: * Version resolution configuration
147: */
148: export const VersioningConfigSchema = z.object({
149: policy: z.enum(['auto', 'manual', 'calver']).optional(),
150: calver: CalVerConfigSchema.optional(),
151: });
152:
153: export type VersioningConfig = z.infer<typeof VersioningConfigSchema>;
154:
155: /**
156: * Changelog configuration
157: */
158: export ...
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
@@ -87,226 +87,237 @@ 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. ...
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-workflow.js</path>
<type>file</type>
<content>
1: import { spawnSync } from "child_process";
2: import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
3: import { tmpdir } from "os";
4: import { join } from "path";
5:
6: import { afterEach, expect, test } from "vitest";
7:
8: const temporaryDirectories = [];
9:
10: function getSetTargetsScript() {
11: const workflow = readFileSync(
12: join(__dirname, "../../../.github/workflows/publish.yml"),
13: "utf8"
14: );
15: const section = workflow.match(
16: / {6}- name: Set targets[\s\S]*? {8}run: \|\n(?<script>[\s\S]*?)\n {6}- uses: docker:\/\/getsentry\/craft:latest/
17: );
18: if (!section?.groups?.script) {
19: throw new Error("Missing Set targets workflow script");
20: }
21: return section.groups.script.replace(/^ {10}/gm, "");
22: }
23:
24: function runSetTargets({ path, repo, version, workspace = ...
<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/vitest.config.mts</path>
<type>file</type>
<content>
1: import { defineConfig } from 'vitest/config';
2:
3: export default defineConfig({
4: test: {
5: globals: true,
6: environment: 'node',
7: include: ['src/**/*.test.ts'],
8: exclude: ['**/node_modules/**', '**/dist/**', '**/fixtures/**'],
9: testTimeout: 30000,
10: alias: {
11: '^marked$': 'marked/lib/marked.umd.js',
12: },
13: },
14: });
(End of file - total 14 lines)
</content>
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/vitest.config.js</path>
<type>file</type>
<content>
1: import { defineConfig } from "vitest/config";
2:
3: export default defineConfig({
4: test: {
5: globals: true,
6: environment: "node",
7: clearMocks: true,
8: include: ["src/**/__tests__/**/*.js"],
9: },
10: });
(End of file - total 10 lines)
</content>
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/publish.yml</path>
<type>file</type>
<content>
135: id: inputs
136: run: node .__publish__/src/publish/inputs.js
137:
138: - name: Inform start
139: if: steps.inputs.outcome == 'success'
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. ...
Found 16 matches
/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: extractWorkspaceSelection(['--workspace', '-cli'], NO_ENV),
Line 67: extractWorkspaceSelection(['--workspace', 'cli'], {
Line 75: extractWorkspaceSelection(
Line 84: extractWorkspaceSelection(
Line 93: extractWorkspaceSelection(['publish'], {
Line 102: extractWorkspaceSelection(['publish', '--workspace', '--dry-run'], {
Line 107: extractWorkspaceSelection(
Line 116: ...
<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 ...
<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/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>
RUN v4.1.8 /home/byk/Code/getsentry/craft-workspace-action-propagation
Test Files 3 passed (3)
Tests 77 passed (77)
Start at 13:57:34
Duration 2.27s (transform 1.04s, setup 0ms, import 2.85s, tests 397ms, environment 0ms)
yarn run v1.22.22
$ /home/byk/Code/getsentry/publish-workspace-acceptance/node_modules/.bin/vitest run src/modules/__tests__/details-from-context.js src/modules/__tests__/update-issue.js src/modules/__tests__/publish-workflow.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 3 passed (3)
Tests 18 passed (18)
Start at 13:57:44
Duration 383ms (transform 100ms, setup 0ms, import 186ms, tests 110ms, environment 0ms)
Done in 0.93s.
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/update-issue.js</path>
<type>file</type>
<content>
1: const { updateIssue } = require('../modules/update-issue.js');
2: const {getGitHubToken} = require('../libs/github');
3: const github = require('@actions/github');
4:
5: const context = github.context;
6: const octokit = github.getOctokit(getGitHubToken());
7: const inputs = JSON.parse(process.env.PUBLISH_ARGS);
8:
9: updateIssue({ context, octokit, inputs });
(End of file - total 9 lines)
</content>
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>
430: export function requiresMinVersion(requiredVersion: string): boolean {
431: const config = getConfiguration();
432: return isVersionGteMinVersion(config.minVersion, requiredVersion);
433: }
434:
435: /** Minimum craft version required for auto-versioning and CalVer */
436: const AUTO_VERSION_MIN_VERSION = '2.14.0';
437:
438: /**
439: * Returns the effective versioning policy for the project.
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 ...
M .github/workflows/release.yml M action.yml M src/commands/__tests__/publish.test.ts M src/commands/publish.ts ?? 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 ?? src/modules/__tests__/publish-workflow.js
> @sentry/craft@2.31.0-dev.0 test /home/byk/Code/getsentry/craft-workspace-action-propagation > vitest run 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"... ...
yarn run v1.22.22
$ vitest run
(!) 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 6 passed (6)
Tests 25 passed (25)
Start at 13:59:39
Duration 2.26s (transform 416ms, setup 0ms, import 2.04s, tests 442ms, environment 1ms)
Done in 3.61s.
<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 ...
(no output)
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts</path>
<type>file</type>
<content>
135: description: 'Ignore local git changes and unsynchronized remotes',
136: type: 'boolean',
137: })
138: .check(checkVersion)
139: .demandOption('new-version', 'Please specify the version to publish');
140: };
141:
142: /** Command line options. */
143: export interface PublishOptions {
144: /** The git remote to use when pushing */
145: remote: string;
146: /** Revision to publish (can be commit, tag, etc.) */
147: rev?: string;
148: /** Target branch to merge the release into, auto detected when empty */
149: mergeTarget?: string;
150: /** One or more targets we want to publish */
151: target?: string | string[];
152: /** The new version to publish */
153: newVersion: string;
154: /** Do not perform merge after publishing */
155: noMerge: boolean;
156: /** Do not remove downloads after publishing */
157: ...
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/publish.ts</path>
<type>file</type>
<content>
680: }
681:
682: const revision = await git.revparse('HEAD');
683: logger.debug('Revision to publish: ', revision);
684:
685: const statusProvider = await getStatusProviderFromConfig();
686: const artifactProvider = await getArtifactProviderFromConfig();
687:
688: // Check status of all CI builds linked to the revision
689: await checkRevisionStatus(statusProvider, revision, argv.noStatusCheck);
690:
691: await printRevisionSummary(artifactProvider, revision);
692:
693: await checkRequiredArtifacts(artifactProvider, revision, config.requireNames);
694:
695: // Find targets
696: let targetsToPublish: Set<string> = new Set(
697: (typeof argv.target === 'string' ? [argv.target] : argv.target) || [
698: SpecialTarget.All,
699: ],
700: );
701:
702: // Treat "all"/"none" specially
703: for (const specialTarget of ...
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 ...
M .github/workflows/release.yml M action.yml M src/commands/__tests__/publish.test.ts M src/commands/publish.ts ?? 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 ?? src/modules/__tests__/publish-workflow.js
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/details-from-context.js</path>
<type>file</type>
<content>
1: /**
2: * Matches the entire "Targets" section of a github publish issue body.
3: */
4: const TARGETS_SECTION_PARSER_REGEX =
5: /^(?!### Targets$\s)(?: *- \[[ xX]\] \S+\s*$(?:\r?\n)?)+/m;
6:
7: /**
8: * Matches all targets of a github publish issue body in a section that was already matched and extracted with `TARGETS_PARSER_REGEX`.
9: * The "id" of the targets is captured within a capture group.
10: */
11: const TARGETS_PARSER_REGEX = /^\s*- \[[ x]\] (\S+)/gim;
12:
13: /**
14: * Matches checked targets of a github publish issue body in a section that was already matched and extracted with `TARGETS_PARSER_REGEX`.
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 || ...
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/details-from-context.js</path>
<type>file</type>
<content>
70: issue: {
71: number: "223",
72: title: "publish: getsentry/sentry@21.3.1",
73: body: `
74: Requested by: @BYK
75: Merge target: (default)
76: Quick links:
77: - [View changes](https://github.com/getsentry/sentry/compare/21.3.0...refs/heads/releases/21.3.1)
78: - [View check runs](https://github.com/getsentry/sentry/commit/7e5ca7ed5581552de066e2a8bc295b8306be38ac/checks/)
79: Assign the **accepted** label to this issue to approve the release.
80: ### Targets\r
81: - [x] github\r
82: - [ ] pypi\r
83: - [ ] docker[release]
84: - [x] docker[latest]\r
85: `,
86: labels: ["accepted"],
87: },
88: },
89: },
90: };
91:
92: test("Do not extract merge_target value if its a default value", async () => {
93: const result = await detailsFromContext(defaultTargetInputsArgs);
94: ...
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/update-issue.js</path>
<type>file</type>
<content>
1: const fs = require("fs");
2: const {
3: TARGETS_SECTION_PARSER_REGEX,
4: TARGETS_PARSER_REGEX,
5: } = require("./details-from-context");
6:
7: async function updateTargets({
8: octokit,
9: stateFilePath,
10: publishRepo,
11: issue_number,
12: }) {
13: if (!stateFilePath || !fs.existsSync(stateFilePath)) {
14: return;
15: }
16:
17: const issueRequest = octokit.rest.issues.get({
18: ...publishRepo,
19: issue_number,
20: });
21:
22: const craftStateRequest = fs.promises
23: .readFile(stateFilePath, { encoding: "utf-8" })
24: .then((data) => JSON.parse(data));
25:
26: const [{ data: issue }, craftState] = await Promise.all([
27: issueRequest,
28: craftStateRequest,
29: ]);
30:
31: const newIssueBody = transformIssueBody(craftState, issue.body);
32:
33: await octokit.rest.issues.update({
34: ...
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/commands/__tests__/publish.test.ts</path>
<type>file</type>
<content>
115: }
116: }
117: } finally {
118: for (const [key, val] of Object.entries(before)) {
119: if (val === undefined) {
120: delete process.env[key];
121: } else {
122: process.env[key] = val;
123: }
124: }
125: }
126: });
127:
128: test('forwards GITHUB_* and RUNNER_* by prefix, not credential-named vars', async () => {
129: const before = {
130: GITHUB_RUN_ID: process.env.GITHUB_RUN_ID,
131: GITHUB_REPOSITORY: process.env.GITHUB_REPOSITORY,
132: RUNNER_OS: process.env.RUNNER_OS,
133: NPM_TOKEN: process.env.NPM_TOKEN,
134: DOCKER_PASSWORD: process.env.DOCKER_PASSWORD,
135: };
136: process.env.GITHUB_RUN_ID = '9876';
137: process.env.GITHUB_REPOSITORY = 'getsentry/sentry-cocoa';
138: process.env.RUNNER_OS = ...
None.
PASS — action manifest and early rejection
action.yml:71-83; WORKSPACE is correctly nested in each step’s env.gh, Git config, downloads, or Craft: action.yml:74-83, followed by first side effect at :84-94.action.yml:170-213..github/workflows/release.yml:122-150.src/__tests__/action.test.ts:93-144.PASS — both ingress paths reject unsafe Unicode
Cc, Cf, Zl, and Zp: action.yml:74-82.publish/.../details-from-context.js:24-40.workspace; empty action input remains accepted: details-from-context.js:68-75, tests at details-from-context.test.js:92-102 and action.test.ts:135-143.details-from-context.test.js:145-162; unsafe controls, bidi, Zl, and Zp at :181-293.PASS — state identity matches without changing publishing identity
action.yml:263-270.publish.yml:191-233; Craft receives it only as CRAFT_PUBLISH_STATE_GITHUB_REPO: publish.yml:255-258.getPublishStatePath: src/commands/publish.ts:715-731; the override parser is strict: :177-195.publish.yml:214-230, src/utils/publishState.ts:82-99.publish-workflow.js:57-81.PASS — option-looking workspace values remain one option value
--workspace=$WORKSPACE: action.yml:185-213. ...Date: Aug 26, 2026 * 🟡 (14:02) Inspected `/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/update-issue.js` (84 lines). `updateTargets({ octokit, stateFilePath, publishRepo, issue_number })` returns without action if `stateFilePath` is absent or does not exist; otherwise it concurrently fetches the issue through `octokit.rest.issues.get(...)` and reads/parses the state JSON with…
Date: Aug 26, 2026 * 🟡 (13:59) Full `craft-workspace-action-propagation` test suite passed with Vitest `v4.1.8`: 60 test files passed; 1138 tests passed, 1 skipped (1139 total); duration `43.22s` (transform `3.91s`, import `71.00s`, tests `34.76s`). Test logs exercised GitHub-release edge cases: orphaned draft `v1.0.0` deletion, cleanup failure handling, published-release detection after `create…
Date: Aug 26, 2026 * 🟡 (13:57) Inspected `craft-workspace-action-propagation/src/utils/__tests__/helpers.test.ts` lines 1–160. `extractWorkspaceSelection` tests define: no CLI flag or `CRAFT_WORKSPACE` returns `undefined`; `--workspace cli` returns `cli`; `--workspace=mcp` returns `mcp`; `--workspace=-cli` accepts `-cli` but separated `--workspace -cli` returns `undefined`; CLI selection overrid…
Date: Aug 26, 2026 * 🟡 (13:56) Inspected `publish-workspace-acceptance/.github/workflows/publish.yml` lines 135–323. The workflow runs `node .__publish__/src/publish/inputs.js` (`id: inputs`) and, upon successful input processing, runs `node .__publish__/src/publish/post-workflow-details.js` with `GITHUB_TOKEN`. * 🟡 (13:56) `Set target repo checkout branch` condition selects a protected merge-t…
Date: Aug 26, 2026 * 🟡 (13:55) Inspected `publish-workspace-acceptance/src/modules/__tests__/publish-workflow.js`: `getSetTargetsScript()` reads `../../../.github/workflows/publish.yml` and extracts the `Set targets` shell block via regex up to `uses: docker://getsentry/craft:latest`; it throws `Missing Set targets workflow script` if extraction fails and strips 10-space indentation. * 🟡 (13:55…
Date: Aug 26, 2026 * 🔴 (13:54) User asserted that a following CLI option such as `--workspace --dry-run` must never be mistaken for a workspace name. * 🟡 (13:54) Inspected `src/utils/helpers.ts`: `extractWorkspaceSelection(argv, env)` uses Node `parseArgs()` with `options: { workspace: { type: 'string } }`, `allowPositionals: true`, `strict: false`, and `tokens: true` to resolve `--workspace` b…
Date: Aug 26, 2026 * 🔴 (13:54) User directive reaffirmed: Always use `pnpm` for package management. * 🔴 (13:54) User directive reaffirmed: Never use `npm` or `yarn`. * 🟡 (13:54) Craft added untracked test file `src/__tests__/action.test.ts` (144 lines), importing Node `fs`, `os`, `path`, `child_process`, `js-yaml`, and Vitest to execute individual composite-action shell steps from `action.yml`…
Date: Aug 26, 2026 * 🔴 (13:53) User directive: Always use `pnpm` for package management. * 🔴 (13:53) User directive: Never use `npm` or `yarn`. * 🔴 (13:53) User directive: Always throw for unexpected values. * 🔴 [requested-read-only-review] (13:53) User requested a fresh, rigorous, read-only adversarial review of CURRENT uncommitted changes in both worktrees; explicitly instructed not to modi…