From 9e0c5359fa086068ac0ea0832a7f1af57210da77 Mon Sep 17 00:00:00 2001 From: Fielding Johnston Date: Mon, 7 Sep 2026 17:08:19 -0500 Subject: [PATCH] Skip redundant Vercel builds with an Ignored Build Step Every push built all three Vercel projects, and each deployment branch also produced a Preview on the projects it is not production for (main -> ripguard-testnet preview, testnet -> ripguard + ripguard-sol previews). Nine deployments per PR cycle, three of them useful. Each carries a ~23 MB function bundle and Vercel keeps the last 20 production + 20 preview deployments per project regardless of retention policy, which is how three projects reached 3.3 GB of Functions Storage. scripts/vercel-ignore.sh, wired from packages//vercel.json (Vercel reads vercel.json from the Root Directory), exits 0 to skip when: - VERCEL_ENV is preview and the ref is main or testnet, or - nothing under the package or the workspace manifests changed since VERCEL_GIT_PREVIOUS_SHA, the last successful deployment of the branch. Not HEAD^: a testnet fast-forward lands several commits at once. Anything uncertain (no previous SHA, SHA outside the shallow clone, system env vars not exposed) builds. Co-Authored-By: Claude Fable 5.1 --- AGENTS.md | 9 ++++++++ packages/app-sol/vercel.json | 4 ++++ packages/app/vercel.json | 4 ++++ scripts/vercel-ignore.sh | 43 ++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 packages/app-sol/vercel.json create mode 100644 packages/app/vercel.json create mode 100755 scripts/vercel-ignore.sh diff --git a/AGENTS.md b/AGENTS.md index 2b977e2..db2170d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,6 +25,15 @@ Verify a deploy the way Vercel does, not the way CI does: `cd packages/ && CI=1 pnpm install && ./node_modules/.bin/next build`. A green `pnpm install --frozen-lockfile` at the repo root does not exercise this path. +Because `rootDirectory` is set, Vercel reads `vercel.json` from `packages//`, not +the repo root. Each package's `vercel.json` wires `scripts/vercel-ignore.sh` as the +Ignored Build Step: it skips Preview builds of `main`/`testnet` (each is production for +one project and a wasted Preview on the others) and skips any build where nothing under +the package or the workspace manifests changed since the last successful deployment. +Every retained deployment holds a ~23 MB function bundle, and Vercel keeps the last 20 +production + 20 preview deployments per project regardless of retention policy, so +deployment count is what drives Functions Storage. + ## Maintaining this file Keep this file for knowledge useful to almost every future agent session in this project. diff --git a/packages/app-sol/vercel.json b/packages/app-sol/vercel.json new file mode 100644 index 0000000..1088e14 --- /dev/null +++ b/packages/app-sol/vercel.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "ignoreCommand": "bash \"$(git rev-parse --show-toplevel)/scripts/vercel-ignore.sh\" packages/app-sol" +} diff --git a/packages/app/vercel.json b/packages/app/vercel.json new file mode 100644 index 0000000..fa79c0d --- /dev/null +++ b/packages/app/vercel.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "ignoreCommand": "bash \"$(git rev-parse --show-toplevel)/scripts/vercel-ignore.sh\" packages/app" +} diff --git a/scripts/vercel-ignore.sh b/scripts/vercel-ignore.sh new file mode 100755 index 0000000..007d310 --- /dev/null +++ b/scripts/vercel-ignore.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Vercel "Ignored Build Step" for one package of this monorepo. +# +# Exit 0 = skip the build, exit 1 = build. Anything uncertain builds. +# Wired from packages//vercel.json (Vercel reads vercel.json from each +# project's Root Directory, so the shared logic lives here). +# +# Every push used to build all three Vercel projects, and the two deployment +# branches each produced a Preview on the projects they are not production +# for. That tripled Functions Storage for nothing. +set -u +pkg="${1:?usage: vercel-ignore.sh packages/}" +cd "$(git rev-parse --show-toplevel)" || exit 1 + +# 1. `main` is production for ripguard + ripguard-sol, `testnet` for +# ripguard-testnet. A push to either also triggers a Preview build on the +# other project(s) that nobody looks at. +if [ "${VERCEL_ENV:-}" = "preview" ]; then + case "${VERCEL_GIT_COMMIT_REF:-}" in + main|testnet) + echo "ignore: preview of deployment branch '$VERCEL_GIT_COMMIT_REF'" + exit 0 + ;; + esac +fi + +# 2. Nothing this package depends on changed since the last successful +# deployment of this branch. Compare against that SHA, not HEAD^: a +# fast-forward of `testnet` lands several commits at once and HEAD^ would +# only see the last one. Unknown base (first deploy, shallow clone too +# short) -> build. +base="${VERCEL_GIT_PREVIOUS_SHA:-}" +if [ -n "$base" ] && git cat-file -e "${base}^{commit}" 2>/dev/null; then + if git diff --quiet "$base" HEAD -- \ + "$pkg" \ + package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc .node-version \ + scripts/vercel-ignore.sh; then + echo "ignore: no changes under $pkg or the workspace manifests since ${base:0:7}" + exit 0 + fi +fi + +exit 1