Build Minutes
You fix a typo in the README. Push. Vercel builds the entire app, including the parts that have nothing to do with documentation. That build takes a minute and a half. You're billed for it.
Multiply by every README change, every comment fix, every CHANGELOG update across a year. On a fast-moving repo this is a few hundred unnecessary builds. Each one pays for a full reinstall, a full type check, a full bundle compilation, just to produce a deployment that is byte-identical to the one already running.
Vercel has an exit hatch. Before each build, Vercel runs whatever shell command you point it at. If that command exits 0, the build is skipped. If it exits 1, the build proceeds. We're going to point it at a tiny script that says "if only docs changed, skip."
Outcome
Saturday has a working ignore-build-step.sh script in the repo root, and the project's Ignored Build Step setting is wired to run it. Doc-only commits skip the build.
Hands-on exercise 4.3
Three steps. One file, one file mode change, one dashboard toggle.
Requirements:
- Create
ignore-build-step.shat the root of the repo - The script should compare the current commit against its parent and exit 0 if the only changed files are Markdown or live under
docs/ - Run
chmod +x ignore-build-step.shso Vercel can execute it - Open Saturday > Settings > Git
- Find the Ignored Build Step section
- Set the command to
bash ignore-build-step.sh - Commit the script, push, and test by making a docs-only commit
Implementation hints:
- Exit code 0 means skip, exit code 1 means build. Get this backwards and your skip script will trigger builds and your build script will skip them. It is the most common mistake people make with this feature, and it's worth verifying twice.
- The
git diff --quiet HEAD^ HEAD -- ':!*.md' ':!docs/*'form is concise.--quietreturns 0 if there's no diff and 1 if there is. The:!syntax excludes paths from the diff. So if the only changes are inside excluded paths, --quiet returns 0 (no diff in the included set), and we exit 0 (skip the build). - The script runs from the project root with the deploying commit checked out. You don't need to
cdanywhere. - Test with two commits: a code change and a docs change. The code one should produce a build, the docs one should be skipped.
Try It
After you've added the script and configured the setting, make a docs-only commit:
echo "## New section" >> README.md
git commit -am "docs: add new README section"
git pushOpen the Deployments tab in Saturday. The new commit should appear with a status like:
docs: add new README section
Skipped (Ignored Build Step)
That's the success signal. No build minutes consumed, no new production deployment created, the existing one stays live.
Now make a code change:
echo "// trivial comment" >> app/page.tsx
git commit -am "chore: trivial comment"
git pushThe deployment should proceed normally:
chore: trivial comment
Building... Ready
Build minutes consumed, new production deployment created.
If both behaviors hold, the script is doing its job.
Done-When
ignore-build-step.shexists at the repo root- The script is executable (
ls -l ignore-build-step.shshows thexbit) - Saturday > Settings > Git > Ignored Build Step is set to
bash ignore-build-step.sh - A docs-only commit produces a "Skipped" status in Vercel
- A code commit triggers a normal build
Troubleshooting
Every commit gets skipped.
The exit code logic is inverted. Your script is returning 0 when it should be returning 1, or the script is silently failing and bash is treating the failure as exit 0. Add set -e at the top of the script (which the solution version has) so silent failures don't pass.
Every commit triggers a build, even README-only ones.
The script isn't being executed, or the path check is wrong. Common causes: forgot chmod +x, the dashboard setting is set to the wrong path, the :! exclude syntax is interpreted differently in your environment. Try running the script locally on a docs-only diff: git diff --quiet HEAD^ HEAD -- ':!*.md' ':!docs/*' && echo "skip" || echo "build".
The first deploy with the script enabled triggered a "Skipped" status, but I wanted it to build.
The script compares against the parent commit. The commit that adds the script itself only touches ignore-build-step.sh, which isn't in the exclude list, so the script should exit 1 and build. If you're seeing skip, double-check the exclude patterns, your shell might be expanding :!*.md before git sees it. Quote the patterns: ':!*.md'.
Solution
The finished ignore-build-step.sh is on the complete branch if you want to check your version against it.
The script:
#!/bin/bash
# Vercel Ignored Build Step script for Saturday.
# Configured under Project Settings > Git > Ignored Build Step.
#
# Exit 0 = skip build (proceed without deploying)
# Exit 1 = proceed with build
set -e
if git diff --quiet HEAD^ HEAD -- ':!*.md' ':!docs/*'; then
echo "Only docs changed. Skipping build."
exit 0
fi
echo "Code changes detected. Proceeding with build."
exit 1And the dashboard configuration:
Settings > Git > Ignored Build Step
Command: bash ignore-build-step.sh
You can get more elaborate. Monorepo users often check whether files under a specific app or package changed: git diff --quiet HEAD^ HEAD -- apps/saturday/ would skip when nothing in the Saturday app changed even if other things in the repo did. For a single-app repo, the docs-only check is the highest-leverage version.
Up next: the last cost lever. Sampling the observability tools so you keep the insights without paying for every event.
Was this helpful?