mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 17:45:53 +01:00
106 lines
3.4 KiB
JavaScript
106 lines
3.4 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import test from "node:test";
|
|
|
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
|
|
function readWorkflow(name) {
|
|
return readFileSync(path.join(repoRoot, ".github/workflows", name), "utf8");
|
|
}
|
|
|
|
function readPrManifestPattern() {
|
|
const prWorkflow = readWorkflow("pr.yml");
|
|
const manifestPattern = prWorkflow.match(/^\s*manifest_pattern='([^']+)'$/m)?.[1];
|
|
|
|
assert.ok(manifestPattern, "expected a manifest_pattern definition in pr.yml");
|
|
return new RegExp(manifestPattern);
|
|
}
|
|
|
|
test("release workflow delegates stable and canary verification to the reusable workflow", () => {
|
|
const releaseWorkflow = readWorkflow("release.yml");
|
|
|
|
assert.match(
|
|
releaseWorkflow,
|
|
/verify_canary:\n\s+if: github\.event_name == 'push'\n\s+uses: \.\/\.github\/workflows\/release-verify\.yml\n\s+with:\n\s+ref: \$\{\{ github\.sha \}\}/,
|
|
);
|
|
assert.match(
|
|
releaseWorkflow,
|
|
/verify_stable:\n\s+if: github\.event_name == 'workflow_dispatch'\n\s+uses: \.\/\.github\/workflows\/release-verify\.yml\n\s+with:\n\s+ref: \$\{\{ inputs\.source_ref \}\}/,
|
|
);
|
|
assert.doesNotMatch(releaseWorkflow, /verify_(?:canary|stable):[\s\S]*?pnpm test:run(?:\n|$)/);
|
|
});
|
|
|
|
test("release verify workflow covers the same split test surface as stable PR verification", () => {
|
|
const verifyWorkflow = readWorkflow("release-verify.yml");
|
|
|
|
assert.match(verifyWorkflow, /workflow_call:/);
|
|
assert.match(verifyWorkflow, /node \.\/scripts\/release-package-map\.mjs check/);
|
|
assert.match(verifyWorkflow, /pnpm -r typecheck/);
|
|
assert.match(verifyWorkflow, /pnpm build/);
|
|
|
|
for (const group of ["general-server", "general-workspaces-a", "general-workspaces-b"]) {
|
|
assert.match(verifyWorkflow, new RegExp(`group: ${group}`));
|
|
}
|
|
|
|
for (const shardIndex of [0, 1, 2]) {
|
|
assert.match(
|
|
verifyWorkflow,
|
|
new RegExp(`group: general-server[\\s\\S]*?shard_index: ${shardIndex}[\\s\\S]*?shard_count: 3`),
|
|
);
|
|
}
|
|
|
|
for (const shardIndex of [0, 1, 2, 3]) {
|
|
assert.match(verifyWorkflow, new RegExp(`shard_index: ${shardIndex}[\\s\\S]*?shard_count: 4`));
|
|
}
|
|
|
|
assert.match(verifyWorkflow, /pnpm test:run:general -- --group/);
|
|
assert.match(verifyWorkflow, /pnpm test:run:serialized -- --shard-index/);
|
|
});
|
|
|
|
test("pr workflow regenerates the lockfile for dependency graph inputs", () => {
|
|
const manifestPattern = readPrManifestPattern();
|
|
|
|
const triggeringPaths = [
|
|
"package.json",
|
|
"packages/shared/package.json",
|
|
"pnpm-workspace.yaml",
|
|
".npmrc",
|
|
"pnpmfile.cjs",
|
|
"pnpmfile.js",
|
|
"pnpmfile.mjs",
|
|
"patches/acpx@0.12.0.patch",
|
|
"patches/nested/fix.patch",
|
|
];
|
|
|
|
for (const filePath of triggeringPaths) {
|
|
assert.equal(
|
|
manifestPattern.test(filePath),
|
|
true,
|
|
`${filePath} should trigger lockfile regeneration`,
|
|
);
|
|
}
|
|
});
|
|
|
|
test("pr workflow lockfile trigger stays scoped to root-level config and patches", () => {
|
|
const manifestPattern = readPrManifestPattern();
|
|
|
|
const ignoredPaths = [
|
|
"README.md",
|
|
"packages/shared/src/index.ts",
|
|
"packages/shared/.npmrc",
|
|
"packages/shared/pnpmfile.cjs",
|
|
"packages/shared/patches/acpx.patch",
|
|
"docs/patches/acpx.patch",
|
|
];
|
|
|
|
for (const filePath of ignoredPaths) {
|
|
assert.equal(
|
|
manifestPattern.test(filePath),
|
|
false,
|
|
`${filePath} should not trigger lockfile regeneration`,
|
|
);
|
|
}
|
|
});
|