Optimize CI build pipeline (~15 min → ~3-5 min) #59

Merged
chrisp merged 2 commits from ci/build-optimization into main 2026-05-31 04:35:06 +00:00
Owner

Summary

  • Dockerfile layer caching: development-dependencies-env now copies only package.json/package-lock.json before npm ci (was COPY . /app), so the npm install layer is cached on every code-only commit instead of rebuilt from scratch
  • Skip QEMU: platforms: linux/amd64 added to build-push-action, cutting setup-buildx-action from ~5 min to ~30 sec
  • npm cache in CI jobs: Manual actions/cache@v3 blocks (copy-pasted 3×) replaced with actions/setup-node@v4 + cache: 'npm', which handles path/key/restore automatically and pins Node 20 explicitly
  • Harden .npmrc: Switched from COPY .npmrc to --mount=type=secret,id=npmrc in both npm ci stages — the file is available during install but never written into a Docker layer, so it cannot leak through the registry build cache regardless of future contents

Expected timing

Step Before After (code change)
Setup buildx ~5 min ~30 sec
Build + push ~5 min ~1-2 min
Deploy (docker pull) ~5 min ~1-2 min
Total ~15 min ~3-5 min

Test plan

  • Push a code-only commit to main — confirm setup-buildx-action logs ~30s (no QEMU), Docker build shows CACHED for npm install layers, build+push completes in ~1-2 min
  • Check deploy job — docker compose pull should show most layers as Already exists
  • Push a commit that changes package.json — confirm npm layer correctly re-runs (not cached)
  • Confirm deployed app is functional

🤖 Generated with Claude Code

## Summary - **Dockerfile layer caching**: `development-dependencies-env` now copies only `package.json`/`package-lock.json` before `npm ci` (was `COPY . /app`), so the npm install layer is cached on every code-only commit instead of rebuilt from scratch - **Skip QEMU**: `platforms: linux/amd64` added to `build-push-action`, cutting `setup-buildx-action` from ~5 min to ~30 sec - **npm cache in CI jobs**: Manual `actions/cache@v3` blocks (copy-pasted 3×) replaced with `actions/setup-node@v4` + `cache: 'npm'`, which handles path/key/restore automatically and pins Node 20 explicitly - **Harden `.npmrc`**: Switched from `COPY .npmrc` to `--mount=type=secret,id=npmrc` in both `npm ci` stages — the file is available during install but never written into a Docker layer, so it cannot leak through the registry build cache regardless of future contents ## Expected timing | Step | Before | After (code change) | |---|---|---| | Setup buildx | ~5 min | ~30 sec | | Build + push | ~5 min | ~1-2 min | | Deploy (docker pull) | ~5 min | ~1-2 min | | **Total** | **~15 min** | **~3-5 min** | ## Test plan - [ ] Push a code-only commit to main — confirm `setup-buildx-action` logs ~30s (no QEMU), Docker build shows `CACHED` for npm install layers, build+push completes in ~1-2 min - [ ] Check deploy job — `docker compose pull` should show most layers as `Already exists` - [ ] Push a commit that changes `package.json` — confirm npm layer correctly re-runs (not cached) - [ ] Confirm deployed app is functional 🤖 Generated with [Claude Code](https://claude.com/claude-code)
chrisp added 1 commit 2026-05-31 03:40:54 +00:00
Optimize CI build pipeline and harden .npmrc handling
Some checks failed
🚀 Deploy / 🧪 Test (pull_request) Successful in 11m40s
🚀 Deploy / ʦ TypeScript (pull_request) Successful in 10m35s
🚀 Deploy / 🐳 Build (pull_request) Has been cancelled
🚀 Deploy / 🚀 Deploy (pull_request) Has been cancelled
🚀 Deploy / 🔍 Lint (pull_request) Has been cancelled
2c4575c693
- Fix Dockerfile dev-deps layer cache invalidation: copy only package manifests
  before npm ci so the layer is reused on code-only commits
- Skip QEMU by pinning platforms: linux/amd64 in build-push-action (~4 min saving)
- Replace manual actions/cache blocks with actions/setup-node cache: npm in
  test/typecheck/lint jobs (removes 3 duplicate 8-line blocks, pins Node 20)
- Pass .npmrc as a Docker BuildKit secret (--mount=type=secret) instead of
  COPYing it, so it can never leak into registry build-cache layers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chrisp added 1 commit 2026-05-31 04:04:03 +00:00
Remove setup-node from CI jobs — runner has Node pre-installed
All checks were successful
🚀 Deploy / 🧪 Test (pull_request) Successful in 1m34s
🚀 Deploy / ʦ TypeScript (pull_request) Successful in 1m25s
🚀 Deploy / 🔍 Lint (pull_request) Successful in 53s
🚀 Deploy / 🐳 Build (pull_request) Has been skipped
🚀 Deploy / 🚀 Deploy (pull_request) Has been skipped
bbf4aa4668
setup-node@v4 was downloading Node 20 from GitHub (~5 min) instead of
using the runner's pre-installed copy. The Forgejo runner also has no
cache service backend (ETIMEDOUT on save/restore), so the cache: npm
integration provided no benefit and only added overhead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chrisp merged commit 08474631c1 into main 2026-05-31 04:35:06 +00:00
Sign in to join this conversation.
No description provided.