Files
hermes-agent/.github/workflows/js-tests.yml
kshitij de0abc0617 ci(js-tests): drop dead electron download-cache path, skip redundant npm upgrade
Review findings on the caching commit:

- ~/.cache/electron was dead weight: with npm ci skipped on an exact
  cache hit, the download cache is never read (electron's unpacked
  binary lives in node_modules/electron/dist, inside the cached tree);
  it only inflated every saved archive by ~110MB.
- 'npm i -g npm@12' ran unconditionally in all 14 matrix jobs
  (~5-15s each); now a no-op when the bundled npm is already 12.x,
  which also keeps the installed major aligned with the npm12
  cache-key tag.

yaml + actionlint pass.
2026-08-14 12:14:03 -04:00

126 lines
5.0 KiB
YAML

# .github/workflows/js-tests.yml
name: JS Tests
on:
workflow_call:
jobs:
workspaces:
name: List npm workspaces
runs-on: ubuntu-latest
timeout-minutes: 20
outputs:
checks: ${{ steps.set-matrix.outputs.checks }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 26
cache: npm
- name: grab npm 12
run: |
# No-op once the bundled npm is already 12.x — saves ~5-15s/job and
# keeps the installed major aligned with the npm12 cache-key tag.
npm --version | grep -q '^12\.' || npm i -g npm@12
# ``setup-node``'s ``cache: npm`` only caches the ~/.npm tarball cache;
# every job still re-extracts the full workspace node_modules and reruns
# postinstalls (including the Electron binary fetch). Cache the installed
# tree itself, keyed on the lockfile, and skip ``npm ci`` on an exact
# hit. No restore-keys: a partial hit would leave a stale tree, so
# anything but an exact lockfile match reinstalls from scratch.
# The discovery job installs with --ignore-scripts, so its tree differs
# from the check jobs' — hence the distinct ``-noscripts`` key.
- name: Restore node_modules
id: node-modules-cache
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: |
node_modules
apps/*/node_modules
ui-tui/node_modules
ui-tui/packages/*/node_modules
tests-js/node_modules
web/node_modules
key: node-modules-noscripts-${{ runner.os }}-node26-npm12-${{ hashFiles('package-lock.json') }}
- uses: ./.github/actions/retry
if: steps.node-modules-cache.outputs.cache-hit != 'true'
with:
command: npm ci --ignore-scripts
- id: set-matrix
run: |
node -e '
const { execSync } = require("child_process");
const pkgs = JSON.parse(execSync("npm query .workspace", { encoding: "utf-8" }));
if (pkgs.length === 0) {
console.error("::error::Workspace discovery produced an empty package list — refusing to emit a zero-length matrix (would skip all JS/TS checks silently).");
process.exit(1);
}
const checks = [];
for (const pkg of pkgs) {
const scripts = pkg.scripts || {};
const subs = Object.keys(scripts).filter(s => /^check:.+$/.test(s));
if (subs.length > 0) {
for (const script of subs) {
checks.push({ package: pkg.location, script });
}
} else if (scripts.check) {
checks.push({ package: pkg.location, script: "check" });
}
}
if (checks.length === 0) {
console.error("::error::No check scripts found in any workspace package.");
process.exit(1);
}
process.stdout.write("checks=" + JSON.stringify(checks) + "\n");
' >> "$GITHUB_OUTPUT"
check:
name: ${{ matrix.package }} / ${{ matrix.script }}
needs: workspaces
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
matrix:
include: ${{ fromJson(needs.workspaces.outputs.checks) }}
fail-fast: false # report all failures, not just the first one
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 26
cache: npm
- name: grab npm 12
run: |
# No-op once the bundled npm is already 12.x — saves ~5-15s/job and
# keeps the installed major aligned with the npm12 cache-key tag.
npm --version | grep -q '^12\.' || npm i -g npm@12
# Same rationale as the discovery job's cache above, but this ``npm ci``
# runs WITH install scripts, so the tree includes postinstall artifacts
# (electron's postinstall unpacks its binary into node_modules/electron/
# dist, which lives inside the cached tree — the ~/.cache/electron
# download cache is deliberately NOT cached: with npm ci skipped on hit
# it would never be read, only inflate the archive).
- name: Restore node_modules
id: node-modules-cache
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: |
node_modules
apps/*/node_modules
ui-tui/node_modules
ui-tui/packages/*/node_modules
tests-js/node_modules
web/node_modules
key: node-modules-scripts-${{ runner.os }}-node26-npm12-${{ hashFiles('package-lock.json') }}
- uses: ./.github/actions/retry
if: steps.node-modules-cache.outputs.cache-hit != 'true'
with:
command: npm ci
- run: npm run --prefix ${{ matrix.package }} ${{ matrix.script }}