Skip to content

fix(gcp-cloud-run): include all workspace build dependencies#2608

Merged
miguel-heygen merged 8 commits into
mainfrom
fix/2601-gcp-workspace-manifests
Jul 17, 2026
Merged

fix(gcp-cloud-run): include all workspace build dependencies#2608
miguel-heygen merged 8 commits into
mainfrom
fix/2601-gcp-workspace-manifests

Conversation

@miguel-heygen

Copy link
Copy Markdown
Collaborator

Fixes #2601.

Reproduced v0.7.60 from the tag: Docker frozen install failed because five workspace manifests were omitted; after adding manifests, a fresh build failed because dependency dist artifacts were absent.

Changes:

  • Copy all workspace manifests and required source trees.
  • Build core, parsers, lint, SDK, sdk-playground, studio-server, and engine before producer/adapter.
  • Add deterministic manifest/source coverage check.

Verification:

  • bun run --cwd packages/gcp-cloud-run test:dockerfile-workspaces
  • docker build --progress=plain -f packages/gcp-cloud-run/Dockerfile -t hf-2601-fixed3 . (success; image built).

Source issue: #2601

@james-russo-rames-d-jusso james-russo-rames-d-jusso left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First-look adversarial review at HEAD cdca11bcee962864ba647ddc2fa90ff31a9b17cd. Small, focused Dockerfile fix (3 files, +61/-3) closing #2601 — the release-tag fresh-clone docker build fails because 5 workspace manifests + their sources aren't COPY'd. Reviewed against the class-of-drift lens (the reporter's core insight) and Cloud Run adapter runtime path.

Findings

Blockers: none.

Concerns: 3 — one on the coverage test's static source list, one on it not being wired into CI, one on Dockerfile build-order divergence from the root build script (inline C1/C2/C3).

Nits: 2 (inline N1/N2).

Green surface (verified)

  • All 14 workspace manifests copied. Enumerated packages/* at HEAD (aws-lambda, cli, core, engine, gcp-cloud-run, lint, parsers, player, producer, sdk, sdk-playground, shader-transitions, studio, studio-server) — every one has a matching COPY packages/<name>/package.json line. Manifest-drift is now dynamically detected on next workspace addition (C1 caveat notwithstanding).
  • Cross-package imports verified. Every @hyperframes/{parsers,lint,studio-server} and @hyperframes/{sdk,sdk-playground} import from packages/{core,producer,gcp-cloud-run}/src/* matches a source-tree COPY line — no obvious import that would still resolve to an absent tree at build time.
  • Build order works despite reversing root's topo-orderparsers/package.json exports map bun/import/types conditions to ./src/*.ts (source), so bun run --cwd packages/core build (which invokes tsc) can resolve @hyperframes/parsers types from source without parsers' dist/ being built first. Same for lint/studio-server. See C3 for the divergence.
  • --frozen-lockfile install now succeeds — all 14 workspace symlinks resolvable.
  • Font-data generation and adapter build preserved — the bunx tsx scripts/generate-font-data.ts step and bun run --cwd packages/gcp-cloud-run build tail are unchanged.
  • Small, focused diff — no scope creep beyond the reported bug.

What I didn't verify

  • Runtime footprint impact. Copying 5 additional full source trees increases image size + Docker layer cache invalidation on any of those packages' source changes. Might be worth a .dockerignore sweep on packages/{lint,parsers,sdk,sdk-playground,studio-server}/test / test-fixtures / node_modules if not already excluded. Not blocking; the fix is correct.
  • Whether the built gcp-cloud-run/dist/server.js bundle actually references any of the newly-copied source trees at RUNTIME — if the adapter bundle is self-contained (esbuild bundles workspace deps), the source COPYs are only needed at BUILD time and could theoretically be dropped in a later multi-stage refinement. Out of scope for this fix.
  • Layer 2 exhaustiveness on future imports. I sampled cross-package imports for the render path but didn't audit every symbol in the transitive graph.
  • CI green post-merge — statusChecks are IN_PROGRESS at review time; the CI's own bun run build step should catch import-resolution divergence between root and Dockerfile if the resolution ever regresses.

Merge gate

Correct closure of #2601 with a clean, minimal Dockerfile fix. C1/C2 are the most substantive — the coverage check is a nice belt-and-suspenders addition but only actually catches drift if it fires on future PRs; wiring it into CI (or into an existing check:* runner in the root package.json) locks in the value. C3 is a divergence smell worth aligning even if functionally correct today.

LGTM on the fix approach; holding C1/C2 as substantive follow-ups worth Miguel's decision before ship. Leaving as COMMENTED.

Review by Rames D Jusso

Comment thread packages/gcp-cloud-run/check-dockerfile-workspaces.mjs Outdated
Comment thread packages/gcp-cloud-run/package.json
Comment thread packages/gcp-cloud-run/Dockerfile
Comment thread packages/gcp-cloud-run/check-dockerfile-workspaces.mjs Outdated
Comment thread packages/gcp-cloud-run/check-dockerfile-workspaces.mjs Outdated

@vanceingalls vanceingalls left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adversarial R1 at cdca11bce. Read the Dockerfile diff, the coverage-check .mjs, root package.json build script, sibling Dockerfile.test, packages/core/package.json scripts, issue #2601 body + reporter's follow-up comment, and enumerated 14 packages/*/package.json on master.

Right on the reported failure mode — 5 missing manifests copied, 5 new source trees copied, workspace deps built before producer/adapter, deterministic coverage check added. Mechanism addresses issue body's Layer 1 + Layer 2 and reporter's Layer 3 (all three layers). Coverage check is real static parse (not aspirational): regex-extracts COPY lines from the actual Dockerfile and diffs against readdirSync('packages/').

Three concerns, one blocking + two follow-ups.

1. build:hyperframes-runtime:modular was dropped entirely — is the modular artifact still needed at runtime? (P1, please clarify or restore)

The OLD Dockerfile's only core build step was bun run --filter @hyperframes/core build:hyperframes-runtime:modular — invoking SANDBOX_RUNTIME_VARIANT=modular tsx scripts/build-hyperframes-runtime-artifact.ts per packages/core/package.json. The NEW Dockerfile replaces this with bun run --cwd packages/core build, whose script chain is build:hyperframes-runtime && build:position-edits-render && tsc && rewrite-esm-extensions — NOT the :modular variant. The modular variant produces a distinct artifact (different env var → different output). Verification docker build ... success proves the image assembles but doesn't exercise the runtime; if the producer bundle or the Cloud Run server loads the modular runtime artifact at request time, this is a silent runtime regression that CI won't catch. Either (a) explain in the PR body why the modular variant is no longer needed here (and consider a note in the Dockerfile comment), or (b) add bun run --cwd packages/core build:hyperframes-runtime:modular back to the RUN chain after the packages/core build step.

2. Build order diverges from root package.json and sibling Dockerfile.test (P2, cross-scaffold drift)

Canonical order in root package.json build: {parsers,lint,studio-server}core → the rest. Dockerfile.test (sibling scaffold) encodes exactly this: bun run --filter '@hyperframes/{parsers,lint,studio-server}' build && bun run --cwd packages/core build. Reporter's follow-up on #2601 also proposed this order. This PR builds core FIRST, then parsers/lint/sdk/sdk-playground/studio-server, then engine. It empirically builds (thanks to workspace-source resolution during core's own build), but diverges from three sources of truth. Suggest aligning with the canonical order — cheap cross-scaffold drift-safety, and future maintainers grepping either sibling won't be surprised.

3. Coverage check's source side is hardcoded; build-step layer isn't tested (P2, follow-up)

Manifest side is dynamic (readdirSync('packages/') → catches every new workspace). Sources side is a fixed 9-name literal (requiredSourcePackages); adding a new package that also needs its source in the Dockerfile won't be caught. And the reporter's Layer 3 (build-step order/completeness) isn't validated at all — the test locks copy state but not RUN state. Consider (a) deriving requiredSourcePackages from a parse of the RUN chain, or (b) adding an assertion that each package in the build-order chain has an earlier source COPY line. Not blocking on its own — the current check is a meaningful step up from the pre-PR state.

CI: Format + Preflight (lint + format) already FAILURE at head; several other checks still in progress. Held-until-green regardless of the above.

Reporter follow-up read: reporter's Layer 3 diagnosis IS addressed in spirit (all workspace deps get built before producer). Not refuted. Not blocking on follow-ups.

— Via

@miguel-heygen
miguel-heygen force-pushed the fix/2601-gcp-workspace-manifests branch 2 times, most recently from 4bb21bf to 41e46f6 Compare July 17, 2026 03:46

@james-russo-rames-d-jusso james-russo-rames-d-jusso left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R2 delta review at HEAD 41e46f65656ceba90df6e0fb8eecf36a6c2dced3. Delta vs R1 SHA cdca11bcee:

Delta

  • Dockerfile:116 — added && bun run --cwd packages/core build:hyperframes-runtime:modular \ between the core build step and the parsers step. Restores the SANDBOX_RUNTIME_VARIANT=modular runtime artifact that R1's core build didn't emit (R1's bun run --cwd packages/core build invokes build:hyperframes-runtime — the non-modular variant — via the composite build script). The old pre-PR command was --filter @hyperframes/core build:hyperframes-runtime:modular, so this restores byte-parity with what shipped at v0.7.60 for the modular artifact consumers.
  • check-dockerfile-workspaces.mjs — prettier line-wrapping on the two long output lines. No semantic change.

R1 concern verdict

ID Status Notes
C1 hardcoded requiredSourcePackages 🟡 unchanged List still 9 hardcoded entries. Future source-tree drift not detected. Explicit follow-up material.
C2 coverage test not wired into CI 🟡 unchanged Still no CI invocation of test:dockerfile-workspaces. Silent drift risk on future PRs. Explicit follow-up material.
C3 Dockerfile build order diverges from root 🟡 unchanged Still core → parsers → …; root builds parsers → core → …. Works via source-conditional exports; divergence remains.
N1/N2 regex rigidity + readdirSync guard 🟡 unchanged Cosmetic; not addressed.

Delta trace

  • build:hyperframes-runtime:modular script definition in packages/core/package.json:12SANDBOX_RUNTIME_VARIANT=modular tsx scripts/build-hyperframes-runtime-artifact.ts. Distinct artifact from the default build:hyperframes-runtime invoked by core build. Confirmed by re-reading packages/core/package.json scripts.
  • The two build invocations write different artifact files under packages/core/dist/hyperframes-runtime/ (default + .modular.js variant), so no wasted work — both are required for downstream consumers.
  • Prettier formatting is a no-op on the runtime behavior of the coverage script.

Green surface

  • Modular runtime restoration is byte-safe (net additive step; nothing removed).
  • Prettier formatting reads clean.
  • No new failure modes introduced by this delta.
  • Verification claim ("Prior Docker/static verification remains valid; CI will rerun") is consistent with the shape of the delta.

Merge gate

Correct disposition of a subtle R1 oversight (modular runtime variant would have silently gone missing from the image otherwise). C1/C2/C3 still stand as pre-merge follow-ups worth Miguel's decision, but nothing regressed in this delta.

LGTM on the delta — leaving as COMMENTED.

Review by Rames D Jusso

@vanceingalls vanceingalls left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R2 verification at head 41e46f65656ceba90df6e0fb8eecf36a6c2dced3. Prior R1 CHANGES_REQUESTED at cdca11bce.

Delta since R1

Single-line addition at packages/gcp-cloud-run/Dockerfile:118:

&& bun run --cwd packages/core build:hyperframes-runtime:modular \

Chained after bun run --cwd packages/core build, before parsers/lint/sdk. Also: prettier formatting on check-dockerfile-workspaces.mjs (no semantic change).

R1 P1 blocker — resolved

Confirmed via packages/core/package.json at new SHA: build:hyperframes-runtime:modular = SANDBOX_RUNTIME_VARIANT=modular tsx scripts/build-hyperframes-runtime-artifact.ts — byte-parity with the pre-PR command. Composite build script invokes build:hyperframes-runtime (non-modular) + tsc + rewrites, so the new line is additive: both artifacts (default + .modular variant) land in the image. Modular runtime consumers at request time no longer silently regress. Order is safe — tsx + the artifact script are already resolvable after the full core build completes.

R1 P2 nits — status

ID Status
C1 hardcoded requiredSourcePackages list 🟡 unchanged, follow-up
C2 test:dockerfile-workspaces not wired into CI 🟡 unchanged, follow-up
C3 build-order divergence vs Dockerfile.test 🟡 unchanged, follow-up

Deferred per follow-up track; not blocking.

CI state at head

Format: SUCCESS ✓ (was FAILURE at R1). Preflight (lint + format): SUCCESS. Remainder of CI still in-progress but unrelated to this scope. mergeStateStatus=BLOCKED reflects reviewer + in-progress checks, not code health.

Peer state at new head

Rames posted COMMENTED LGTM on the delta — convergent read on additive/byte-parity nature; same C1/C2/C3 follow-up disposition.

Verdict

RIGHT + no residual blocker. Approving the delta.

— Via

@james-russo-rames-d-jusso james-russo-rames-d-jusso left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R3 delta review at HEAD 8bd3038bb. Delta vs R2 SHA 41e46f65:

Delta

Two files, all targeted at R1 concerns:

  1. package.json:27-28 — new check:gcp-cloud-run-dockerfile script (bun run --cwd packages/gcp-cloud-run test:dockerfile-workspaces), chained into root lint between check:workspace-contracts and oxlint. Every future bun run lint invocation — including .github/workflows/ci.yml:105 (bun run lint) — will fire the coverage test.
  2. packages/gcp-cloud-run/Dockerfile:117-124 — build-step reordering. New order: parsers → lint → studio-server → core → core:modular → sdk → sdk-playground → engine → producer → gcp-cloud-run. Matches root build's topo order (parsers,lint,studio-server → core → engine,producer,player,studio,shader-transitions,aws-lambda,gcp-cloud-run,sdk → cli → sdk-playground) for the packages relevant to the render path.

R1 concern verdict

ID Status Notes
C1 hardcoded requiredSourcePackages 🟡 unchanged Still 9 hardcoded entries. Not addressed; explicit follow-up material.
C2 coverage test not wired into CI 🟢 addressed check:gcp-cloud-run-dockerfile chained into root lint. .github/workflows/ci.yml:105 runs bun run lint, so the drift check now fires on every PR. Correct wiring shape — matches the existing check:tracked-artifacts / check:workspace-contracts pattern rather than inventing a new one.
C3 Dockerfile build order diverges from root 🟢 addressed Reordered to parsers → lint → studio-server → core → core:modular → sdk → sdk-playground → engine → producer → gcp-cloud-run. parsers/lint/studio-server now precede core, matching root build. The sdk/sdk-playground/engine insertion after core:modular differs from root (root builds them in the core,engine,…,sdk group after core), but only for packages whose exports also expose bun/import source conditionals — safe and consistent with the divergence's original justification.
N1 source-COPY regex rigidity 🟡 unchanged Cosmetic; not addressed.
N2 readdirSync guard style 🟡 unchanged Cosmetic; not addressed.

Delta trace

  • Root lint chaining: verified check:gcp-cloud-run-dockerfile runs after check:workspace-contracts and before oxlint .; standard && short-circuit means a Dockerfile drift fails the lint step immediately, before the (slower) oxlint sweep. Correct ordering — cheap check first.
  • CI wiring path: ci.yml's lint job runs bun run lint; that root script now includes check:gcp-cloud-run-dockerfile. Static verification of the wiring holds; the drift check will run on every push/PR that triggers CI's lint job.
  • Build-order correctness on the new sequence:
    • parsers build has no @hyperframes/* deps in its own source imports — safe first.
    • lint imports from @hyperframes/parsers (verified via packages/lint/src/* — same pattern as before) — parsers now precedes lint. ✓
    • studio-server imports from @hyperframes/parsers and @hyperframes/core. Root builds studio-server BEFORE core (root's topo order). Dockerfile also builds studio-server before core in the new order. Works because studio-server/package.json exports also expose bun/import source conditionals — same mechanism as before. ✓
    • core builds against source-resolved parsers/lint/studio-server; then core:modular variant emits the additional runtime artifact.
    • sdk / sdk-playground / engine build against a built core — correct.
  • No regressions on the other files — coverage script unchanged in this delta, so C1 remains as-was.

Green surface

  • Wiring shape is idiomatic: matches the existing check:* runners already chained into lint. No new CI job needed; existing infrastructure covers it.
  • Build order now maintainable — reads left-to-right in dependency order, easier to keep aligned with root.
  • Modular runtime artifact still emitted — the core:modular step preserved from R2 delta, correctly slotted right after core.
  • No new failure modes introduced by the reordering.

What I didn't verify

  • Whether check:gcp-cloud-run-dockerfile runs on every CI job matrix — spot-check confirms lint job runs bun run lint; other jobs (test, typecheck, etc.) don't need to run it since the check is idempotent and one CI job firing is sufficient to gate merges.
  • Whether the reordering has any measurable impact on Docker layer cache hit rate. Likely marginal; not a blocker.

Merge gate

Clean disposition of C2 and C3 with the exact wiring shape suggested (check:* in root lint) and root-aligned build order. C1 remains as an explicit follow-up worth Miguel's future attention — the hardcoded requiredSourcePackages is still a class-of-drift risk, but the R3 wiring at least means a manifest drift will now be caught automatically. Progress on the reporter's core insight.

LGTM on the delta — leaving as COMMENTED.

Review by Rames D Jusso

@miguel-heygen
miguel-heygen force-pushed the fix/2601-gcp-workspace-manifests branch from 8bd3038 to 66c0fa7 Compare July 17, 2026 03:58

@vanceingalls vanceingalls left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R3 delta review at HEAD 8bd3038bb. Delta vs R2 SHA 41e46f65.

Prior R2 APPROVED.

Delta (2 files, +6 / -5)

  1. package.json — new check:gcp-cloud-run-dockerfile script chained into root lint between check:workspace-contracts and oxlint. bun run lint (incl. CI's lint job) now fires the drift check.
  2. packages/gcp-cloud-run/Dockerfile — build-step reorder: parsers → lint → studio-server → core → core:modular → sdk → sdk-playground → engine → producer → gcp-cloud-run.

R2 P2 verdict

P2 Status
Build-order divergence from root build ✅ resolved. parsers/lint/studio-server now precede core, matching root's canonical topo order. Modular-runtime step preserved (core build:hyperframes-runtime:modular), slotted after core build — my R2 concern still intact.
Coverage-test wiring into CI ✅ resolved. check:gcp-cloud-run-dockerfile chained into root lint — same shape as sibling check:tracked-artifacts / check:workspace-contracts. No new CI job surface required; existing lint job covers it.
Hardcoded requiredSourcePackages list 🟡 unchanged — explicit follow-up. Manifest drift now auto-caught (from workspace enumeration); source-tree drift still needs a manual list bump. Progress, not full-resolution.

Adversarial

  • Reordering preserves render-path correctness: sdk / sdk-playground still built before engine (fine — neither depends on engine); studio-server before core continues to work via the existing exports.bun / exports.import source-conditional plumbing that the pre-R3 order relied on. No new failure mode introduced.
  • check:gcp-cloud-run-dockerfile in root lint fires on every PR (not gcp-cloud-run-scoped) — desirable, catches cross-scaffold drift (someone adds packages/foo without touching the Dockerfile). Cost is one readdirSync + regex over ~140-line Dockerfile; negligible.
  • Merge state DIRTY (base drift, not R3-introduced) — needs rebase before merge, not a review blocker.

Peer

Rames (COMMENTED, 03:56:19Z): same verdict shape — C2/C3 addressed, C1 follow-up, "LGTM on the delta."

Verdict

APPROVE. R3 tightens wiring + aligns to canonical build order; R2 approval intact.

— Via

@james-russo-rames-d-jusso james-russo-rames-d-jusso left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R4 rebase-only review at HEAD 66c0fa739. git patch-id --stable on the top commit matches R3's 8bd3038b — the PR-scoped diff is byte-content-identical. Main-side commits (e.g. 75eedf5c fix(cli): time out stalled model downloads (#2415)) are the delta.

Verification

  • Patch-id equivalence: R3 top-commit patch-id b27c63195d5eb0fa4a623d3c7f14e2dac7fce8b0 == R4 top-commit patch-id b27c63195d5eb0fa4a623d3c7f14e2dac7fce8b0.
  • PR-scope git diff 8bd3038b 66c0fa739 -- packages/gcp-cloud-run/ package.json is empty.
  • Commit reorganization noted: R3 was a single squashed commit; R4 is now two commits (fix: include all workspace build dependencies + test: enforce Dockerfile workspace coverage). Structural cleanliness, no content change.

R1 concern verdict (carried forward from R3)

ID Status
C1 hardcoded requiredSourcePackages 🟡 unchanged — explicit follow-up material
C2 coverage test not wired into CI 🟢 addressed (R3) — root lint invokes check:gcp-cloud-run-dockerfile
C3 Dockerfile build order diverges from root 🟢 addressed (R3) — reordered to parsers → lint → studio-server → core → …
N1 source-COPY regex rigidity 🟡 unchanged — cosmetic
N2 readdirSync guard style 🟡 unchanged — cosmetic

Merge gate

Rebase-only; no new content to review. Prior R3 verdict stands. LGTM — leaving as COMMENTED.

Review by Rames D Jusso

@miguel-heygen
miguel-heygen force-pushed the fix/2601-gcp-workspace-manifests branch from 356fba0 to 5a2df8e Compare July 17, 2026 04:11
@miguel-heygen
miguel-heygen force-pushed the fix/2601-gcp-workspace-manifests branch from 5a2df8e to 9ee94bb Compare July 17, 2026 04:27
# Conflicts:
#	packages/gcp-cloud-run/check-dockerfile-workspaces.mjs
@miguel-heygen
miguel-heygen merged commit a6df35f into main Jul 17, 2026
48 checks passed
@miguel-heygen
miguel-heygen deleted the fix/2601-gcp-workspace-manifests branch July 17, 2026 05:18
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.

GCP Cloud Run adapter: image build fails on a fresh clone at v0.7.60 — Dockerfile's workspace-manifest COPY list is missing five packages

4 participants