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>
- 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>