fix: keep pnpm's package store out of the release builder's clean-source check
CI / verify (pull_request) Successful in 1m4s
CI / infrastructure-smoke (pull_request) Successful in 37s
CI / migration-smoke (pull_request) Successful in 1m54s
CI / package-release (pull_request) Successful in 32s
CI / image-build (pull_request) Successful in 30s
CI / deploy-smoke (same-origin) (pull_request) Successful in 50s
CI / deploy-smoke (split) (pull_request) Successful in 1m32s
CI / verify (pull_request) Successful in 1m4s
CI / infrastructure-smoke (pull_request) Successful in 37s
CI / migration-smoke (pull_request) Successful in 1m54s
CI / package-release (pull_request) Successful in 32s
CI / image-build (pull_request) Successful in 30s
CI / deploy-smoke (same-origin) (pull_request) Successful in 50s
CI / deploy-smoke (split) (pull_request) Successful in 1m32s
The package-release job failed its clean-tree assertion in CI. Reproduced as root in a container with a bind-mounted checkout, as the Gitea runner does: after checkout the tree is clean; `pnpm install --frozen-lockfile` then creates `.pnpm-store/` (17,272 untracked files) at the checkout's root, because pnpm keeps its store on the node_modules file system and the checkout is its own mount; `pnpm build` changes nothing. No tracked file is ever modified. - `.pnpm-store/` is ignored, like node_modules: a package cache, never source. The clean-commit requirement is unchanged for every tracked file and every untracked file Git does not ignore. - The clean-tree failure now lists `git status --short` and `git diff --stat`. - Nothing is built before the clean-source assertion: the gate no longer runs a global `pnpm build` first. The builder asserts a clean tree, builds, then fails if its build changed the tree, before packing. Core's verifier is built after both releases, for the consumer proof only. - Every secondary offline install (the second worktree, the consumer module) uses the workspace install's own store explicitly, since pnpm picks a store per file system and those directories are on another. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9debe4e891
commit
4f1b1d68c7
@@ -433,6 +433,20 @@ async function inspectTarball(
|
||||
return [...new Set(problems)].map((problem) => `${entry.name} ${problem}.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Every uncommitted change in the source tree, as `git status --short` lines followed by
|
||||
* `git diff --stat`, all relative to the repository root; empty for a clean tree. Ignored files
|
||||
* (build output, `node_modules`) are not source and never count.
|
||||
*/
|
||||
async function sourceTreeChanges(): Promise<string[]> {
|
||||
const status = (
|
||||
await run("git", ["status", "--short", "--untracked-files=all"], repositoryRoot)
|
||||
).trimEnd();
|
||||
if (status === "") return [];
|
||||
const stat = (await run("git", ["diff", "--stat"], repositoryRoot)).trimEnd();
|
||||
return [...status.split("\n"), ...(stat === "" ? [] : stat.split("\n"))];
|
||||
}
|
||||
|
||||
export class PackageReleaseError extends Error {
|
||||
readonly problems: readonly string[];
|
||||
|
||||
@@ -462,13 +476,12 @@ export async function buildPackageRelease(
|
||||
if (setProblems.length > 0) throw new PackageReleaseError(setProblems);
|
||||
|
||||
const revision = (await run("git", ["rev-parse", "HEAD"], repositoryRoot)).trim();
|
||||
const modified =
|
||||
(
|
||||
await run("git", ["status", "--porcelain", "--untracked-files=all"], repositoryRoot)
|
||||
).trim() !== "";
|
||||
const dirty = await sourceTreeChanges();
|
||||
const modified = dirty.length > 0;
|
||||
if (modified && options.allowModified !== true) {
|
||||
throw new PackageReleaseError([
|
||||
"The source tree has uncommitted changes. A release is built from a clean commit.",
|
||||
...dirty,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -498,6 +511,15 @@ export async function buildPackageRelease(
|
||||
],
|
||||
repositoryRoot,
|
||||
);
|
||||
// The source was clean before the build; it must still be, so what is packed is the commit. A build
|
||||
// that wrote a tracked file, or an untracked file Git does not ignore, fails the release here.
|
||||
const changedByBuild = (await sourceTreeChanges()).filter((line) => !dirty.includes(line));
|
||||
if (changedByBuild.length > 0) {
|
||||
throw new PackageReleaseError([
|
||||
"The build changed the source tree. A release packs exactly its commit.",
|
||||
...changedByBuild,
|
||||
]);
|
||||
}
|
||||
|
||||
const scratch = await mkdtemp(path.join(tmpdir(), "ekklesia-package-release-"));
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user