Page-weight budget in CI
Fail a build when a committed image is over a size budget.
A common gate: don’t let a hero image or a screenshot land in the repo bigger than it needs to be.
imagekbreducer can both enforce and fix this in one CI step.
Check-only: fail if anything is over budget
Use --dry-run --json so nothing is written — this step should only ever report, never mutate the
repo on its own:
#!/usr/bin/env bash
set -euo pipefail
BUDGET="200kb"
FAILED=0
for file in $(git diff --name-only --diff-filter=ACM "$BASE_SHA" -- '*.jpg' '*.jpeg' '*.png' '*.webp'); do
result=$(imagekbreducer compress "$file" --to "$BUDGET" --dry-run --json --quiet || true)
ok=$(echo "$result" | jq -r '.results[0].ok')
if [ "$ok" != "true" ]; then
echo "::error file=$file::over the ${BUDGET} budget and cannot be brought under it even after recompression -- $(echo "$result" | jq -r '.results[0].error.message')"
FAILED=1
fi
done
exit $FAILED
.results[0].ok is what actually decides this, not a raw byte-count comparison against the source
file — a source that’s already well over budget but compresses fine under it should pass; only a
file the tool genuinely can’t bring under the budget (a target-unreachable failure — see
Give-up codes) should block the merge.
Fix-in-place: compress on commit, fail only if it can’t reach budget
If you’d rather the CI step just fix the problem instead of only reporting it:
imagekbreducer compress src/images/*.png --to 200kb --format webp --out dist/images --json > result.json
if ! jq -e '.ok' result.json > /dev/null; then
jq -r '.results[] | select(.ok == false) | "\(.input): \(.error.message)"' result.json
exit 1
fi
--format webp here is doing real work, not just picking a preference: WebP’s own header/entropy
floor is lower than JPEG’s, so a PNG that can’t reach a tight budget as JPEG frequently can as
WebP — one of the suggestions the tool itself offers on a
FORMAT_FLOOR failure (exit 12).
Precomputing the budget once, checking it forever
For images that rarely change, run the compression once and commit the compressed result — then a much cheaper CI check just confirms nothing regressed, with no compression step at all:
for file in dist/images/*.webp; do
bytes=$(wc -c < "$file")
[ "$bytes" -le 204800 ] || { echo "$file is ${bytes} bytes, over the 200kb budget"; exit 1; }
done
See Using it in CI for exit-code and --json fundamentals this recipe builds on.