
Shipping Build Artifacts
Make the build step a real gate on what you actually distribute, build scripts that...
Install
npx skills add kajisho5/ffmpeg-skill --skill shipping-build-artifacts -g -a claude-code -y- Repository
- kajisho5/ffmpeg-skill4.3k
- Category
- Writing
- Updated
- 4d ago
- License
- MIT
- Context cost
- Mediumabout 1,940 tokens
- Runs scripts
- No, instructions only
What it does
Make the build step a real gate on what you actually distribute, build scripts that warn and exit 0 on a missing input, size checks with only an upper bound, hand-maintained file lists that drift from the entrypoints they must cover, committed bundles that go stale when only the source changes, GNU-only shell in release scripts that aborts on the other OS, and verification that runs against the source tree instead of the artifact. Use when writing or reviewing a build/package script, a `dist/` copy step, a release workflow that uploads a zip or installer, or a committed compiled asset.
Shipping Build Artifacts
Lint, type-check, and tests run against the source tree. What users install is a different set of bytes, assembled by a script that most gates never look at, then uploaded by a workflow that trusts whatever the script left behind. Every failure below ships a broken or stale artifact under fully green CI.
A script that warns and exits 0 is not a gate
The shape is universal: a declared list of inputs, a copy loop, a friendly warning when one is missing.
for (const f of DIST_FILES) {
if (!fs.existsSync(f)) {
console.warn(`Warning: ${f} not found, skipping`); // build "succeeds"
continue;
}
fs.copyFileSync(f, path.join("dist", f));
}
Move one required file aside and the script prints a line nobody reads, exits 0,
and produces a dist/ without it. Nothing downstream notices: the test job ran
against the source tree, and the release job zips dist/ and attaches it to a
public release. The artifact is wholly non-functional, the entrypoint imports a
file that isn't there, and the failure is discovered by users.
const missing = DIST_FILES.filter((f) => !fs.existsSync(f));
if (missing.length) {
console.error(`Missing build inputs: ${missing.join(", ")}`);
process.exit(1);
}
The rule: inside a build script, warn may only describe something the artifact
survives without. If you cannot say what still works when that file is absent, it
is an error and the process must exit non-zero.
Bound the artifact size on both sides
A packaging check with only a ceiling, "fail if the zip exceeds 500 KB", is a cost guard, not a correctness one. A build that silently dropped half its files is smaller, so it passes the only check that exists.
assert(bytes < 500 * 1024, "package too large");
assert(bytes > 20 * 1024, "package suspiciously small, inputs likely missing");
assert(entries.length === DIST_FILES.length, "package entry count mismatch");
