Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion scripts/release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,40 @@ await runLoud(["bun", "run", "audit:high"]);
console.log("→ typecheck");
await runLoud(["bun", "x", "tsc", "--noEmit"]);
console.log("→ test suite");
await runLoud(["bun", "test", "--isolate", "tests"]);
// Match CI's isolation policy instead of inventing a second one. `ci.yml` runs
// the storage-policy and api-usage harnesses in DEDICATED jobs and excludes them
// from the general shards (`scripts/ci/run-bun-test-batches.sh`
// `is_general_test_file`), because those Worker-heavy files corrupt the isolate
// state around them.
//
// This preflight used to run `bun test --isolate tests` — the whole directory in
// one process — so it exercised a grouping CI never runs. The result was a
// release gate that failed on `api-usage` while every CI job for the same commit
// was green: the worst kind of gate, one that blocks a good release and teaches
// you to distrust it. Same files and same coverage as before (915), now in the
// same groups CI uses.
// Every command here stays a `bun` invocation. The release-helper suite shims
// exactly `bun`, `gh`, `git` and `npm` onto a scratch PATH to record calls
// without executing them; a `bash` step would miss that shim, escape into the
// real suite, and fail the helper tests with exit 127.
const ISOLATED_TEST_FILES = [
"./tests/api-storage-policy-already-running.test.ts",
"./tests/api-storage-policy-mutation-busy.test.ts",
"./tests/api-storage-policy-put-race.test.ts",
"./tests/api-storage-policy-run.test.ts",
"./tests/api-storage-policy.test.ts",
"./tests/api-storage.test.ts",
"./tests/api-usage.test.ts",
];
await runLoud([
"bun", "test", "--isolate", "tests",
"--path-ignore-patterns=**/api-storage-policy*.test.ts",
"--path-ignore-patterns=**/api-storage.test.ts",
"--path-ignore-patterns=**/api-usage.test.ts",
]);
for (const isolated of ISOLATED_TEST_FILES) {
await runLoud(["bun", "test", "--isolate", isolated]);
}
console.log("→ privacy scan");
await runLoud(["bun", "run", "privacy:scan"]);

Expand Down
21 changes: 19 additions & 2 deletions tests/release-helper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,21 @@ describe("release helper", () => {

const auditIndex = findCallIndex(calls, "bun", call => call.args.join(" ") === "run audit:high");
const typecheckIndex = findCallIndex(calls, "bun", call => call.args.join(" ") === "x tsc --noEmit");
const testIndex = findCallIndex(calls, "bun", call => call.args.join(" ") === "test --isolate tests");
// The suite runs in CI's two groups, not as one directory sweep: the general
// files with the Worker-heavy harnesses ignored, then those harnesses one at
// a time. Assert the grouping, not just that "a test command ran" — the whole
// point of the change is WHICH processes the files land in.
const testIndex = findCallIndex(calls, "bun", call =>
call.args[0] === "test"
&& call.args.includes("tests")
&& call.args.some(arg => arg.startsWith("--path-ignore-patterns=") && arg.includes("api-usage")),
);
const isolatedUsageIndex = findCallIndex(calls, "bun", call =>
call.args.join(" ") === "test --isolate ./tests/api-usage.test.ts",
);
const isolatedStorageIndex = findCallIndex(calls, "bun", call =>
call.args.join(" ") === "test --isolate ./tests/api-storage.test.ts",
);
const privacyIndex = findCallIndex(calls, "bun", call => call.args.join(" ") === "run privacy:scan");
const versionIndex = findCallIndex(calls, "npm", call => call.args.join(" ") === "version 9.9.9 --no-git-tag-version");
const dispatchIndex = findCallIndex(calls, "gh", call =>
Expand All @@ -338,7 +352,10 @@ describe("release helper", () => {
expect(auditIndex).toBeGreaterThanOrEqual(0);
expect(typecheckIndex).toBeGreaterThan(auditIndex);
expect(testIndex).toBeGreaterThan(typecheckIndex);
expect(privacyIndex).toBeGreaterThan(testIndex);
// Every excluded harness is still executed, in its own process.
expect(isolatedUsageIndex).toBeGreaterThan(testIndex);
expect(isolatedStorageIndex).toBeGreaterThan(testIndex);
expect(privacyIndex).toBeGreaterThan(isolatedUsageIndex);
expect(versionIndex).toBeGreaterThan(privacyIndex);
expect(dispatchIndex).toBeGreaterThan(versionIndex);
});
Expand Down
Loading