Dashboard › craft › Session 1LEu2NJkHyTa
1LEu2NJkHyTa0kBztRead-only research in current Craft master: map the GitHub Action layer relevant to craft prepare/publish, especially inputs/outputs, issue title/body/labels/state keys, scripts/workflows, and tests. Do not edit. Return a concise file:line-cited map of how a new workspace selection could be propagated safely, including backward compatibility risks and exact likely touchpoints.
No files found
/home/byk/Code/getsentry/craft/pnpm-lock.yaml /home/byk/Code/getsentry/craft/package.json /home/byk/Code/getsentry/craft/action.yml /home/byk/Code/getsentry/craft/build.mjs /home/byk/Code/getsentry/craft/tsconfig.build.json /home/byk/Code/getsentry/craft/tsconfig.json /home/byk/Code/getsentry/craft/eslint.config.mjs /home/byk/Code/getsentry/craft/.prettierrc.yml /home/byk/Code/getsentry/craft/.craft.yml /home/byk/Code/getsentry/craft/src/index.ts /home/byk/Code/getsentry/craft/src/config.ts /home/byk/Code/getsentry/craft/src/logger.ts /home/byk/Code/getsentry/craft/src/instrument.ts /home/byk/Code/getsentry/craft/src/utils/publishState.ts /home/byk/Code/getsentry/craft/src/utils/helpers.ts /home/byk/Code/getsentry/craft/src/utils/git.ts /home/byk/Code/getsentry/craft/src/utils/releaseCommandEnv.ts /home/byk/Code/getsentry/craft/src/utils/system.ts /home/byk/Code/getsentry/craft/src/utils/gpg.ts /home/byk/Code/getsentry/craft/src/utils/env.ts /home/byk/Code/getsentry/craft/src/utils/dyn...
Found 40 matches
/home/byk/Code/getsentry/craft/action.yml:
Line 21: publish_repo:
Line 22: description: Repository for publish issues (owner/repo format)
Line 64: issue_url:
Line 65: description: The URL of the created publish request issue
Line 66: value: ${{ steps.request-publish.outputs.issue_url }}
Line 78: if [[ "$FORCE_INPUT" != 'true' ]] && gh issue list -l "$BLOCKER_LABEL_INPUT" -s open | grep -q '^[0-9]\+[[:space:]]'; then
Line 79: echo "::error::Open release-blocking issues found (label: $BLOCKER_LABEL_INPUT), cancelling release..."
Line 182: craft prepare "${VERSION_ARG[@]}" "${CRAFT_ARGS[@]}"
Line 194: echo "targets<<EOF" >> "$GITHUB_OUTPUT"
Line 195: echo "$targets" >> "$GITHUB_OUTPUT"
Line 196: echo "EOF" >> "$GITHUB_OUTPUT"
Line 198: - name: Request publish
Line 199: id: request-publish
Line 213: PUBLISH_REPO: ${{ inputs.publish_repo || ...
Found 100 matches (more matches available) /home/byk/Code/getsentry/craft/src/index.ts: Line 18: import * as prepare from './commands/prepare'; Line 19: import * as publish from './commands/publish'; Line 91: .command(prepare) Line 92: .command(publish) /home/byk/Code/getsentry/craft/src/config.ts: Line 255: * is provided to `craft prepare`: Line 502: * Returns whether the release branch should be merged after publishing. Line 571: * to implement their own expansion logic (e.g., npm workspace expansion). /home/byk/Code/getsentry/craft/src/schemas/project_config.ts: Line 187: * Do not merge the release branch after publishing. /home/byk/Code/getsentry/craft/src/utils/publishState.ts: Line 2: * Helpers for locating Craft's publish-state file in a path that is NOT Line 3: * writable by the repository being published. Line 5: * Background: `craft publish` writes a small JSON file listing targets Line 7: * existed, the file lived at ...
<path>/home/byk/Code/getsentry/craft/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. ...
No files found
<path>/home/byk/Code/getsentry/craft/src/utils/helpers.ts</path>
<type>file</type>
<content>
1: import { appendFileSync, mkdirSync, writeFileSync } from 'fs';
2: import path from 'path';
3:
4: import prompts from 'prompts';
5: import { logger, LogLevel, setLevel } from '../logger';
6:
7: /**
8: * Maximum size (in bytes) for step output values passed through GITHUB_OUTPUT.
9: * Values exceeding this are truncated to avoid E2BIG errors when GitHub Actions
10: * expands them into environment variables for subsequent steps.
11: *
12: * 64 KB is well under the ~2 MB ARG_MAX kernel limit and also under GitHub's
13: * ~65 536-character issue body limit, so truncated changelogs still render.
14: */
15: export const MAX_STEP_OUTPUT_BYTES = 64 * 1024;
16:
17: const FALSY_ENV_VALUES = new Set(['', 'undefined', 'null', '0', 'false', 'no']);
18: export function envToBool(envVar: unknown): boolean {
19: const normalized = String(envVar).toLowerCase();
20: return ...
<path>/home/byk/Code/getsentry/craft/src/commands/prepare.ts</path>
<type>file</type>
<content>
1: import { existsSync, promises as fsPromises } from 'fs';
2: import { join, relative } from 'path';
3:
4: import * as shellQuote from 'shell-quote';
5: import type { SimpleGit, StatusResult } from 'simple-git';
6: import type { Arguments, Argv, CommandBuilder } from 'yargs';
7: import { createDryRunIsolation, safeFs } from '../utils/dryRun';
8:
9: import {
10: CONFIG_FILE_NAME,
11: DEFAULT_RELEASE_BRANCH_NAME,
12: getConfigFileDir,
13: getConfiguration,
14: getGitTagPrefix,
15: getGlobalGitHubConfig,
16: getVersioningPolicy,
17: loadConfigurationFromString,
18: requiresMinVersion,
19: } from '../config';
20: import { logger } from '../logger';
21: import {
22: ChangelogPolicy,
23: type TargetConfig,
24: VersioningPolicy,
25: } from '../schemas/project_config';
26: import { sleep } from '../utils/async';
27: import {
28: type BumpType,
29: ...
Found 65 matches /home/byk/Code/getsentry/craft/.lore.md: Line 38: * **getsentry/publish poller: active-polling via self-dispatch, cron as fallback**: GitHub Actions \`\*/5\` cron drifts to 30-40 min under load, stalling releases with fast CI. \`ci-poller.yml\` uses self-dispatch: when pending issues remain, it \`gh workflow run\`s itself (cap 60 attempts ~30min). Concurrency group \`ci-status-poller\` with \`cancel-in-progress: false\` queues runs — GHA startup gives ~30-60s between checks. Chain starts via \`waiting-for-ci\` job in \`publish.yml\` when \`accepted\` label is added. Cron is safety net (also skipped when \`CI\_POLLER\_HAS\_PENDING == 'false'\`). Zero idle cost — no chain running unless human action occurred. Self-dispatch step must guard on \`steps.token.outcome == 'success'\` and \`steps.remaining.outcome == 'success'\` to avoid dispatching with empty token. ...
<path>/home/byk/Code/getsentry/craft/src/commands/prepare.ts</path> <type>file</type> <content> 875: typeof config.changelog === 'string' 876: ? config.changelog 877: : config.changelog?.filePath; 878: // Get policy from new format or legacy changelogPolicy 879: const changelogPolicy = ( 880: typeof config.changelog === 'object' && config.changelog?.policy 881: ? config.changelog.policy 882: : config.changelogPolicy 883: ) as ChangelogPolicy | undefined; 884: const changelogBody = await prepareChangelog( 885: git, 886: oldVersion, 887: newVersion, 888: argv.noChangelog ? ChangelogPolicy.None : changelogPolicy, 889: changelogPath, 890: ); 891: 892: // Explicitly stage the changelog file so it is committed even when no 893: // pre-release command runs. git-add on an unmodified file is a no-op. ...
<path>/home/byk/Code/getsentry/craft/src/commands/targets.ts</path>
<type>file</type>
<content>
1: import { getConfiguration, expandWorkspaceTargets } from '../config';
2: import { formatJson } from '../utils/strings';
3: import { getAllTargetNames } from '../targets';
4: import { BaseTarget } from '../targets/base';
5:
6: export const command = ['targets'];
7: export const description = 'List defined targets as JSON array';
8:
9: export async function handler(): Promise<any> {
10: let definedTargets = getConfiguration().targets || [];
11:
12: // Expand workspace targets (e.g., npm workspaces)
13: definedTargets = await expandWorkspaceTargets(definedTargets);
14:
15: const possibleTargetNames = new Set(getAllTargetNames());
16: const allowedTargetNames = definedTargets
17: .filter(target => target.name && possibleTargetNames.has(target.name))
18: .map(BaseTarget.getId);
19:
20: console.log(formatJson(allowedTargetNames));
21: }
(End of file - total 21 ...
Found 1 matches /home/byk/Code/getsentry/craft/src/config.ts: Line 571: * to implement their own expansion logic (e.g., npm workspace expansion).
Found 18 matches
/home/byk/Code/getsentry/craft/src/commands/__tests__/prepare.test.ts:
Line 225: e: 'Invalid version or version part specified: "v2.3.3". Removing the "v" prefix will likely fix the issue',
/home/byk/Code/getsentry/craft/src/commands/__tests__/targets.test.ts:
Line 11: import { handler } from '../targets';
Line 18: vi.mock('../../targets', () => ({
Line 23: import { getAllTargetNames } from '../../targets';
Line 25: describe('targets command', () => {
Line 40: test('lists targets without expansion when no workspaces', async () => {
Line 41: const targets = [{ name: 'npm' }, { name: 'github' }];
Line 43: mockedGetConfiguration.mockReturnValue({ targets });
Line 44: mockedExpandWorkspaceTargets.mockResolvedValue(targets);
Line 49: expect(mockedExpandWorkspaceTargets).toHaveBeenCalledWith(targets);
Line 55: test('lists expanded workspace targets', async () => {
Line 67: ...
Found 23 matches
/home/byk/Code/getsentry/craft/src/utils/__tests__/helpers.test.ts:
Line 12: truncateForOutput,
Line 13: writeGitHubActionsFile,
Line 43: outputFile = path.join(dir, 'GITHUB_OUTPUT');
Line 44: process.env.GITHUB_OUTPUT = outputFile;
Line 70: test('is a no-op when GITHUB_OUTPUT is not set', () => {
Line 71: delete process.env.GITHUB_OUTPUT;
Line 77: describe('writeGitHubActionsFile', () => {
Line 85: outputFile = path.join(tempDir, 'GITHUB_OUTPUT');
Line 88: process.env.GITHUB_OUTPUT = outputFile;
Line 99: const filePath = writeGitHubActionsFile('changelog', 'hello world');
Line 106: const filePath = writeGitHubActionsFile('changelog', 'content');
Line 108: expect(output).toContain(`changelog_file=${filePath}`);
Line 113: const result = writeGitHubActionsFile('changelog', 'content');
Line 120: writeGitHubActionsFile('test', 'data');
Line 125: describe('truncateForOutput', () => ...
<path>/home/byk/Code/getsentry/craft/.opencode/plans/workspaces-redesign-design.md</path>
<type>file</type>
<content>
75: - Model after `VersioningConfigSchema`/`ChangelogConfigSchema` (`project_config.ts:131-165`).
76: - **Backward compatible**: if `workspaces` is absent, everything behaves exactly as today
77: (single implicit workspace = the top-level config).
78: - `minVersion` gating like `AUTO_VERSION_MIN_VERSION` (`config.ts:249`).
79:
80: ## Selector
81:
82: - CLI: global `--workspace <name>` option; env `CRAFT_WORKSPACE` works automatically via
83: yargs `.env('CRAFT')` (`index.ts:90`). Also accept it on `prepare`/`publish`/`targets`.
84: - Resolution: `getConfiguration()` gains a workspace-aware view. Introduce
85: `getActiveWorkspaceConfig(name?)` that merges top-level defaults with the selected
86: workspace and returns a normalized config object with the SAME shape the rest of the code
87: already consumes. ...
<path>/home/byk/Code/getsentry/craft/src/commands/__tests__/targets.test.ts</path>
<type>file</type>
<content>
1: import {
2: vi,
3: describe,
4: test,
5: expect,
6: beforeEach,
7: afterEach,
8: type Mock,
9: type MockInstance,
10: } from 'vitest';
11: import { handler } from '../targets';
12:
13: vi.mock('../../config', () => ({
14: getConfiguration: vi.fn(),
15: expandWorkspaceTargets: vi.fn(),
16: }));
17:
18: vi.mock('../../targets', () => ({
19: getAllTargetNames: vi.fn(),
20: }));
21:
22: import { getConfiguration, expandWorkspaceTargets } from '../../config';
23: import { getAllTargetNames } from '../../targets';
24:
25: describe('targets command', () => {
26: const mockedGetConfiguration = getConfiguration as Mock;
27: const mockedExpandWorkspaceTargets = expandWorkspaceTargets as Mock;
28: const mockedGetAllTargetNames = getAllTargetNames as Mock;
29: let consoleSpy: MockInstance;
30:
31: beforeEach(() => {
32: vi.clearAllMocks();
33: ...
<path>/home/byk/Code/getsentry/craft/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: MAX_STEP_OUTPUT_BYTES,
11: setGitHubActionsOutput,
12: truncateForOutput,
13: writeGitHubActionsFile,
14: } from '../helpers';
15:
16: describe('envToBool', () =>
17: test.each([
18: [undefined, false],
19: [null, false],
20: [false, false],
21: ['undefined', false],
22: ['null', false],
23: ['', false],
24: ['0', false],
25: ['no', false],
26: [true, true],
27: ['true', true],
28: [1, true],
29: ['1', true],
30: ['yes', true],
31: ['dogs are great!', true],
32: ])('From %j we should get "%s"', (envVar, result) =>
33: ...
<path>/home/byk/Code/getsentry/craft/.github</path> <type>directory</type> <entries> workflows/ (1 entries) </entries>
<path>/home/byk/Code/getsentry/craft/.github/workflows</path> <type>directory</type> <entries> build.yml changelog-preview.yml docs-preview.yml enforce-license-compliance.yml image.yml lint.yml release.yml (7 entries) </entries>
<path>/home/byk/Code/getsentry/craft/.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:
16: # For external repos to call this workflow
17: workflow_call:
18: inputs:
19: version:
20: description: Version to release (semver, bump type, or "auto")
21: type: string
22: required: false
23: force:
24: description: Force a release even when there are release-blockers
25: type: string
26: required: false
27: default: 'false'
28: merge_target:
29: description: Target branch ...
Found 9 matches /home/byk/Code/getsentry/craft/.github/workflows/changelog-preview.yml: Line 33: # uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2 Line 44: # uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2 Line 283: "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \ Line 290: "repos/$GITHUB_REPOSITORY/issues/comments/$COMMENT_ID" \ Line 295: "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \ /home/byk/Code/getsentry/craft/.github/workflows/release.yml: Line 38: description: Repository for publish issues (owner/repo format) Line 81: uses: ./.github/workflows/build.yml Line 119: uses: ./ Line 130: uses: getsentry/craft@v2
<path>/home/byk/Code/getsentry/craft/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/src/commands/publish.ts</path>
<type>file</type>
<content>
50: import { getPublishStatePath } from '../utils/publishState';
51:
52: /** Default path to post-release script, relative to project root */
53: const DEFAULT_POST_RELEASE_SCRIPT_PATH = join('scripts', 'post-release.sh');
54:
55: export const command = ['publish NEW-VERSION'];
56: export const aliases = ['pp', 'publish'];
57: export const description = '🛫 Publish artifacts';
58:
59: export const builder: CommandBuilder = (yargs: Argv) => {
60: const definedTargets = getConfiguration().targets || [];
61: const possibleTargetNames = new Set(getAllTargetNames());
62: const allowedTargetNames = definedTargets
63: .filter(target => target.name && possibleTargetNames.has(target.name))
64: .map(BaseTarget.getId);
65:
66: return yargs
67: .positional('NEW-VERSION', {
68: description: 'Version to publish',
69: type: 'string',
70: })
71: .option('target', ...
/home/byk/Code/getsentry/craft/action.yml
version, merge_target, path, config source, and publish repository; there is no workspace input (:4-43).craft prepare with only optional version and --config-from (:157-182).craft targets to build the issue checklist (:184-196).issue_url from the request step (:45-66)./home/byk/Code/getsentry/craft/.github/workflows/release.yml
workflow_call, including path, but has no workspace selector (:17-58).issue_url (:59-74, :93-98).getsentry/craft@v2 (:126-142); for Craft dogfooding it invokes ./ with only version/force (:115-125).publish: ${GITHUB_REPOSITORY}${SUBDIRECTORY}@${RESOLVED_VERSION}
(/home/byk/Code/getsentry/craft/action.yml:211-213,241).
SUBDIRECTORY derives only from inputs.path./home/byk/Code/getsentry/craft/action.yml:243-255,319-327). A root-level multi-workspace release at the same version would therefore select the wrong issue.:302-308);accepted label (:310);### Targets checkbox section (:312-316)./home/byk/Code/getsentry/craft/action.yml:257-285). No label is added by this action; accepted is an external publish-pipeline contract. ...Date: Aug 25, 2026 * 🟡 (10:37) Assistant inspected `/home/byk/Code/getsentry/craft/.github/`, which contains only `workflows/`; `/home/byk/Code/getsentry/craft/.github/workflows/` contains `build.yml`, `changelog-preview.yml`, `docs-preview.yml`, `enforce-license-compliance.yml`, `image.yml`, `lint.yml`, and `release.yml`. * 🟡 (10:37) Assistant identified reusable workflow `/home/byk/Code/getse…
Date: Aug 25, 2026 * 🟡 (10:36) Workspace-redesign design specifies selector behavior: global CLI `--workspace <name>`; `CRAFT_WORKSPACE` works through yargs `.env('CRAFT')` in `index.ts:90`; selector also accepted by `prepare`, `publish`, and `targets`. `getConfiguration()` should gain workspace-aware resolution through `getActiveWorkspaceConfig(name?)`, merging top-level defaults with the chose…
Date: Aug 25, 2026 * 🟡 (10:36) Search found 23 matches in `/home/byk/Code/getsentry/craft/src/utils/__tests__/helpers.test.ts` for GitHub Actions output helpers: imports `truncateForOutput` and `writeGitHubActionsFile`; tests set `process.env.GITHUB_OUTPUT` to `path.join(dir, 'GITHUB_OUTPUT')` (line 43) and `path.join(tempDir, 'GITHUB_OUTPUT')` (line 85), and delete it for `is a no-op when GITHU…
Date: Aug 25, 2026 * 🟡 (10:35) Search found `src/config.ts:571` documentation stating that consumers can implement their own expansion logic, e.g. npm workspace expansion. * 🟡 (10:36) Search found `src/commands/__tests__/prepare.test.ts:225` expected error text: `Invalid version or version part specified: "v2.3.3". Removing the "v" prefix will likely fix the issue`. * 🟡 (10:36) Search found `s…
Date: Aug 25, 2026 * 🔴 (10:35) User directed that CalVer changelogs destined for publish issues replace `@`-mentions with bold formatting, avoiding mass contributor notifications on regular-cadence releases; committed `CHANGELOG.md` entries retain original `@`-mentions because they do not notify users. * 🟡 (10:35) `src/commands/prepare.ts:875-963` obtains `changelogPath` from `config.changelog`…
Date: Aug 25, 2026 * 🔴 (10:34) User stated that npm publish must always be verified before retrying a failed craft publish, to avoid a duplicate-publish 403. * 🔴 (10:34) User stated that the workspaces redesign’s action-layer fix—an additive publish-issue title change embedding workspace name—must ship together with the `--workspace` selector, never separately. * 🟡 (10:34) Research finding—get…
Date: Aug 25, 2026 * 🟡 (10:33) Research finding—`src/commands/prepare.ts:1-69` imports filesystem helpers (`existsSync`, `fsPromises`), path helpers (`join`, `relative`), `shell-quote`, `simple-git` types, `yargs` types, dry-run isolation (`createDryRunIsolation`, `safeFs`), configuration/versioning utilities, changelog helpers, git helpers, GitHub Actions output helpers, `buildReleaseCommandEnv…
Date: Aug 25, 2026 * 🟢 (10:29) Tool search returned “No files found.” * 🟡 (10:31) Research finding—`src/utils/helpers.ts:8-15`: `MAX_STEP_OUTPUT_BYTES` is `64 * 1024`; values sent through `GITHUB_OUTPUT` are limited to prevent Linux `E2BIG` errors when GitHub Actions expands outputs into environment variables in subsequent steps. The comment notes 64 KB is below the approximately 2 MB `ARG_MAX`…
Date: Aug 25, 2026 * 🟡 [requested-read-only-research] (10:12) User requested read-only research in the current Craft master; explicitly requested no edits. Scope: map the GitHub Action layer relevant to `craft prepare`/`craft publish`, especially inputs/outputs, issue title/body/labels/state keys, scripts/workflows, and tests; return a concise file:line-cited propagation map for a new workspace …