mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(repo): keep one fallow audit base cache per checkout instead of one per main commit (#4525)
This commit is contained in:
+2
-1
@@ -30,7 +30,8 @@ pre-commit:
|
||||
# Unset git worktree env vars: fallow creates a temp worktree internally and
|
||||
# GIT_DIR/GIT_INDEX_FILE (set by git in worktree hook context) break that.
|
||||
# env -u is safe in non-worktree contexts (no-op when var is unset).
|
||||
run: env -u GIT_DIR -u GIT_INDEX_FILE -u GIT_WORK_TREE bunx fallow audit --base origin/main --fail-on-issues
|
||||
# The prune keeps one audit base cache per checkout; the commit gets the audit's own status.
|
||||
run: env -u GIT_DIR -u GIT_INDEX_FILE -u GIT_WORK_TREE sh -c 'bunx fallow audit --base origin/main --fail-on-issues; status=$?; bun scripts/prune-fallow-audit-caches.mjs origin/main; exit $status'
|
||||
largefiles:
|
||||
# Reject large binaries committed straight into the git pack instead of
|
||||
# LFS. The script reads the staged set itself (via `git diff --cached`)
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@
|
||||
"player:perf": "bun run --filter @hyperframes/player perf",
|
||||
"format:check": "oxfmt --check .",
|
||||
"knip": "knip",
|
||||
"test:scripts": "node --import tsx --test scripts/animejs-v4-guidance.test.mjs scripts/check-tracked-artifacts.test.mjs scripts/check-registry-set-delta.test.mjs scripts/check-no-main-deletions.test.mjs scripts/check-pr-captures.test.mjs scripts/check-comment-citations.test.mjs scripts/comments-workflow.test.mjs scripts/comment-ratchet.test.mjs scripts/check-docs-snippet-motion.test.mjs scripts/registry-target-paths.test.mjs scripts/check-workspace-contracts.test.mjs scripts/check-media-use-copy-parity.test.mjs scripts/check-svg-sanitize-parity.test.mjs scripts/check-media-use-svg-sanitize-generated.test.mjs scripts/check-package-cycles.test.mjs scripts/check-cli-process-ownership.test.mjs scripts/check-large-files.test.mjs scripts/package-subpaths.test.mjs scripts/validate-release-channel.test.mjs scripts/publish-workflow.test.mjs scripts/pr-edit-concurrency.test.mjs scripts/merge-queue-workflows.test.mjs scripts/install-workspace-dependencies.test.mjs scripts/draft-changelog.test.ts scripts/set-version.test.ts scripts/release-prepare.test.ts scripts/cli-options.test.ts scripts/changelog-weekly.test.ts scripts/claude-plugin-compression.test.ts scripts/catalog-payload-assets.test.ts scripts/host-registry-assets.test.ts scripts/catalog-preview-temp.test.ts scripts/catalog-hosted-files.test.ts scripts/player-cdn-pin.test.ts scripts/studio-runtime-smoke.test.mjs scripts/verify-packed-manifests.test.mjs scripts/lint-skills.test.mjs scripts/creator-editing-recipes.test.mjs packages/gcp-cloud-run/check-dockerfile-workspaces.test.mjs packages/core/scripts/writeGeneratedFile.test.ts scripts/catalog-publication.test.mjs scripts/ci/resolve-workflow-pr.test.mjs scripts/check-catalog-source-pr.test.mjs scripts/generate-registry-items.test.ts scripts/catalog-drift.test.ts scripts/catalog-fetch-mirror.test.ts scripts/catalog-script-inlining.test.ts scripts/catalog-detail.test.ts scripts/generate-catalog-pages.test.ts scripts/verify-catalog-payloads.test.ts scripts/registry-skill-files.test.ts scripts/creator-editing-capabilities.test.mjs scripts/generate-catalog-previews.test.ts scripts/registry-primitive-payloads.test.ts registry/components/pan-stations/pan-stations.test.mjs && vitest run scripts/catalog/ scripts/contrastRatchet.test.ts scripts/generate-catalog-payloads.test.ts",
|
||||
"test:scripts": "node --import tsx --test scripts/animejs-v4-guidance.test.mjs scripts/check-tracked-artifacts.test.mjs scripts/check-registry-set-delta.test.mjs scripts/check-no-main-deletions.test.mjs scripts/check-pr-captures.test.mjs scripts/check-comment-citations.test.mjs scripts/comments-workflow.test.mjs scripts/comment-ratchet.test.mjs scripts/check-docs-snippet-motion.test.mjs scripts/registry-target-paths.test.mjs scripts/check-workspace-contracts.test.mjs scripts/check-media-use-copy-parity.test.mjs scripts/check-svg-sanitize-parity.test.mjs scripts/check-media-use-svg-sanitize-generated.test.mjs scripts/check-package-cycles.test.mjs scripts/check-cli-process-ownership.test.mjs scripts/check-large-files.test.mjs scripts/prune-fallow-audit-caches.test.mjs scripts/package-subpaths.test.mjs scripts/validate-release-channel.test.mjs scripts/publish-workflow.test.mjs scripts/pr-edit-concurrency.test.mjs scripts/merge-queue-workflows.test.mjs scripts/install-workspace-dependencies.test.mjs scripts/draft-changelog.test.ts scripts/set-version.test.ts scripts/release-prepare.test.ts scripts/cli-options.test.ts scripts/changelog-weekly.test.ts scripts/claude-plugin-compression.test.ts scripts/catalog-payload-assets.test.ts scripts/host-registry-assets.test.ts scripts/catalog-preview-temp.test.ts scripts/catalog-hosted-files.test.ts scripts/player-cdn-pin.test.ts scripts/studio-runtime-smoke.test.mjs scripts/verify-packed-manifests.test.mjs scripts/lint-skills.test.mjs scripts/creator-editing-recipes.test.mjs packages/gcp-cloud-run/check-dockerfile-workspaces.test.mjs packages/core/scripts/writeGeneratedFile.test.ts scripts/catalog-publication.test.mjs scripts/ci/resolve-workflow-pr.test.mjs scripts/check-catalog-source-pr.test.mjs scripts/generate-registry-items.test.ts scripts/catalog-drift.test.ts scripts/catalog-fetch-mirror.test.ts scripts/catalog-script-inlining.test.ts scripts/catalog-detail.test.ts scripts/generate-catalog-pages.test.ts scripts/verify-catalog-payloads.test.ts scripts/registry-skill-files.test.ts scripts/creator-editing-capabilities.test.mjs scripts/generate-catalog-previews.test.ts scripts/registry-primitive-payloads.test.ts registry/components/pan-stations/pan-stations.test.mjs && vitest run scripts/catalog/ scripts/contrastRatchet.test.ts scripts/generate-catalog-payloads.test.ts",
|
||||
"typecheck:scripts": "tsc --noEmit -p scripts/tsconfig.json",
|
||||
"test:skills": "node --test 'skills/**/*.test.mjs' 'packages/cli/src/media-use/**/*.test.mjs'",
|
||||
"generate:previews": "tsx scripts/generate-template-previews.ts",
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bun
|
||||
// fallow keeps one base-snapshot worktree per checkout and base commit in the temp dir
|
||||
// (`fallow-audit-base-cache-<xxh3 of the checkout path>-<base sha[:16]>`); 2.75 never removes
|
||||
// the one for an old base. Run after `fallow audit`: keeps only the current base's.
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { readdirSync, realpathSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
const PREFIX = "fallow-audit-base-cache-";
|
||||
|
||||
/** The entries in `names` that are this checkout's caches for a base other than `keepSha`. */
|
||||
export function staleAuditCaches(names, repoHash, keepSha) {
|
||||
const own = `${PREFIX}${repoHash}-`;
|
||||
const keep = `${own}${keepSha.slice(0, 16)}`;
|
||||
return names.filter((name) => name.startsWith(own) && !name.includes(".") && name !== keep);
|
||||
}
|
||||
|
||||
function git(root, args) {
|
||||
return spawnSync("git", args, { cwd: root, encoding: "utf8" });
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
const base = process.argv[2] ?? "origin/main";
|
||||
const root = realpathSync(git(process.cwd(), ["rev-parse", "--show-toplevel"]).stdout.trim());
|
||||
const keepSha = git(root, ["rev-parse", base]).stdout.trim();
|
||||
if (!keepSha) {
|
||||
console.error(`prune-fallow-audit-caches: cannot resolve ${base}; nothing removed`);
|
||||
process.exit(0);
|
||||
}
|
||||
const repoHash = Bun.hash.xxHash3(root).toString(16).padStart(16, "0");
|
||||
const dir = tmpdir();
|
||||
const stale = staleAuditCaches(readdirSync(dir), repoHash, keepSha);
|
||||
for (const name of stale) {
|
||||
// A registered cache must leave git's worktree list too, or `git worktree add` refuses the path later.
|
||||
git(root, ["worktree", "remove", "--force", join(dir, name)]);
|
||||
rmSync(join(dir, name), { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import {
|
||||
appendFileSync,
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
mkdtempSync,
|
||||
readdirSync,
|
||||
rmSync,
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { describe, it } from "node:test";
|
||||
import { staleAuditCaches } from "./prune-fallow-audit-caches.mjs";
|
||||
|
||||
const SCRIPT = join(import.meta.dirname, "prune-fallow-audit-caches.mjs");
|
||||
const FALLOW = join(import.meta.dirname, "../node_modules/.bin/fallow");
|
||||
const CAN_AUDIT = spawnSync("bun", ["--version"]).status === 0 && existsSync(FALLOW);
|
||||
|
||||
// Run from inside a git hook, these would point the temp repo's git at the outer checkout.
|
||||
const ENV = { ...process.env };
|
||||
for (const name of ["GIT_DIR", "GIT_INDEX_FILE", "GIT_WORK_TREE"]) delete ENV[name];
|
||||
|
||||
function git(cwd, ...args) {
|
||||
const result = spawnSync("git", args, { cwd, env: ENV, encoding: "utf8" });
|
||||
assert.equal(result.status, 0, result.stderr);
|
||||
return result.stdout.trim();
|
||||
}
|
||||
|
||||
function commit(repo, message) {
|
||||
git(
|
||||
repo,
|
||||
"-c",
|
||||
"user.email=t@t",
|
||||
"-c",
|
||||
"user.name=t",
|
||||
"-c",
|
||||
"commit.gpgsign=false",
|
||||
"commit",
|
||||
"-q",
|
||||
"--no-verify",
|
||||
"-am",
|
||||
message,
|
||||
);
|
||||
}
|
||||
|
||||
describe("staleAuditCaches", () => {
|
||||
it("picks this checkout's caches for other bases, nothing else", () => {
|
||||
const names = [
|
||||
"fallow-audit-base-cache-aaaaaaaaaaaaaaaa-1111111111111111",
|
||||
"fallow-audit-base-cache-aaaaaaaaaaaaaaaa-2222222222222222",
|
||||
"fallow-audit-base-cache-aaaaaaaaaaaaaaaa-1111111111111111.lock",
|
||||
"fallow-audit-base-cache-bbbbbbbbbbbbbbbb-1111111111111111",
|
||||
"fallow-audit-base-4242-99",
|
||||
"unrelated",
|
||||
];
|
||||
|
||||
assert.deepEqual(staleAuditCaches(names, "aaaaaaaaaaaaaaaa", "2222222222222222ffff"), [
|
||||
"fallow-audit-base-cache-aaaaaaaaaaaaaaaa-1111111111111111",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe(
|
||||
"prune-fallow-audit-caches",
|
||||
{ skip: !CAN_AUDIT && "bun or fallow is not installed" },
|
||||
() => {
|
||||
it("leaves one fallow cache for the checkout after audits against two bases", () => {
|
||||
const work = mkdtempSync(join(tmpdir(), "hf-fallow-prune-"));
|
||||
try {
|
||||
const repo = join(work, "repo");
|
||||
const temp = join(work, "tmp");
|
||||
mkdirSync(join(repo, "src"), { recursive: true });
|
||||
mkdirSync(temp);
|
||||
writeFileSync(
|
||||
join(repo, "package.json"),
|
||||
'{"name":"x","type":"module","main":"src/index.js"}',
|
||||
);
|
||||
writeFileSync(join(repo, "src/index.js"), "export const a = 1;\n");
|
||||
git(repo, "init", "-q");
|
||||
git(repo, "add", "-A");
|
||||
commit(repo, "a");
|
||||
const oldBase = git(repo, "rev-parse", "HEAD");
|
||||
appendFileSync(join(repo, "src/index.js"), "export const b = 2;\n");
|
||||
commit(repo, "b");
|
||||
const newBase = git(repo, "rev-parse", "HEAD");
|
||||
appendFileSync(join(repo, "src/index.js"), "export const c = 3;\n");
|
||||
const env = { ...ENV, TMPDIR: temp };
|
||||
for (const base of [oldBase, newBase]) {
|
||||
const audit = spawnSync(FALLOW, ["audit", "--base", base], {
|
||||
cwd: repo,
|
||||
env,
|
||||
encoding: "utf8",
|
||||
});
|
||||
assert.equal(audit.status, 0, audit.stderr);
|
||||
}
|
||||
const caches = () =>
|
||||
readdirSync(temp).filter((name) =>
|
||||
/^fallow-audit-base-cache-[0-9a-f]+-[0-9a-f]+$/.test(name),
|
||||
);
|
||||
assert.equal(caches().length, 2, "fallow left one cache per base");
|
||||
const foreign = join(
|
||||
temp,
|
||||
`fallow-audit-base-cache-0000000000000000-${oldBase.slice(0, 16)}`,
|
||||
);
|
||||
mkdirSync(foreign);
|
||||
|
||||
const run = spawnSync("bun", [SCRIPT, newBase], { cwd: repo, env, encoding: "utf8" });
|
||||
|
||||
assert.equal(run.status, 0, run.stderr);
|
||||
const left = caches().filter((name) => !foreign.endsWith(name));
|
||||
assert.equal(left.length, 1);
|
||||
assert.ok(left[0].endsWith(`-${newBase.slice(0, 16)}`), `kept ${left[0]}`);
|
||||
assert.ok(existsSync(foreign), "another checkout's cache is not touched");
|
||||
assert.doesNotMatch(git(repo, "worktree", "list"), new RegExp(oldBase.slice(0, 16)));
|
||||
} finally {
|
||||
rmSync(work, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user