From e46b87b26d246ab0bdc809fb4c76052aeba4a106 Mon Sep 17 00:00:00 2001 From: Edwin van den Houdt Date: Thu, 30 Jul 2026 09:26:05 +0200 Subject: [PATCH] perf(ci): cache node_modules, skip npm ci on a hit (WP-30 #1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit actions/cache on node_modules keyed by package-lock.json hash, across all 4 npm-based jobs (frontend, storybook-a11y, e2e, api-client-drift). The if: guard is what makes this a real speedup: npm ci deletes-then-reinstalls unconditionally, so caching node_modules alone does nothing unless the install step is skipped outright on a cache hit. Unverifiable from this environment — CI timing needs a real Gitea run to confirm; shipped as its own commit so a red run is easy to bisect/revert. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/ci.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3e9068..695970f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,15 @@ jobs: with: node-version: 24 cache: npm + # WP-30: on a hit, npm ci is skipped entirely (not just faster) — caching node_modules + # alone doesn't help since npm ci always deletes-then-reinstalls unconditionally. + - id: node-modules-cache + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: node_modules + key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} - run: npm ci --prefer-offline --no-audit --no-fund + if: steps.node-modules-cache.outputs.cache-hit != 'true' - run: npm run lint # Bounded-context + atomic-layer boundaries (WP-38, dependency-cruiser). - run: npm run dep:check @@ -67,7 +75,13 @@ jobs: with: node-version: 24 cache: npm + - id: node-modules-cache + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: node_modules + key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} - run: npm ci --prefer-offline --no-audit --no-fund + if: steps.node-modules-cache.outputs.cache-hit != 'true' # Cache the chromium download across runs; `install --with-deps` then only # runs the (fast, idempotent) apt deps check on a hit. - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 @@ -122,7 +136,13 @@ jobs: path: ~/.nuget/packages key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj') }} restore-keys: nuget-${{ runner.os }}- + - id: node-modules-cache + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: node_modules + key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} - run: npm ci --prefer-offline --no-audit --no-fund + if: steps.node-modules-cache.outputs.cache-hit != 'true' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.cache/ms-playwright @@ -175,6 +195,12 @@ jobs: path: ~/.nuget/packages key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj') }} restore-keys: nuget-${{ runner.os }}- + - id: node-modules-cache + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: node_modules + key: node-modules-${{ runner.os }}-${{ hashFiles('package-lock.json') }} - run: npm ci --prefer-offline --no-audit --no-fund + if: steps.node-modules-cache.outputs.cache-hit != 'true' - run: npm run gen:api - run: git diff --exit-code src/app/shared/infrastructure/api-client.ts backend/swagger.json