Skip to content

feat(collab): pre-warm pnpm store with frontend + api deps at build time#43

Merged
hblanken merged 1 commit into
collabfrom
feat/collab-prewarm-pnpm-store
Jun 14, 2026
Merged

feat(collab): pre-warm pnpm store with frontend + api deps at build time#43
hblanken merged 1 commit into
collabfrom
feat/collab-prewarm-pnpm-store

Conversation

@hblanken

Copy link
Copy Markdown

Speed win V1 (PR 4 of 5) — the single biggest user-visible latency in the collab flow.

The problem

A cold pnpm install inside a fresh frontend workspace takes ~10 min (3,500-package tree, network-bound). Every participant pays it on every fresh session.

The fix

pnpm's store is content-addressed and shared across installs, so populating it at build time turns every runtime session install into a near-offline store-link (~30 s) instead of a 10-min download.

New warm-store RUN in the Dockerfile uses pnpm fetch (reads only the lockfile, downloads to the store, links no node_modules — exactly a store warm) for unleashlive/frontend + unleashlive/api. Runs with HOME=/home/opencode so pnpm's default store path matches what the runtime preview install (uid 10001) reads; the existing final-stage chown -R 10001:10001 /home/opencode hands the warmed store to the runtime user.

Auth — one operator action required to activate

Cloning these private repos at build time needs a cross-repo read token, passed as a BuildKit secret (id=github_token), mounted only for that RUN — never baked into a layer.

To turn it on: provision a fine-grained PAT (or GitHub App installation token) with Contents: read on unleashlive/frontend + unleashlive/api, store it as the repo secret WARM_STORE_GITHUB_TOKEN. deploy-collab.yml already wires it through.

Safe to merge before the secret exists

When the secret is unset, build-push-action passes an empty value, the Dockerfile's [ ! -s ] guard skips the warm, and the image builds normally — runtime installs just stay cold until a warmed image ships. Clone/fetch failures are caught per-repo (no pipe-masked exit codes) and never abort the build.

Tradeoff

Cold image build grows ~5-10 min (the warm can't use a build cache mount — the store must be baked into the image, not a throwaway cache). Worth it: one operator's build-time pain per deploy vs. every participant's 10-min wait on every fresh session.

Staleness is fine — a lockfile that drifts post-build means pnpm fetches only the delta at runtime; the unchanged thousands are store hits.

Merge-order note

Touches Dockerfile in a different region than PR #38 (Headroom MCP edits apt-get + the config printf; this adds a RUN after the config bake). Should auto-merge; if not, trivial rebase.

Test plan

  • Merge + set WARM_STORE_GITHUB_TOKEN, deploy
  • Build log shows [warm-store] pnpm fetch for frontend… + …for api… + pre-warm complete
  • First session launch against frontend: install drops from ~10 min to ~30 s (CloudWatch Done in …)
  • Without the secret: build log shows no github_token secret — SKIPPING, image builds fine
  • Bad/expired token: per-repo WARNING clone failed, build still succeeds

🤖 Generated with Claude Code

Speed win V1 — the single biggest user-visible latency in the collab
flow.  A cold `pnpm install` inside a fresh frontend workspace takes
~10 min (3,500-package tree, network-bound).  pnpm's store is
content-addressed and shared across installs, so populating it at BUILD
time turns every runtime session install into a near-offline store-link
("Done in ~30 s") instead of a 10-min download.

Dockerfile: new "warm-store" RUN after the config bake.  Uses
`pnpm fetch` (reads ONLY the lockfile, downloads to the store, links no
node_modules — exactly a store warm) for unleashlive/frontend +
unleashlive/api.  Runs with HOME=/home/opencode so pnpm's default store
path matches what the runtime preview install (uid 10001) reads; the
existing final-stage `chown -R 10001:10001 /home/opencode` hands the
warmed store to the runtime user.

Auth: cloning these PRIVATE repos at build time needs a cross-repo read
token, passed as a BuildKit secret (id=github_token) — mounted only for
that RUN, never baked into a layer.  deploy-collab.yml wires it from a
new repo secret WARM_STORE_GITHUB_TOKEN.

SAFE TO MERGE BEFORE THE SECRET EXISTS: when the secret is unset,
build-push-action passes an empty value, the Dockerfile's `[ ! -s ]`
guard skips the warm, and the image builds normally — runtime installs
just stay cold until a warmed image ships.  Clone/fetch failures are
caught per-repo (no pipe-masked exit codes) and never abort the build.

Tradeoff: cold image build grows ~5-10 min (the warm can't use a build
cache mount — the store must be baked into the image, not a throwaway
cache).  Worth it: one operator's build-time pain per deploy vs. every
participant's 10-min wait on every fresh session.

Staleness is fine — a lockfile that drifts post-build means pnpm
fetches only the delta at runtime; the unchanged thousands are store
hits.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hblanken hblanken merged commit aeedefc into collab Jun 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant