Skip to content

Commit 386cb15

Browse files
bokelleyclaude
andauthored
perf(ci): cache ~/.npm + drop per-invocation npx for storyboard runners (#450)
Three changes informed by an honest read of where the time goes on cold CI runs (per recent feedback): 1. ``actions/cache@v4`` on ``~/.npm`` for both storyboard jobs, keyed by OS only (not by version). Cache survives across ``@adcp/sdk`` releases — ``npm install`` reuses tarballs already in the cache and only fetches the delta. Buys back ~20-25s of network fetch on warm runs. 2. Move installs to a single ``npm install -g @adcp/sdk@latest`` step per job. Subsequent invocations call ``adcp …`` directly instead of paying the per-call ``npx -y -p …`` extract+link tax. Both jobs do this (seller_agent storyboard + v3 ref seller storyboard). 3. ``@adcp/sdk@latest`` stays unpinned — drift detection is the point of these jobs. Caching ``~/.npm`` doesn't fight that: the cache amortizes the disk-side cost across runs while the version resolution still surfaces protocol drift on every invocation. The realistic floor on storyboard CI startup is now ~5-10s on warm runs (no network) vs ~30-45s previously. Cold runs are unchanged (first job populates the cache). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6b89599 commit 386cb15

1 file changed

Lines changed: 48 additions & 16 deletions

File tree

.github/workflows/ci.yml

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,34 @@ jobs:
356356
with:
357357
node-version: "22"
358358

359+
# Cache the npm tarball + extracted package directory so the
360+
# storyboard runner install isn't a cold network fetch every run.
361+
# Key by OS only (not by version) so the cache survives across
362+
# ``@adcp/sdk`` releases — npm install reuses tarballs that are
363+
# already in the cache and only fetches the delta. ``@latest`` is
364+
# intentional for drift detection (see "Run storyboard suite"
365+
# below); the cache amortizes the 5-15 s of fetch+extract that
366+
# would otherwise repeat on every CI run.
367+
- name: Cache ~/.npm
368+
uses: actions/cache@v4
369+
with:
370+
path: ~/.npm
371+
key: ${{ runner.os }}-npm-adcp-sdk
372+
restore-keys: |
373+
${{ runner.os }}-npm-
374+
375+
- name: Pre-install @adcp/sdk (once, then call binary directly)
376+
# Single install step at the top of the job; subsequent runner
377+
# calls invoke the already-installed binary instead of paying
378+
# the ``npx -y -p ...`` per-invocation extract+link tax.
379+
# ``@adcp/sdk@latest`` is intentionally unpinned: this is AdCP's
380+
# own CI running AdCP's own canonical runner — tracking latest
381+
# surfaces protocol drift as soon as it ships, which is the
382+
# point of this job.
383+
run: |
384+
npm install -g @adcp/sdk@latest
385+
adcp --version
386+
359387
- name: Install dependencies
360388
run: |
361389
python -m pip install --upgrade pip
@@ -388,11 +416,11 @@ jobs:
388416
389417
- name: Run storyboard suite
390418
timeout-minutes: 5
391-
# @adcp/sdk@latest is intentionally unpinned — this is AdCP's own CI
392-
# running AdCP's own canonical runner. Tracking latest surfaces protocol
393-
# drift as soon as it ships, which is the point of this job.
419+
# ``adcp`` was installed once at job start (see "Pre-install"
420+
# step) — call the binary directly to skip per-invocation
421+
# ``npx`` extract+link overhead.
394422
run: |
395-
npx -y -p @adcp/sdk@latest adcp storyboard run \
423+
adcp storyboard run \
396424
http://127.0.0.1:3001/mcp media_buy_seller \
397425
--json --allow-http \
398426
> storyboard-result.json
@@ -484,23 +512,25 @@ jobs:
484512
uses: actions/setup-node@v4
485513
with:
486514
node-version: "22"
487-
# No cache: requires a package-lock.json which this Python
488-
# repo doesn't ship. The pre-install step below uses
489-
# ``npm install -g`` which is fast on the runner anyway
490-
# (~3-5s with warm tarball mirrors).
515+
516+
# Cache ~/.npm by OS only so subsequent runs hit the tarball
517+
# cache; npm install reuses what's there and only fetches the
518+
# delta on a new ``@latest`` release. See the storyboard job
519+
# above for the same pattern + rationale.
520+
- name: Cache ~/.npm
521+
uses: actions/cache@v4
522+
with:
523+
path: ~/.npm
524+
key: ${{ runner.os }}-npm-adcp-sdk
525+
restore-keys: |
526+
${{ runner.os }}-npm-
491527
492528
- name: Install dependencies
493529
run: |
494530
python -m pip install --upgrade pip
495531
pip install -e ".[dev,pg]"
496532
497-
- name: Pre-install @adcp/client (separate from boot)
498-
# Pull the package + its deps into the npm cache up-front so the
499-
# boot step doesn't have to do an install in its 60s readiness
500-
# window. ``npx --yes`` fetches into the cache; the
501-
# ``--package=...`` form leaves an installed copy that subsequent
502-
# ``npx`` invocations resolve instantly. ``adcp --version`` is a
503-
# cheap smoke that the binary is wired correctly.
533+
- name: Pre-install @adcp/sdk (once, then call binary directly)
504534
run: |
505535
npm install -g @adcp/sdk@latest
506536
adcp --version
@@ -592,7 +622,9 @@ jobs:
592622
# /etc/hosts override so the buyer can reach acme.localhost
593623
# (the seeded tenant subdomain).
594624
echo "127.0.0.1 acme.localhost" | sudo tee -a /etc/hosts
595-
npx -y -p @adcp/sdk@latest adcp storyboard run \
625+
# ``adcp`` was installed once at job start — call the binary
626+
# directly to skip per-invocation ``npx`` extract+link.
627+
adcp storyboard run \
596628
http://acme.localhost:3001/mcp media_buy_seller \
597629
--json --allow-http \
598630
> v3-storyboard-result.json || true

0 commit comments

Comments
 (0)