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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,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-no-main-deletions.test.mjs scripts/check-docs-snippet-motion.test.mjs scripts/registry-target-paths.test.mjs scripts/check-workspace-contracts.test.mjs scripts/check-package-cycles.test.mjs scripts/check-cli-process-ownership.test.mjs scripts/package-subpaths.test.mjs scripts/validate-release-channel.test.mjs scripts/publish-workflow.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/catalog-preview-temp.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 packages/gcp-cloud-run/check-dockerfile-workspaces.test.mjs && vitest run scripts/catalog/",
"test:scripts": "node --import tsx --test scripts/animejs-v4-guidance.test.mjs scripts/check-tracked-artifacts.test.mjs scripts/check-no-main-deletions.test.mjs scripts/check-docs-snippet-motion.test.mjs scripts/registry-target-paths.test.mjs scripts/check-workspace-contracts.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/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/catalog-preview-temp.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 packages/gcp-cloud-run/check-dockerfile-workspaces.test.mjs && vitest run scripts/catalog/",
"typecheck:scripts": "tsc --noEmit -p scripts/tsconfig.json",
"test:skills": "node --test 'skills/**/*.test.mjs'",
"generate:previews": "tsx scripts/generate-template-previews.ts",
Expand Down
13 changes: 13 additions & 0 deletions scripts/check-large-files.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@ list_files "$@" | while IFS= read -r f; do
# round-trip. Those are the product, not accidental bloat — skip them here.
case "$f" in registry/*) continue ;; esac

# Text is exempt, whatever its size, because the cost this hook exists to stop
# is a binary one. Git delta-compresses text, so a file that grows by a few KB
# per commit adds a few KB to the pack. A binary of the same size re-enters the
# pack whole on every edit, which is exactly how the history got its hundreds
# of megabytes. `docs/changelog.mdx` is the case that forced this: half a
# megabyte of release notes, a little larger every release, tripping a check
# whose own error message says "large binaries".
#
# `grep -I` treats a file containing NUL bytes as binary, the same heuristic
# git uses to print "Binary files differ". A generated blob of text is still
# caught by review, not here.
grep -qI . "$f" 2>/dev/null && continue

bytes="$(wc -c < "$f" | tr -d ' ')"
# Ceiling division: a sub-1024-byte file must report >=1 KB, never 0, so it
# can't slip past a strict threshold (e.g. HF_MAX_NONLFS_KB=0). Plain
Expand Down
68 changes: 68 additions & 0 deletions scripts/check-large-files.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, it } from "node:test";

const SCRIPT = join(import.meta.dirname, "check-large-files.sh");
const OVER_LIMIT_BYTES = 2 * 1024 * 1024;

/** Run the checker over explicit paths. Exit 0 means "nothing to complain about". */
function check(...paths) {
const result = spawnSync(SCRIPT, paths, { encoding: "utf-8" });
return { ok: result.status === 0, stderr: result.stderr ?? "" };
}

function withFiles(files, run) {
const dir = mkdtempSync(join(tmpdir(), "hf-largefiles-"));
try {
const paths = {};
for (const [name, contents] of Object.entries(files)) {
paths[name] = join(dir, name);
writeFileSync(paths[name], contents);
}
run(paths);
} finally {
rmSync(dir, { recursive: true, force: true });
}
}

const bigBinary = Buffer.alloc(OVER_LIMIT_BYTES);
const bigText = "the quick brown fox jumps over the lazy dog\n".repeat(50_000);

describe("check-large-files", () => {
it("rejects a binary over the limit, and names it", () => {
withFiles({ "big.bin": bigBinary }, ({ "big.bin": path }) => {
const { ok, stderr } = check(path);
assert.equal(ok, false);
assert.match(stderr, /big\.bin/);
});
});

// The cost this hook exists to stop is a binary one: git delta-compresses
// text, so a file that grows a few KB per commit costs a few KB. Before this,
// `docs/changelog.mdx` (half a megabyte of release notes, a little larger
// every release) failed a check whose own message says "large binaries", and
// every release had to pass HF_MAX_NONLFS_KB to get through.
it("accepts a text file over the limit", () => {
withFiles({ "big.txt": bigText }, ({ "big.txt": path }) => {
assert.equal(check(path).ok, true);
});
});

it("accepts a binary under the limit", () => {
withFiles({ "small.bin": Buffer.alloc(1024) }, ({ "small.bin": path }) => {
assert.equal(check(path).ok, true);
});
});

it("reports every offending binary, not just the first", () => {
withFiles({ "a.bin": bigBinary, "b.bin": bigBinary }, ({ "a.bin": a, "b.bin": b }) => {
const { ok, stderr } = check(a, b);
assert.equal(ok, false);
assert.match(stderr, /a\.bin/);
assert.match(stderr, /b\.bin/);
});
});
});
Loading