Dashboard › craft › Session 06rTnCnnGnEp
06rTnCnnGnEpeXlUmStrict final READ-ONLY adversarial audit. Do not modify. Inspect current full diffs and source/tests in both /home/byk/Code/getsentry/craft-workspace-action-propagation and /home/byk/Code/getsentry/publish-workspace-acceptance.
Validate the final state with concrete file:line evidence: release-revision authority regex anchored strictly at byte 0 to Action's request header; forged header/Quick links later in body rejected; exactly-one link and poller update behavior; workflow_dispatch preserved; legacy JSON workspace cli/v2 works with root-only rule while new action inputs reject unsafe compact names; Inform start occurs after revision resolution; same SHA checkout/discovery/location/state/craft --rev; state parity fixture; parser freshness; no local-state fallback; YAML correctness; intended file hygiene. Publish has two known newline-only unrelated dirty files (src/modules/post-workflow-details.js and src/publish/inputs.js) intentionally excluded from staging. Confirm pnpm-lock is absent. Return prioritized findings with PASS/FAIL plus MERGE or DO-NOT-MERGE.
<skill_content name="jj-guide"> # Skill: jj-guide # jj Guide for AI Agents Jujutsu (jj) is a Git-compatible VCS with mutable commits, automatic snapshotting, no staging area, and first-class conflicts. This skill teaches you how to use it safely from a non-interactive agent environment. If `.jj/` exists in the repo root, this is a jj repo. **Use `jj` commands, not `git`.** In a colocated repo (`.jj/` *and* `.git/`), git tools can read the state, but mutations should go through `jj` so the operation log stays consistent. ## Critical Rules - **NEVER** use interactive flags (`-i`, `--interactive`). TUI prompts hang in agent environments. This applies to `jj split -i`, `jj squash -i`, `jj commit -i`, `jj resolve`, `jj diffedit`, etc. - **ALWAYS** pass `-m "msg"` when describing/committing. Without `-m`, an editor opens and hangs. - **VERIFY** mutations with `jj st` and `jj log` after `squash`, `abandon`, `rebase`, `restore`, `commit`. ...
<path>/home/byk/Code/getsentry</path> <type>directory</type> <entries> cli-api-1423/ cli-wt/ cli/ codecov-action/ craft-vercel-prebuilt-output/ craft-vercel-project-config/ craft-workspace-action-propagation/ craft-workspaces-schema/ craft/ devinfra-coder-infra/ devinfra-deployment-service/ getsentry/ ops/ package_grant_publish_repo/ publish-workspace-acceptance/ publish/ security-as-code/ self-hosted/ sentry-api-schema/ sentry-docs/ sentry-forge/ sentry-go/ sentry-javascript/ sentry-orbital/ sentry-python/ sentry-release-registry/ sentry-wizard/ sentry/ snuba/ spotlight/ sqlish/ static-sites/ stripe-app/ symbolic/ (34 entries) </entries>
Error: There is no jj repo in "."
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/ 6dae341 feat: propagate release workspaces 21270a1 feat(config): add release workspaces 32f5462 fix(git): prevent fatal error for missing 'origin' remote (#871) 5d0ec43 fix(registry): retry registry push with backoff on concurrent updates (#870) 35e8063 meta: Bump new development version b2524ef Merge branch 'release/2.30.1' cd1e829 release: 2.30.1 06180e3 fix(vercel): pass prebuilt output directory 29ad5c3 meta: Bump new development version c02eb03 Merge branch 'release/2.30.0' action.yml | 18 ++--- docs/src/content/docs/targets/github.md | 36 ++++++++- src/__tests__/action.test.ts | 135 ++++++++++++++++++++++++++++--- ...
M .github/workflows/ci-poller.yml 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 ?? scripts/ ?? src/modules/__tests__/ci-poller-input.js ?? src/modules/__tests__/publish-location.js ?? src/modules/__tests__/release-revision.js ?? src/modules/ci-poller-input.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-ci-poller-input.js ?? src/publish/resolve-location.js ?? src/publish/resolve-release-revision.js b658ffa fix: validate publish workspace JSON 33de3f1 feat: accept workspace publish requests 83d210b build(deps): bump js-yaml from 4.3.0 to 4.3.1 (#9174) 5268a23 feat: Add Vercel creds 92eba3f feat: Add ...
BASE 8cc54254f2e9489abbfdc028df15e7effbbc6bb8 M .github/workflows/release.yml M CHANGELOG.md M action.yml M docs/package.json M docs/pnpm-lock.yaml M docs/src/content/docs/targets/github.md M docs/src/content/docs/targets/vercel.md M package.json M pnpm-lock.yaml A 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 M src/targets/__tests__/registry.test.ts M src/targets/__tests__/vercel.test.ts M src/targets/registry.ts M src/targets/vercel.ts M src/utils/__tests__/helpers.test.ts M src/utils/__tests__/publishState.test.ts M src/utils/git.ts M src/utils/helpers.ts M src/utils/publishState.ts --- untracked --- src/commands/workspace.ts src/commands/workspace_cmds/__tests__/list.test.ts src/commands/workspace_cmds/list.ts --- full tree diff stat --- .github/workflows/release.yml | 9 + CHANGELOG.md | 26 +++ ...
fatal: Not a valid object name master
feat/workspace-acceptance
origin https://github.com/getsentry/publish.git (fetch)
origin https://github.com/getsentry/publish.git (push)
2513c782a5a54da5921a87ce52fc357a78c8e263 refs/heads/chore/fix-security-advisories
b658ffa0299fedf78c9dd9a2121cd740691ca157 refs/heads/feat/workspace-acceptance
a58b7212cd8886308be5d742885271ebda2f81e7 refs/heads/fix/add-workflow-permissions
83d210b29553ea6f4d97508821724a834c43856e refs/heads/main
83d210b29553ea6f4d97508821724a834c43856e refs/heads/opencode/tidy-orchid
83d9383368ee750b828da30943768a1956966e4e refs/heads/security/dual-write-publish-state
1b279b935f2213dac175660877449772a2342dbb refs/heads/security/remove-legacy-publish-state-write
error: unknown option `remotes'
usage: git show-ref [--head] [-d | --dereference]
[-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]
[--heads] [--] [<pattern>...]
or: git show-ref --verify [-q | --quiet] [-d | --dereference]
[-s | --hash[=<n>]] ...
BASE 83d210b29553ea6f4d97508821724a834c43856e M .github/workflows/ci-poller.yml M .github/workflows/cocoapods-keepalive.yml M .github/workflows/publish.yml M README.md A docs/publish-issue-format.md M package.json M src/modules/__tests__/details-from-context.js A src/modules/__tests__/publish-workflow.js M src/modules/__tests__/update-issue.js M src/modules/details-from-context.js M src/modules/post-workflow-details.js M src/modules/update-issue.js M src/publish/inputs.js M yarn.lock --- untracked --- scripts/generate-publish-issue-title-parser.js src/modules/__tests__/ci-poller-input.js src/modules/__tests__/publish-location.js src/modules/__tests__/release-revision.js src/modules/ci-poller-input.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-ci-poller-input.js src/publish/resolve-location.js src/publish/resolve-release-revision.js --- full tree diff stat --- ...
<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/.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 ...
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/release-revision.js</path>
<type>file</type>
<content>
1: const CHECK_RUNS_LINK =
2: /^Requested by: @[^\r\n]+\r?\n(?:[ \t]*\r?\n)?[ \t]*Merge target: [^\r\n]+\r?\n(?:[ \t]*\r?\n)?[ \t]*Quick links:\r?\n(?:[ \t]*\r?\n)?[ \t]*- \[View changes\]\([^\r\n]+\)\r?\n[ \t]*- \[View check runs\]\(https:\/\/github\.com\/getsentry\/(?<repo>[A-Za-z0-9_.-]+)\/commit\/(?<revision>[0-9a-f]{40})\/checks\/?\)(?=\r?\n|$)/;
3: const CHECK_RUNS_LINK_COUNT = /^[ \t]*- \[View check runs\]\(/gm;
4:
5: function getReleaseRevision({ issueBody, repo }) {
6: if ((issueBody.match(CHECK_RUNS_LINK_COUNT) || []).length !== 1) {
7: throw new Error(
8: `Expected exactly one View check runs link in Quick links for getsentry/${repo}.`
9: );
10: }
11:
12: const match = issueBody.match(CHECK_RUNS_LINK);
13: if (!match?.groups || match.groups.repo !== repo) {
14: throw new Error(
15: `Expected a View check runs link ...
<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: ? ...
<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: = ...
<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: inputs();
(End of file - total 12 lines)
</content>
<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. ...
<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: ...
<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>
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/.github/workflows/ci-poller.yml</path> <type>file</type> <content> 1: name: CI Status Poller 2: 3: on: 4: schedule: 5: - cron: "*/5 * * * *" 6: workflow_dispatch: 7: inputs: 8: attempt: 9: description: Self-dispatch attempt counter (internal use) 10: required: false 11: default: "0" 12: 13: permissions: 14: contents: read 15: issues: read 16: 17: jobs: 18: check-ci: 19: runs-on: ubuntu-latest 20: environment: production 21: # Skip entirely (no runner provisioned) when there's nothing to check. 22: # Set to "true" by ci-pending.yml, reset to "false" here when done. 23: # Always allow workflow_dispatch for manual recovery. 24: if: vars.CI_POLLER_HAS_PENDING == 'true' || github.event_name == 'workflow_dispatch' 25: concurrency: 26: group: ci-status-poller 27: cancel-in-progress: false 28: steps: 29: # sentry-internal-app token ...
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/publish/resolve-ci-poller-input.js</path>
<type>file</type>
<content>
1: const { getCiPollerInput } = require("../modules/ci-poller-input");
2:
3: process.stdout.write(
4: JSON.stringify(
5: getCiPollerInput({
6: issueBody: process.env.PUBLISH_ISSUE_BODY || "",
7: title: process.env.PUBLISH_TITLE || "",
8: revision: process.env.PUBLISH_REVISION || "",
9: })
10: )
11: );
(End of file - total 11 lines)
</content>
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/ci-poller-input.js</path>
<type>file</type>
<content>
1: const { parse: parsePublishIssueTitle } = require("./publish-issue-title");
2: const {
3: getReleaseRevision,
4: updateReleaseRevision,
5: } = require("./release-revision");
6:
7: function getCiPollerInput({ title, issueBody, revision }) {
8: let parsedTitle;
9: try {
10: parsedTitle = parsePublishIssueTitle(title);
11: } catch {
12: throw new Error(`Invalid publish issue title: '${title}'`);
13: }
14: const { repo, version } = parsedTitle;
15: const currentRevision = getReleaseRevision({ issueBody, repo });
16:
17: return {
18: ...(revision
19: ? { issueBody: updateReleaseRevision({ issueBody, repo, revision }) }
20: : {}),
21: repo: `getsentry/${repo}`,
22: revision: currentRevision,
23: version,
24: };
25: }
26:
27: module.exports = { getCiPollerInput };
(End of file - total 27 lines)
</content>
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/release-revision.js</path>
<type>file</type>
<content>
1: import { expect, test } from "vitest";
2:
3: const {
4: getReleaseRevision,
5: updateReleaseRevision,
6: } = require("../release-revision.js");
7:
8: const REVISION = "7e5ca7ed5581552de066e2a8bc295b8306be38ac";
9:
10: function requestBody(quickLinks) {
11: return `Requested by: @byk
12:
13: Merge target: (default)
14:
15: Quick links:
16: ${quickLinks}`;
17: }
18:
19: function canonicalQuickLinks(revision = REVISION) {
20: return `- [View changes](https://github.com/getsentry/toolkit/compare/1.2.2...release/1.2.3)
21: - [View check runs](https://github.com/getsentry/toolkit/commit/${revision}/checks/)`;
22: }
23:
24: test("gets the CI-approved revision from the request header", () => {
25: expect(
26: getReleaseRevision({
27: repo: "toolkit",
28: issueBody: requestBody(canonicalQuickLinks()),
29: })
30: ...
<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>
<path>/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-location.js</path>
<type>file</type>
<content>
1: import { expect, test } from "vitest";
2:
3: const {
4: needsWorkspaceDiscovery,
5: resolvePublishLocation,
6: } = require("../publish-location.js");
7:
8: test.each([
9: [{ path: "./cli" }, true],
10: [{ path: "./packages/cli" }, false],
11: [{ path: "." }, false],
12: [{ path: "./cli", workspace: "cli" }, false],
13: ])("workspace discovery is %s for %j", (input, expected) => {
14: expect(needsWorkspaceDiscovery(input)).toBe(expected);
15: });
16:
17: test("classifies an exact one-segment workspace without normalizing it", () => {
18: expect(
19: resolvePublishLocation({
20: path: "./CLI",
21: workspaceNames: ["cli", "CLI"],
22: })
23: ).toStrictEqual({ path: ".", workspace: "CLI" });
24: });
25:
26: test("keeps a non-workspace suffix as a checkout path", () => {
27: expect(
28: ...
Found 67 matches
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/ci-poller-input.js:
Line 17: test("parses compact and legacy workspace publish titles", () => {
Line 32: title: 'publish: toolkit [workspace: "cli/v2"] @1.2.3',
/home/byk/Code/getsentry/publish-workspace-acceptance/src/modules/__tests__/publish-location.js:
Line 12: [{ path: "./cli", workspace: "cli" }, false],
Line 13: ])("workspace discovery is %s for %j", (input, expected) => {
Line 17: test("classifies an exact one-segment workspace without normalizing it", () => {
Line 21: workspaceNames: ["cli", "CLI"],
Line 23: ).toStrictEqual({ path: ".", workspace: "CLI" });
Line 26: test("keeps a non-workspace suffix as a checkout path", () => {
Line 30: workspaceNames: ["cli"],
Line 35: test("keeps multi-segment paths even when the last segment is a workspace", () => {
Line 39: workspaceNames: ["cli"],
Line 48: workspaceNames: ...
<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 { resolvePublishLocation } = require("../publish-location.js");
9:
10: const temporaryDirectories = [];
11:
12: function getWorkflow() {
13: return readFileSync(
14: join(__dirname, "../../../.github/workflows/publish.yml"),
15: "utf8"
16: );
17: }
18:
19: function getSetTargetsScript() {
20: const workflow = getWorkflow();
21: const section = workflow.match(
22: / {6}- name: Set targets[\s\S]*? {8}run: \|\n(?<script>[\s\S]*?)\n {6}- uses: docker:\/\/getsentry\/craft:latest/
23: );
24: if (!section?.groups?.script) {
25: throw new Error("Missing Set targets workflow ...
<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": ...
<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: ...
<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>
<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>
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 16: export interface WorkspacePackage {
Line 25: /** Dependencies that are also workspace packages */
Line 26: workspaceDependencies: string[];
Line 29: /** Result of workspace discovery */
Line 30: export interface WorkspaceDiscoveryResult {
Line 31: /** The type of workspace manager detected */
Line 34: packages: WorkspacePackage[];
Line 37: /** Structure of pnpm-workspace.yaml */
Line 38: interface PnpmWorkspaceConfig {
Line 45: workspaces?: string[] | { packages?: string[] };
Line 93: * Extract workspaces array from package.json workspaces field
Line 96: function extractWorkspacesGlobs(
Line 97: workspaces: string[] | { packages?: string[] } | undefined,
Line 99: if (!workspaces) {
Line 102: if (Array.isArray(workspaces)) {
Line ...
Found 23 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/config.ts:
Line 61: * The minimum craft version required to use the top-level `workspaces` config.
Line 63: * This is the release the workspaces feature ships in. A dev build of that
Line 108: * - `minVersion` and `workspaces` themselves are stripped from the result.
Line 114: const workspaces = base.workspaces || {};
Line 115: if (!Object.hasOwn(workspaces, workspaceName)) {
Line 116: const available = Object.keys(workspaces);
Line 120: ? `Available workspaces: ${available.join(', ')}.`
Line 121: : 'No workspaces are defined in the configuration.'),
Line 124: const workspace = workspaces[workspaceName];
Line 127: const { workspaces: _ignoredWorkspaces, ...baseWithoutWorkspaces } = base;
Line 188: `Using "workspaces" requires minVersion >= ${WORKSPACES_MIN_VERSION} ` +
Line 206: * - No `workspaces` in config, no active selection ...
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/config.ts</path> <type>file</type> <content> 45: /** 46: * The default prefix for the release branch. 47: */ 48: export const DEFAULT_RELEASE_BRANCH_NAME = 'release'; 49: 50: /** 51: * Cached path to the configuration file 52: */ 53: let _configPathCache: string; 54: 55: /** 56: * Cached configuration 57: */ 58: let _configCache: CraftProjectConfig; 59: 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). ...
<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. ...
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/schemas/project_config.ts</path>
<type>file</type>
<content>
229: /**
230: * Craft project-specific configuration
231: */
232: export const CraftProjectConfigSchema = z
233: .object({
234: ...releaseUnitFields,
235: minVersion: z
236: .string()
237: .regex(/^\d+\.\d+\.\d+.*$/)
238: .optional(),
239: /**
240: * Named, independently-versioned release units within a single repository.
241: *
242: * When present, a release run must select one via `--workspace <name>` (or
243: * `CRAFT_WORKSPACE`). The selected workspace's fields override the top-level
244: * ones. When absent, craft behaves exactly as before (the top-level config is
245: * the single implicit release unit) — fully backward compatible.
246: */
247: workspaces: z.record(WorkspaceNameSchema, WorkspaceSchema).optional(),
248: })
249: .superRefine((config, context) => {
250: if ...
Found 6 matches
/home/byk/Code/getsentry/craft-workspace-action-propagation/src/__tests__/action.test.ts:
Line 113: WORKSPACE: workspace,
Line 139: WORKSPACE: workspace,
Line 168: expect(getActionStep('Craft Prepare').env?.WORKSPACE).toBe(
Line 171: expect(getActionStep('Read Craft Targets').env?.WORKSPACE).toBe(
Line 226: test('rejects workspace names outside the compact title grammar', () => {
Line 246: test('uses the compact workspace path in publish request titles', () => {
<path>/home/byk/Code/getsentry/craft-workspace-action-propagation/src/__tests__/action.test.ts</path>
<type>file</type>
<content>
90: environment: ReturnType<typeof createActionEnvironment>,
91: ) {
92: return spawnSync(
93: 'bash',
94: ['-e', '-c', getActionStep('Request publish').run!],
95: {
96: cwd: environment.directory,
97: env: {
98: ...process.env,
99: CHANGELOG_FILE: '',
100: GITHUB_ACTOR: 'byk',
101: GITHUB_OUTPUT: environment.output,
102: GITHUB_REPOSITORY: 'getsentry/toolkit',
103: GH_TITLES: environment.ghTitles,
104: MERGE_TARGET: '(default)',
105: PATH: `${environment.binDirectory}:${process.env.PATH}`,
106: PUBLISH_REPO: 'getsentry/publish',
107: RELEASE_BRANCH: 'release/1.2.3',
108: RELEASE_PREVIOUS_TAG: '1.2.2',
109: RELEASE_SHA: 'abc123',
110: RESOLVED_VERSION: '1.2.3',
111: SUBDIRECTORY: '',
112: TARGETS: ' - [ ] ...
yarn run v1.22.22
$ node scripts/generate-publish-issue-title-parser.js --check
Done in 0.49s.
diff --git a/src/publish/inputs.js b/src/publish/inputs.js
index 0640d9e..9330d92 100644
--- a/src/publish/inputs.js
+++ b/src/publish/inputs.js
@@ -9,5 +9,4 @@ async function inputs() {
core.setOutput('result', result);
}
-
inputs();
diff --git a/src/modules/post-workflow-details.js b/src/modules/post-workflow-details.js
index 278d23e..227c81a 100644
--- a/src/modules/post-workflow-details.js
+++ b/src/modules/post-workflow-details.js
@@ -16,4 +16,4 @@ async function postWorkflowDetails({context, octokit}) {
});
}
-module.exports = postWorkflowDetails;
\ No newline at end of file
+module.exports = postWorkflowDetails;
diff --git a/src/publish/inputs.js b/src/publish/inputs.js
index 0640d9e..9330d92 100644
--- a/src/publish/inputs.js
+++ b/src/publish/inputs.js
@@ -9,5 +9,4 @@ async function inputs() {
core.setOutput('result', result);
}
-
-inputs();
\ No newline at end of file
+inputs();
--- numstat ---
1 1 src/modules/post-workflow-details.js
1 2 src/publish/inputs.js
--- full current status ---
M .github/workflows/ci-poller.yml
M .github/workflows/publish.yml
M docs/publish-issue-format.md
M package.json
M src/modules/__tests__/details-from-context.js
M ...
<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/utils/publishState.ts</path>
<type>file</type>
<content>
60: * disambiguate monorepo subpaths so `packages/foo` and `packages/bar`
61: * get separate state files even at the same version.
62: */
63: function shortCwdHash(cwd: string): string {
64: return createHash('sha1').update(cwd).digest('hex').slice(0, 12);
65: }
66:
67: /**
68: * Builds the filename for the publish-state file.
69: *
70: * With a resolvable GitHub config:
71: * `publish-state-<owner>-<repo>-<sha1(cwd)[:12]>-<version>.json`
72: *
73: * Without GitHub config (offline / non-GitHub test harnesses) the
74: * filename falls back to a cwd-hash-only form so Craft still refuses
75: * to write into the repo itself:
76: * `publish-state-<sha256(cwd)[:16]>-<version>.json`
77: *
78: * When a release workspace is selected, its losslessly encoded name is
79: * included before the version so independent release units in the same
80: * ...
<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. ...
node:internal/modules/cjs/loader:1520
throw err;
^
Error: Cannot find module 'yaml'
Require stack:
- /home/byk/Code/getsentry/craft-workspace-action-propagation/[eval]
at Module._resolveFilename (node:internal/modules/cjs/loader:1517:15)
at wrapResolveFilename (node:internal/modules/cjs/loader:1071:27)
at defaultResolveImplForCJSLoading (node:internal/modules/cjs/loader:1095:10)
at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1122:12)
at Module._load (node:internal/modules/cjs/loader:1294:5)
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
at Module.require (node:internal/modules/cjs/loader:1617:12)
at require (node:internal/modules/helpers:153:16)
at [eval]:1:36
at runScriptInThisContext (node:internal/vm:219:10) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/home/byk/Code/getsentry/craft-workspace-action-propagation/[eval]'
]
}
Node.js v24.18.0
/usr/bin/bash: line 1: ruby: command not found
actionlint unavailable 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/
No files found
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/
action.yml:84 accepts __proto__, -foo, and --config; its regex only excludes . and ... Craft explicitly rejects __proto__ (src/schemas/project_config.ts:218-227), and Publish discovery rejects it too (src/modules/publish-location.js:35-42). These inputs pass the intended first validation step and reach later side effects (action.yml:89-173). Add rejection for reserved and option-looking names, with focused validator tests.release-revision.js:2 anchors the canonical Action header at byte 0; :3-16 requires exactly one check-runs link and the title repository. Tests reject later forged links/headers (release-revision.js tests :56-94).ci-poller-input.js:7-24; ci-poller.yml:100-147).ci-ready gating is preserved (publish.yml:42-58, :102-114); manual recovery remains enabled (ci-poller.yml:3-24).details-from-context.js:34-58); cli/v2 coverage exists (publish-location.js tests :53-80).publish.yml:138-149, :159-187, :189-249), with the same resolved SHA used for checkout and craft publish --rev.publish.yml:217-236; Craft publishState.ts:51-64,82-98); fixtures cover root and workspace names (publish-workflow.js:97-125).__repo__ (publish.yml:203-236,250-261); failure handling only reads the explicit output path (update-issue.js:13-24,69-80). ...Date: Sep 2, 2026 * 🟡 [requested-audit] (15:27) User requested a strict final read-only adversarial audit with no modifications, covering current full diffs and source/tests in `/home/byk/Code/getsentry/craft-workspace-action-propagation` and `/home/byk/Code/getsentry/publish-workspace-acceptance`. * 🟡 (15:27) Audit validation criteria requested: concrete file:line evidence that the release-rev…