Skip to content

fix(cli): build release-runtime before packaging#127

Open
quanru wants to merge 3 commits intohappier-dev:devfrom
quanru:fix/cli-release-runtime-build
Open

fix(cli): build release-runtime before packaging#127
quanru wants to merge 3 commits intohappier-dev:devfrom
quanru:fix/cli-release-runtime-build

Conversation

@quanru
Copy link

@quanru quanru commented Mar 12, 2026

Summary

  • include release-runtime in the shared workspace build list used by apps/cli
  • verify build output for every bundled workspace package before packaging
  • add a low-dependency contract test that guards the default bundled package sync list

Why

@happier-dev/cli imports @happier-dev/release-runtime at runtime and declares it as a bundled dependency, but apps/cli/scripts/buildSharedDeps.mjs only built agents, cli-common, and protocol.

That made CLI packaging depend on pre-existing local packages/release-runtime/dist state. In practice this can make npm release artifacts nondeterministic and matches the ERR_MODULE_NOT_FOUND failure reported in #103.

Testing

  • node --test apps/cli/scripts/buildSharedDeps.contract.test.mjs
  • node --test apps/cli/scripts/prepack-script.test.mjs

Refs #103

Summary by CodeRabbit

  • Tests

    • Added contract tests validating CLI build outputs: bundled package list, per-package entry resolution, and correct distribution (copy/write) of runtime artifacts.
  • Chores

    • Consolidated bundled-deps configuration into a central manifest and updated CLI build/bundle scripts to iterate that list, with per-package build-entry resolution and per-package verification/messaging.

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: eecc2cea-36e1-4172-9a19-5c741b0168ca

📥 Commits

Reviewing files that changed from the base of the PR and between b6fa3ca and 02a5332.

📒 Files selected for processing (4)
  • apps/cli/scripts/buildSharedDeps.contract.test.mjs
  • apps/cli/scripts/buildSharedDeps.mjs
  • apps/cli/scripts/bundleWorkspaceDeps.mjs
  • apps/cli/scripts/workspaceBundleManifest.mjs

Walkthrough

Adds a workspace bundle manifest and refactors CLI build scripts to use it; introduces resolveBundledWorkspaceBuildEntry and reworks buildSharedDeps to iterate bundled packages; adds a contract test validating bundle metadata, entry resolution, and dist sync behavior with filesystem mocks.

Changes

Cohort / File(s) Summary
New Test
apps/cli/scripts/buildSharedDeps.contract.test.mjs
Adds contract tests that assert bundledWorkspacePackages, validate bundle manifest entries, verify resolveBundledWorkspaceBuildEntry main-resolution behavior, and assert syncBundledWorkspaceDist copy/write actions using mocked FS (existsSync, readFileSync, cpSync, writeFileSync).
Bundle Manifest
apps/cli/scripts/workspaceBundleManifest.mjs
New module exporting bundledWorkspacePackages (['agents','cli-common','protocol','release-runtime']) and createBundledWorkspaceBundles({repoRoot,targetRoot}) which emits bundle descriptors (packageName, srcDir, destDir).
Build CLI refactor
apps/cli/scripts/buildSharedDeps.mjs
Replaced hard-coded package lists with re-exported bundledWorkspacePackages; added resolveBundledWorkspaceBuildEntry(pkg, opts = {}); updated main(), tsconfig compile loop, build output verification, and syncBundledWorkspaceDist to iterate over bundled packages and produce per-package error messages. Exports updated to include bundledWorkspacePackages and resolveBundledWorkspaceBuildEntry.
Bundle consumer update
apps/cli/scripts/bundleWorkspaceDeps.mjs
Replaced static bundles with createBundledWorkspaceBundles({ repoRoot, targetRoot: happyCliDir }) import and invocation; subsequent vendor dependency handling now iterates generated bundles.
Manifest metadata
package.json
Minor manifest edits referenced by diff (contextual change summarized in PR).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: including release-runtime in the shared workspace build. This addresses the core issue of building missing dependencies before packaging.
Description check ✅ Passed The description covers required sections (Summary, Why, Testing) with clear context on what changed and why, including issue reference and test commands.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 12, 2026

Greptile Summary

This PR fixes a real packaging regression: @happier-dev/release-runtime was a bundled dependency of the CLI but was never built by buildSharedDeps.mjs, making the npm artifact depend on pre-existing local dist state and causing intermittent ERR_MODULE_NOT_FOUND errors (refs #103). The fix exports a single bundledWorkspacePackages constant, adds release-runtime to it, and updates both syncBundledWorkspaceDist and main() to iterate over the shared list. A contract test guards the list's contents and the sync behavior.

  • buildSharedDeps.mjs: release-runtime added to the exported bundledWorkspacePackages constant; syncBundledWorkspaceDist default packages and the main() build/verify loops now derive from this single source of truth.
  • main() verification: The post-build check is generalized from a protocol-only check to all packages; confirmed safe since all four packages define "main": "./dist/index.js".
  • Contract test: Covers both the list value and the syncBundledWorkspaceDist copy+package.json-write behavior for release-runtime; the deepEqual assertion on copyCalls also implicitly ensures the other packages are not spuriously synced.

Confidence Score: 4/5

  • Safe to merge — the fix is minimal, targeted, and all current packages satisfy the new dist/index.js convention.
  • The change correctly identifies and fixes the missing release-runtime build step. All four bundled packages have been confirmed to produce dist/index.js, so the generalized verification loop introduces no regressions. The contract test provides a good regression guard. The only concern is the implicit dist/index.js assumption, which is a maintainability nit rather than a defect.
  • No files require special attention.

Important Files Changed

Filename Overview
apps/cli/scripts/buildSharedDeps.mjs Core fix: exports bundledWorkspacePackages constant that now includes release-runtime, updates syncBundledWorkspaceDist default and main() build+verify loops to use it. All four packages confirmed to produce dist/index.js, so the new hardcoded verification path works today — but the assumption is implicit and undocumented.
apps/cli/scripts/buildSharedDeps.contract.test.mjs New contract test that guards the bundledWorkspacePackages list value and verifies syncBundledWorkspaceDist correctly copies and writes package.json for release-runtime when its destination directories exist. Test logic is sound: existsSync mock returns true only for release-runtime paths, so deepEqual on copyCalls implicitly asserts no other packages are incorrectly synced.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[main called] --> B[Build loop: for each pkg in bundledWorkspacePackages]
    B --> C1[runTsc agents/tsconfig.json]
    C1 --> C2[runTsc cli-common/tsconfig.json]
    C2 --> C3[runTsc protocol/tsconfig.json]
    C3 --> C4[runTsc release-runtime/tsconfig.json]
    C4 --> D[Verify loop: for each pkg in bundledWorkspacePackages]
    D --> E1{packages/agents/dist/index.js exists?}
    E1 -- No --> ERR[throw Error]
    E1 -- Yes --> E2{packages/cli-common/dist/index.js exists?}
    E2 -- No --> ERR
    E2 -- Yes --> E3{packages/protocol/dist/index.js exists?}
    E3 -- No --> ERR
    E3 -- Yes --> E4{packages/release-runtime/dist/index.js exists?}
    E4 -- No --> ERR
    E4 -- Yes --> F[syncBundledWorkspaceDist]
    F --> G[For each pkg: if dest dist exists, cpSync src→dest]
    G --> H[For each pkg: if dest package.json exists, sanitize & write]
    H --> I[Done]
Loading

Last reviewed commit: b6fa3ca

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/cli/scripts/buildSharedDeps.mjs (1)

8-8: Unify this package list with bundleWorkspaceDeps.mjs.

bundledWorkspacePackages is now the build-time source of truth, but apps/cli/scripts/bundleWorkspaceDeps.mjs:15-37 still keeps a separate hard-coded bundle manifest. A future bundled package addition can update one script and miss the other, which recreates the same packaging drift this PR is fixing. Consider extracting a shared manifest and deriving both build and bundle behavior from it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/cli/scripts/buildSharedDeps.mjs` at line 8, The hard-coded package list
in bundledWorkspacePackages is diverging from the list in
bundleWorkspaceDeps.mjs; consolidate by extracting a single shared manifest
(e.g., export a constant like bundledWorkspacePackages or
workspaceBundleManifest) and have both apps/cli/scripts/buildSharedDeps.mjs and
apps/cli/scripts/bundleWorkspaceDeps.mjs import/require that shared manifest so
both derive their behavior from the same source; update references in both
scripts to use the shared symbol (bundledWorkspacePackages or new
workspaceBundleManifest) and remove the duplicate hard-coded array in
bundleWorkspaceDeps.mjs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/cli/scripts/buildSharedDeps.contract.test.mjs`:
- Around line 15-20: The test currently hard-codes POSIX paths in the fake
existsSync check (using repoRoot and existsSync) which breaks on Windows; update
the expectations to be platform-neutral by constructing/normalizing the expected
paths with node's path utilities (e.g., use path.resolve or path.join and/or
path.normalize) instead of string literals, and apply the same change to both
occurrences (the existsSync arrays around repoRoot and the other block at lines
36–46) so the candidate comparison uses normalized paths on both sides.

---

Nitpick comments:
In `@apps/cli/scripts/buildSharedDeps.mjs`:
- Line 8: The hard-coded package list in bundledWorkspacePackages is diverging
from the list in bundleWorkspaceDeps.mjs; consolidate by extracting a single
shared manifest (e.g., export a constant like bundledWorkspacePackages or
workspaceBundleManifest) and have both apps/cli/scripts/buildSharedDeps.mjs and
apps/cli/scripts/bundleWorkspaceDeps.mjs import/require that shared manifest so
both derive their behavior from the same source; update references in both
scripts to use the shared symbol (bundledWorkspacePackages or new
workspaceBundleManifest) and remove the duplicate hard-coded array in
bundleWorkspaceDeps.mjs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1e48c178-9f0c-4af6-9fab-b6ea06a3deea

📥 Commits

Reviewing files that changed from the base of the PR and between cd992ae and b6fa3ca.

📒 Files selected for processing (2)
  • apps/cli/scripts/buildSharedDeps.contract.test.mjs
  • apps/cli/scripts/buildSharedDeps.mjs

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