diff --git a/packages/ui/scripts/build-manifest.ts b/packages/ui/scripts/build-manifest.ts index 7460ff72..0b14de0f 100644 --- a/packages/ui/scripts/build-manifest.ts +++ b/packages/ui/scripts/build-manifest.ts @@ -23,7 +23,7 @@ * `Program` over the entry files and reported with its signature and JSDoc summary. */ import { existsSync, mkdirSync, writeFileSync } from "node:fs"; -import { dirname, join, resolve } from "node:path"; +import { dirname, join, relative, resolve } from "node:path"; import { loadMigrations, migrationMarkdown } from "../src/cli/migrations.ts"; import { buildAtlasFile } from "./atlas-markdown.ts"; import { buildReleaseFile } from "./changelog-markdown.ts"; @@ -61,6 +61,19 @@ const SKILL_API = resolve(ROOT, "../../.agents/skills/codeatlas-ui/API.md"); const MIGRATION_MD = resolve(ROOT, "MIGRATION.md"); const SKILL_DEMOS = resolve(ROOT, "../../.agents/skills/codeatlas-ui/DEMOS.md"); +/** + * What a manifest run writes into the git tree, as repo-relative paths (directories end in `/`). The land gate + * (`scripts/generated-paths.sh`, the one list of generated files) must accept every one of them, or a rebase + * would take a side of a file the manifest rebuilds; `tests/issue-workflow.test.ts` checks it (#653). + */ +export const TREE_OUTPUTS = [ + relative(resolve(ROOT, "../.."), SKILL_API), + relative(resolve(ROOT, "../.."), SKILL_DEMOS), + relative(resolve(ROOT, "../.."), MIGRATION_MD), + `site/public/${API_DIR}/`, + "site/public/gallery/", +]; + if (import.meta.main) { const manifest = buildManifest(); const tokens = buildTokens(); diff --git a/packages/ui/tests/issue-workflow.test.ts b/packages/ui/tests/issue-workflow.test.ts index d3f76c39..5a74b5a6 100644 --- a/packages/ui/tests/issue-workflow.test.ts +++ b/packages/ui/tests/issue-workflow.test.ts @@ -20,6 +20,7 @@ import { removeWorktree, worktrees, } from "../../../scripts/issue-lib.ts"; +import { API_PATHS } from "../src/cli/agent-guide.ts"; // Real data from #87/#88: a first-time contributor opened PRs from a fork before `issue:start` ran. const fork = (number: number, headRefName: string): PrRef => ({ @@ -167,6 +168,19 @@ describe("issue-land.sh", () => { "sh", path, ]).exitCode === 0; + // One list (#653): every path a manifest run writes into the tree is accepted by `is_generated`, the list the land + // reads, so a new generated output cannot be left out of it (and `release.ts` stages whatever the manifest wrote). + it("accepts every path the manifest writes into the tree (#653)", async () => { + const { TREE_OUTPUTS } = await import("../scripts/build-manifest.ts"); + for (const out of TREE_OUTPUTS) { + // a directory stands for the files under it: probe a file the manifest really writes there + const probe = out.endsWith("/") + ? `${out}${out.includes("gallery") ? "001.md" : API_PATHS.catalog}` + : out; + expect(generated(probe), probe).toBe(true); + } + }); + it("rebuilds generated files and never picks a side of hand-written ones (#241)", () => { for (const p of [ "bun.lock", diff --git a/scripts/release-meta.ts b/scripts/release-meta.ts index 7c01cc30..678efee4 100644 --- a/scripts/release-meta.ts +++ b/scripts/release-meta.ts @@ -7,9 +7,10 @@ export const PREFIX = "@codeatlasdev/ui@"; /** * Commands `bun run release` runs to turn pending changesets into the release commit. The bump - * stamps the new version into the generated catalog (API.md, DEMOS.md, site/public/api/v1: - * "Needs: @codeatlasdev/ui@"), so they are regenerated before `git add -A`; otherwise - * main keeps the previous stamp until an unrelated PR rebuilds them. + * stamps the new version into the generated catalog ("Needs: @codeatlasdev/ui@"), so the + * manifest is rebuilt before `git add -A`; otherwise main keeps the previous stamp until an unrelated PR + * rebuilds it. Which files that covers is `TREE_OUTPUTS` (packages/ui/scripts/build-manifest.ts), checked + * against `scripts/generated-paths.sh`, the one list of generated files. */ export function versionSteps(): string[][] { return [