Skip to content

chore: migrate to utoo CI#5830

Merged
fengmk2 merged 26 commits intonextfrom
chore-ut-ci
Apr 14, 2026
Merged

chore: migrate to utoo CI#5830
fengmk2 merged 26 commits intonextfrom
chore-ut-ci

Conversation

@elrrrrrrr
Copy link
Copy Markdown
Contributor

@elrrrrrrr elrrrrrrr commented Mar 12, 2026

Summary

Migrate the main CI workflow from pnpm to utoo (ut). The E2E workflow keeps pnpm for now — it requires catalog: / workspace: protocol resolution and publishConfig overrides during pack which ut pm-pack does not yet provide.

Install speedup

The direct win of this migration: ut install --from pnpm is 2.2–3.6× faster than pnpm install across all test matrix platforms.

Platform pnpm install ut install Speedup
ubuntu-22 16.8s 5.2s 3.2×
ubuntu-24 17.7s 4.9s 3.6×
macos-22 26.3s 9.5s 2.8×
macos-24 30.1s 9.1s 3.3×
windows-22 31.1s 12.0s 2.6×
windows-24 28.4s 12.7s 2.2×

Every test matrix job re-installs from scratch, so this 15–20s savings per job compounds into the per-job reductions below.

Overall CI wall-clock

On a clean run (no reruns), the full workflow shaves ~1 minute off wall-clock (25m34s → 24m32s, ~4% faster). The critical path is still bounded by Windows Test (~20–24m), so faster jobs elsewhere can't meaningfully shrink wall-clock. Flaky reruns on the critical path can degrade practical times further.

The win of this PR is per-job speedup (especially macOS, where Test jobs drop 6–8 minutes each) and developer-machine ergonomics (ut install on your laptop is also 3× faster).

CI changes

  • .github/workflows/ci.yml: replace pnpm/action-setup + pnpm install with utooland/setup-utoo + ut install --from pnpm
  • package.json: convert pnpm-specific scripts to ut equivalents (ut run --workspaces, ut run --workspace <name>)
  • site:build / site:dev use cd site && npm run build/dev so Cloudflare Pages works (its env has neither pnpm nor utoo)
  • .gitignore: add .utoo.toml and .claude/
  • .oxfmtrc.json: ignore root package.json (ut rewrites it with npm-style workspaces field)

egg-bin fixes

CJS resolution (baseCommand.ts)

ts-node, tsconfig-paths are CJS packages without exports. On flat-hoisted layouts (npm/utoo), importResolve (which uses import.meta.resolve) fails because the ESM resolver doesn't auto-append .js for bare subpaths. Fix: use createRequire for these CJS packages.

Self-test fixture opt-out (test.ts + coffee.ts)

Under flat-hoisting, egg-bin's own test fixtures reach @eggjs/mock and @eggjs/tegg-vitest via monorepo root hoist even though the fixture projects don't use them. This caused every test fork to load both frameworks unnecessarily (~90s for mock, ~7s/fork for tegg runner → ~70s for the test-bin suite).

Solution: the test harness (coffee.ts) sets EGG_BIN_SELF_TEST_FIXTURE=1 when spawning egg-bin against its own fixtures. test.ts checks this env var and skips both mock and tegg-runner auto-detection.

For real projects, behaviour is unchanged: both frameworks are resolve-then-use. The tegg runner also falls back to egg-bin's own dirname for E2E scenarios (cnpmcore uses tegg transitively via egg without declaring it directly).

Build perf: publint pack

publint runs pnpm pack by default against each of ~80 packages. On main CI (utoo env, no pnpm binary) this fails. On E2E (pnpm env, symlinked node_modules) npm pack is ~10× slower per package — create-egg alone took 85s vs 1s under pnpm.

Fix: tsdown.config.ts reads PUBLINT_PACK env var, defaulting to npm (works in main CI). E2E workflow sets PUBLINT_PACK=pnpm so it stays fast there.

Dependency fixes

Change Why
oxlint-tsgolint: ^0.15.0^0.18.1 Peer requirement of oxlint 1.60.0
Add @types/content-type, @types/koa-compose to root devDeps oxlint type-check needs these at workspace root, not just hoisted from sub-packages

Other source adaptations

File What
packages/cluster/test/options.test.ts Accept flat-hoisted node_modules/egg path
packages/tsconfig/test/index.test.ts Use require.resolve instead of hardcoded path
tegg/plugin/controller, tegg/plugin/mcp-proxy Remove @ts-expect-error for types discoverable under flat hoisting

Per-job timing (clean run, no reruns)

Job next chore-ut-ci Delta
typecheck 2m7s 1m39s -28s
Test (ubuntu, 22) 14m52s 15m20s +28s
Test (ubuntu, 24) 13m38s 13m28s -10s
Test (macos, 22) 21m5s 14m40s -6m25s
Test (macos, 24) 18m54s 10m38s -8m16s
Test (windows, 22) 25m24s 24m23s -1m1s
Test (windows, 24) 23m7s 20m59s -2m8s
Test bin (ubuntu) 2m19s 2m2s -17s
Test bin (windows) 3m51s 2m56s -55s
Test scripts (ubuntu, 22) 1m41s 1m13s -28s
Test scripts (ubuntu, 24) 1m36s 1m16s -20s
cnpmcore E2E 6m0s 5m58s -2s
examples E2E 2m35s 2m25s -10s

Almost every job is faster; the small Test (ubuntu 22) +28s regression is within run-to-run variance.

Test plan

  • typecheck
  • Test matrix (ubuntu/macos/windows × Node 22/24)
  • Test bin, Test scripts
  • E2E (cnpmcore + examples)
  • Cloudflare Pages

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Chores
    • Migrated build and dependency management tooling from pnpm to utoo across the monorepo.
    • Updated CI workflows, workspace configurations, and npm scripts to support the new tooling.
    • Added build configuration for egg-bin TypeScript compilation.
    • Enhanced test infrastructure for environment isolation and compatibility.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c671cbbf-2448-4a7f-87eb-d965e387088a

📥 Commits

Reviewing files that changed from the base of the PR and between f9ef8d3 and 7083e54.

📒 Files selected for processing (1)
  • tools/egg-bin/src/commands/test.ts

📝 Walkthrough

Walkthrough

Migrates CI and workspace tooling from pnpm to utoo/ut, updates package scripts and workspace metadata, adjusts module resolution and build/test tooling in tools/egg-bin, and tightens tests and build configs to reflect new resolution/install behaviors.

Changes

Cohort / File(s) Summary
CI & Workspace Tooling
\.github/workflows/ci.yml, \.github/workflows/e2e-test.yml, pnpm-workspace.yaml, \.gitignore, \.oxfmtrc.json
Replaced pnpm setup with utooland/setup-utoo and ut install --from pnpm; set PUBLINT_PACK in e2e build; added utoo to catalog and onlyBuiltDependencies; ignore .utoo.toml and .claude/; added /package.json to oxfmtrc ignorePatterns.
Root & Tool Package Scripts
package.json, tools/scripts/package.json
Converted pnpm workspace/script invocations to ut run equivalents, adjusted site scripts to cd site && npm run ..., updated workspace invocation patterns and added utoo catalog/devDependency.
egg-bin build & config
tools/egg-bin/tsdown.config.ts, tools/egg-bin/package.json, tsdown.config.ts
Added tsdown entry glob and externals for @eggjs/* and egg; enabled devExports; introduced explicit build script for egg-bin; added publint.pack selectable via PUBLINT_PACK env.
Module resolution & test bootstrap
tools/egg-bin/src/baseCommand.ts, tools/egg-bin/src/commands/test.ts, tools/egg-bin/test/coffee.ts
Replaced importResolve with local cjsResolve using createRequire for CJS resolution, adjusted loader path logic, gated auto-setup/resolution when EGG_BIN_SELF_TEST_FIXTURE is set, and mark test forks with that env var.
Tests — resolution & paths
packages/cluster/test/options.test.ts, packages/tsconfig/test/index.test.ts, packages/utils/test/import.test.ts
Expanded expected framework path candidates (including hoisted node_modules), switched to createRequire(...).resolve for locating tsc, and broadened import-error message matching to accept package or module variants.

Sequence Diagram(s)

(Skipped — changes are not best represented by a new multi-component sequential diagram.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

typescript

Suggested reviewers

  • fengmk2
  • killagu
  • jerryliang64
  • gxkl

Poem

🐰 From pnpm burrows to utoo's bright glen,
I hop through scripts and resolve paths again.
With ut run I prance and tsdown trims the day,
Tests find their homes, and builds purr all the way. ✨

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'chore: migrate to utoo CI' accurately summarizes the primary change: migrating the CI workflow from pnpm to utoo tooling.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore-ut-ci

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.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the project's dependency and workspace management. It transitions from using pnpm-workspace.yaml to a combination of a new .utoo.toml file for dependency catalogs and direct configuration within package.json for workspaces and overrides. This change streamlines how dependencies are declared and managed across the monorepo, likely in preparation for or as part of a new CI setup.

Highlights

  • Configuration Migration: Migrated dependency catalog and workspace definitions from pnpm-workspace.yaml to .utoo.toml and package.json respectively.
  • New Configuration File: Introduced a new .utoo.toml file to centralize dependency version management.
  • Package.json Updates: Updated package.json to include workspace paths and define package overrides, specifically for vite.
  • Removed PNPM Workspace File: Removed the pnpm-workspace.yaml file as its configurations were moved to other files.
Changelog
  • .utoo.toml
    • Added a new file to define a comprehensive catalog of project dependencies and their versions.
  • package.json
    • Added a workspaces array to explicitly define the project's monorepo structure.
    • Introduced an overrides section to specify a custom version for the vite package.
    • Removed the packageManager field, indicating a shift in how the package manager is specified or managed.
  • pnpm-workspace.yaml
    • Removed the file, as its contents for workspace definition and dependency catalog have been migrated to package.json and .utoo.toml.
Ignored Files
  • Ignored by pattern: .github/workflows/** (2)
    • .github/workflows/ci.yml
    • .github/workflows/e2e-test.yml
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/e2e-test.yml Fixed
@socket-security
Copy link
Copy Markdown

socket-security Bot commented Mar 12, 2026

No dependency changes detected. Learn more about Socket for GitHub.

👍 No dependency changes detected in pull request

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the project's dependency and workspace management by migrating configuration from pnpm-workspace.yaml to a new .utoo.toml file and package.json. My review focuses on the maintainability of the new configuration and the potential impact on the developer workflow. I've suggested sorting the new dependency catalog for better readability and pointed out a potential issue with the removal of the packageManager enforcement that could be addressed with documentation.

Comment thread .utoo.toml Outdated
Comment thread package.json
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Mar 12, 2026

Deploying egg-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7083e54
Status: ✅  Deploy successful!
Preview URL: https://025445a0.egg-v3.pages.dev
Branch Preview URL: https://chore-ut-ci.egg-v3.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Mar 12, 2026

Deploying egg with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7083e54
Status: ✅  Deploy successful!
Preview URL: https://06e337f9.egg-cci.pages.dev
Branch Preview URL: https://chore-ut-ci.egg-cci.pages.dev

View logs

@elrrrrrrr elrrrrrrr changed the title chore(ci): utoo ci chore: migrate to utoo CI and fix circular dependencies Mar 16, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.49%. Comparing base (490f849) to head (7083e54).
⚠️ Report is 1 commits behind head on next.

Additional details and impacted files
@@            Coverage Diff             @@
##             next    #5830      +/-   ##
==========================================
- Coverage   86.00%   85.49%   -0.52%     
==========================================
  Files         667      660       -7     
  Lines       18945    18828     -117     
  Branches     3652     3646       -6     
==========================================
- Hits        16294    16097     -197     
- Misses       2297     2360      +63     
- Partials      354      371      +17     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/ci.yml Fixed
@elrrrrrrr elrrrrrrr closed this Mar 16, 2026
@elrrrrrrr elrrrrrrr reopened this Mar 16, 2026
@elrrrrrrr elrrrrrrr closed this Mar 27, 2026
@elrrrrrrr elrrrrrrr reopened this Mar 27, 2026
@elrrrrrrr elrrrrrrr changed the title chore: migrate to utoo CI and fix circular dependencies chore: migrate to utoo CI Apr 7, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 2026

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":500,"request":{"method":"PATCH","url":"https://api.github.com/repos/eggjs/egg/issues/comments/4047416827","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- This is an auto-generated comment: skip review by coderabbit.ai -->\n\n> [!IMPORTANT]\n> ## Review skipped\n> \n> Draft detected.\n> \n> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.\n> \n> <details>\n> <summary>⚙️ Run configuration</summary>\n> \n> **Configuration used**: defaults\n> \n> **Review profile**: CHILL\n> \n> **Plan**: Pro\n> \n> **Run ID**: `9004d336-f76f-4e60-a323-eebffb3a4d8e`\n> \n> </details>\n> \n> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.\n> \n> Use the checkbox below for a quick retry:\n> - [ ] <!-- {\"checkboxId\": \"e9bb8d72-00e8-4f67-9cb2-caf3b22574fe\"} --> 🔍 Trigger review\n\n<!-- end of auto-generated comment: skip review by coderabbit.ai -->\n\n\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n<details>\n<summary>🧪 Generate unit tests (beta)</summary>\n\n- [ ] <!-- {\"checkboxId\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Create PR with unit tests\n- [ ] <!-- {\"checkboxId\": \"6ba7b810-9dad-11d1-80b4-00c04fd430c8\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Commit unit tests in branch `chore-ut-ci`\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n\n<!-- tips_start -->\n\n---\n\nThanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=eggjs/egg&utm_content=5830)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.\n\n<details>\n<summary>❤️ Share</summary>\n\n- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)\n- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)\n- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)\n- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)\n\n</details>\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->"},"request":{"retryCount":3,"signal":{},"retries":3,"retryAfter":16}}}

- Migrate all CI workflows from pnpm to utoo (ut install --from pnpm)
- Add scope-limited require.resolve fallback in importResolve: when
  import.meta.resolve fails for CJS subpaths, fall back to require.resolve
  but reject results outside the caller's paths scope to prevent
  workspace-root hoisted packages from being loaded unexpectedly
- Add V8 snapshot module loader API (setSnapshotModuleLoader)
- Add manifest command to egg-bin for startup manifest management
- Refactor buildRequiresExecArgv to base command for reuse
- Pin egg-bin tsdown build to local config (avoids root workspace scan)
- Bump cnpmcore E2E hash to v4.32.1 (EdgedriverBinary fix)
- Add verify-manifest E2E script
- Various package version bumps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread ecosystem-ci/scripts/verify-manifest.mjs Fixed
Comment thread ecosystem-ci/scripts/verify-manifest.mjs Fixed
elrrrrrrr and others added 3 commits April 13, 2026 11:51
# Conflicts:
#	.github/workflows/ci.yml
#	.gitignore
#	packages/core/src/lifecycle.ts
#	packages/core/test/snapshot.test.ts
#	packages/egg/src/lib/egg.ts
#	packages/egg/src/lib/start.ts
#	packages/egg/test/__snapshots__/index.test.ts.snap
The previous startsWith path check failed with pnpm because
require.resolve follows symlinks and returns .pnpm real paths that
don't match the logical paths. Instead, check if the package exists
in paths[i]/node_modules/ which works with symlinks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
node_modules layout varies across package managers (pnpm symlinks,
utoo hoisting). Fall back to checking if the package is declared in
package.json dependencies/devDependencies/peerDependencies of any
provided path entry.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
elrrrrrrr and others added 3 commits April 13, 2026 23:25
CI runs in utoo environment where pnpm is not available.
Cloudflare Pages build is configured separately and uses pnpm directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Avoids dependency on pnpm or utoo in Cloudflare Pages build environment.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@elrrrrrrr elrrrrrrr marked this pull request as ready for review April 13, 2026 17:15
@elrrrrrrr elrrrrrrr added the chore: gitAction Actions of GitHub such as CI...ect label Apr 13, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Migrates the monorepo’s primary GitHub Actions CI workflow and root scripts from pnpm-centric commands to utoo (ut), while adapting tooling/tests to work under flat/hoisted node_modules layouts.

Changes:

  • Update CI workflow to use utooland/setup-utoo and ut install --from pnpm, and switch CI commands to ut run ….
  • Convert root/workspace scripts from pnpm recursion/filtering to ut run --workspaces/--workspace.
  • Adjust egg-bin resolution and test bootstrapping for flat-hoisted installs (CJS resolution via createRequire, and mock autoload guard via package.json deps).

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
.github/workflows/ci.yml Switch CI jobs from pnpm setup/install to utoo setup + ut commands.
package.json Replace pnpm-recursive scripts with ut equivalents; adjust site scripts for Cloudflare Pages.
pnpm-workspace.yaml Add utoo to catalog and mark it as onlyBuiltDependencies.
tsdown.config.ts Configure publint packing mode for environments without pnpm.
tools/egg-bin/src/baseCommand.ts Use createRequire().resolve for CJS-only subpath resolution under ESM/flat-hoist.
tools/egg-bin/src/commands/test.ts Guard mock setup loading by checking declared deps in package.json.
tools/egg-bin/tsdown.config.ts Adjust egg-bin build config (entry/external/exports).
tools/egg-bin/package.json Update scripts (add explicit build, remove pretest).
tools/scripts/package.json Update coverage/CI scripts to use ut runner.
packages/utils/test/import.test.ts Loosen error message matching for module resolution differences.
packages/tsconfig/test/index.test.ts Use createRequire + require.resolve for TypeScript bin resolution.
packages/cluster/test/options.test.ts Accept additional flat-hoisted node_modules/egg framework path.
.oxfmtrc.json Ignore root package.json to avoid formatting churn from utoo rewrites.
.gitignore Ignore utoo/Claude-related local files.

Comment thread package.json
Comment thread tools/egg-bin/package.json
Copy link
Copy Markdown
Contributor

@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: 3

🧹 Nitpick comments (3)
tsdown.config.ts (1)

3-33: Use a typed intermediate config object before defineConfig(...).

Please align this file with the repo config-typing rule (e.g., assign the config to a typed variable, then export it through defineConfig).

As per coding guidelines {tsdown.config.ts,vitest.config.ts}: Use typed intermediate variables with appropriate types (UserConfig, UserWorkspaceConfig) for tsdown.config.ts and vitest.config.ts configuration files.

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

In `@tsdown.config.ts` around lines 3 - 33, Create a typed intermediate config
object and pass it to defineConfig instead of inlining the object; e.g., import
the appropriate config types (UserConfig and UserWorkspaceConfig) from the
tsdown typing, declare a const config: UserConfig = { workspace: { /* ... */ } ,
unused: { /* ... */ }, exports: { /* ... */ }, fixedExtension: false, publint: {
/* ... */ }, entry: 'src/**/*.ts', unbundle: true, external: [/^@eggjs\//,
'egg'] } (use UserWorkspaceConfig for the workspace property if applicable) and
then export default defineConfig(config). Ensure the variable name (config)
replaces the inline object passed to defineConfig and the types match the repo
rule.
tools/egg-bin/tsdown.config.ts (1)

3-10: Please switch to a typed intermediate tsdown config variable.

This keeps the file aligned with monorepo config typing conventions and improves maintainability.

As per coding guidelines {tsdown.config.ts,vitest.config.ts}: Use typed intermediate variables with appropriate types (UserConfig, UserWorkspaceConfig) for tsdown.config.ts and vitest.config.ts configuration files.

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

In `@tools/egg-bin/tsdown.config.ts` around lines 3 - 10, Create a typed
intermediate config variable instead of inlining the object: import the
appropriate type (UserConfig) and declare const tsdownConfig: UserConfig = {
entry, unbundle, fixedExtension, external, exports: { devExports: true }, ... }
using the existing keys, then pass that variable into defineConfig and export it
(export default defineConfig(tsdownConfig)); keep the same properties (entry,
unbundle, fixedExtension, external, exports/devExports) and ensure you import
the UserConfig type and defineConfig symbol from tsdown so the file follows the
monorepo typed-config convention.
tools/egg-bin/src/commands/test.ts (1)

306-307: Type the package.json dependency shape instead of using any.

The helper only reads dependency maps, so Record<string, any> is wider than necessary and drops type safety on the new branch.

Typed helper shape
+interface PackageJsonDependencyFields {
+  readonly dependencies?: Readonly<Record<string, string>>;
+  readonly devDependencies?: Readonly<Record<string, string>>;
+  readonly peerDependencies?: Readonly<Record<string, string>>;
+}
+
-function hasDependency(pkg: Record<string, any>, name: string): boolean {
+function hasDependency(pkg: PackageJsonDependencyFields, name: string): boolean {
   return !!(pkg.dependencies?.[name] || pkg.devDependencies?.[name] || pkg.peerDependencies?.[name]);
 }
As per coding guidelines, "Avoid 'any' type in TypeScript; use 'unknown' when type is truly unknown'."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/egg-bin/src/commands/test.ts` around lines 306 - 307, The parameter
type for hasDependency is too broad (Record<string, any>); define a narrow
interface (e.g., PackageDeps or PackageJsonDeps) that types the three dependency
maps as optional Record<string, string> (dependencies?, devDependencies?,
peerDependencies?) and change the function signature to use that type for pkg;
add the new type near hasDependency so callers remain type-safe and avoid using
any/unknown.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 209-213: The workspace selector is being passed after the `--` to
the underlying script (e.g., "ut run build -- --workspace ./tools/egg-bin"), so
move the `--workspace` flag so it's consumed by `ut run` itself; update
occurrences like the `ut run build` invocation to use "ut run build --workspace
./tools/egg-bin -- ..." (i.e., place `--workspace` before any `--` separator)
and make the same change for the other affected `ut run` lines (the similar
block around the other occurrence).

In `@package.json`:
- Line 34: Update the package.json script "example:test:all" to use double
quotes for the workspace glob instead of single quotes; change the command
string in the "example:test:all" script so the workspace argument is quoted with
"helloworld-*" (double quotes) to ensure the glob is interpreted correctly on
Windows cmd.exe and cross-platform shells.

In `@tools/egg-bin/src/baseCommand.ts`:
- Around line 217-225: The catch in cjsResolve currently swallows all errors
from createRequire.resolve; change it to only ignore MODULE_NOT_FOUND resolution
errors and rethrow any other exceptions so misconfigurations bubble up. In the
cjsResolve function around createRequire(...).resolve(specifier) inspect the
caught error (e.g., err.code === 'MODULE_NOT_FOUND' or similar) and continue the
loop only for that case, otherwise throw the error; this preserves the fallback
behavior while surfacing broken installs/configuration issues in functions like
cjsResolve and callers that rely on its resolution.

---

Nitpick comments:
In `@tools/egg-bin/src/commands/test.ts`:
- Around line 306-307: The parameter type for hasDependency is too broad
(Record<string, any>); define a narrow interface (e.g., PackageDeps or
PackageJsonDeps) that types the three dependency maps as optional Record<string,
string> (dependencies?, devDependencies?, peerDependencies?) and change the
function signature to use that type for pkg; add the new type near hasDependency
so callers remain type-safe and avoid using any/unknown.

In `@tools/egg-bin/tsdown.config.ts`:
- Around line 3-10: Create a typed intermediate config variable instead of
inlining the object: import the appropriate type (UserConfig) and declare const
tsdownConfig: UserConfig = { entry, unbundle, fixedExtension, external, exports:
{ devExports: true }, ... } using the existing keys, then pass that variable
into defineConfig and export it (export default defineConfig(tsdownConfig));
keep the same properties (entry, unbundle, fixedExtension, external,
exports/devExports) and ensure you import the UserConfig type and defineConfig
symbol from tsdown so the file follows the monorepo typed-config convention.

In `@tsdown.config.ts`:
- Around line 3-33: Create a typed intermediate config object and pass it to
defineConfig instead of inlining the object; e.g., import the appropriate config
types (UserConfig and UserWorkspaceConfig) from the tsdown typing, declare a
const config: UserConfig = { workspace: { /* ... */ } , unused: { /* ... */ },
exports: { /* ... */ }, fixedExtension: false, publint: { /* ... */ }, entry:
'src/**/*.ts', unbundle: true, external: [/^@eggjs\//, 'egg'] } (use
UserWorkspaceConfig for the workspace property if applicable) and then export
default defineConfig(config). Ensure the variable name (config) replaces the
inline object passed to defineConfig and the types match the repo rule.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d12b595f-8a7c-44f1-a16c-8878be92ab2b

📥 Commits

Reviewing files that changed from the base of the PR and between 490f849 and 206e03b.

📒 Files selected for processing (14)
  • .github/workflows/ci.yml
  • .gitignore
  • .oxfmtrc.json
  • package.json
  • packages/cluster/test/options.test.ts
  • packages/tsconfig/test/index.test.ts
  • packages/utils/test/import.test.ts
  • pnpm-workspace.yaml
  • tools/egg-bin/package.json
  • tools/egg-bin/src/baseCommand.ts
  • tools/egg-bin/src/commands/test.ts
  • tools/egg-bin/tsdown.config.ts
  • tools/scripts/package.json
  • tsdown.config.ts

Comment thread .github/workflows/ci.yml
Comment thread package.json
Comment thread tools/egg-bin/src/baseCommand.ts
@elrrrrrrr elrrrrrrr marked this pull request as draft April 14, 2026 02:45
elrrrrrrr and others added 3 commits April 14, 2026 10:59
Under flat-hoisting (utoo/npm), every test fork loaded the tegg runner
even for fixtures that don't use tegg, costing ~7s per fork (~70s for
test-bin suite). The runner was reached via monorepo root hoist rather
than a legitimate dependency.

Solution: the test harness (coffee.ts) now sets EGG_BIN_SELF_TEST_FIXTURE=1
when spawning egg-bin against its own fixtures. test.ts checks this env
var and skips runner auto-detection, avoiding the false-positive load.

This keeps the resolve-then-use approach for real projects (including the
E2E cnpmcore case where tegg is transitive via egg).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pinning pack to 'npm' was intended to make main CI portable (utoo env has
no pnpm binary), but it forces E2E (pnpm env) to also use npm pack, which
takes ~90s per package against pnpm's symlinked node_modules (vs ~2s with
pnpm pack). Total E2E build impact was +110s.

With auto-detect:
- E2E: pnpm-lock.yaml present → pnpm pack (fast, ~13s total)
- Main CI: no lockfile → falls back to npm pack (still fast here since
  utoo's flat node_modules doesn't have the symlink traversal overhead)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-detect picked pnpm pack based on pnpm-workspace.yaml presence, but
main CI (utoo env) has no pnpm binary and fails. Pinning to npm works in
main CI but causes 10x slowdown in E2E against pnpm's symlinked
node_modules.

Use env-controlled pack: default 'npm' (keeps main CI portable), E2E
workflow sets PUBLINT_PACK=pnpm (restores fast pnpm pack).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@elrrrrrrr elrrrrrrr marked this pull request as ready for review April 14, 2026 06:14
Copilot AI review requested due to automatic review settings April 14, 2026 06:14
Comment thread tools/egg-bin/src/commands/test.ts Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated 3 comments.

Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/ci.yml
Comment thread package.json
@elrrrrrrr elrrrrrrr marked this pull request as draft April 14, 2026 06:18
Drop hasDependency(projectPkg, '@eggjs/mock') in favour of the same
EGG_BIN_SELF_TEST_FIXTURE env var that already guards tegg-runner.
Two mechanisms doing similar jobs was inconsistent and redundant — the
env var is set precisely when we want to opt out (self-test fixtures).

For real projects in flat-hoisted monorepos that reach @eggjs/mock via
hoist without declaring it, the auto-load still runs. That's acceptable
because it was never the target of the guard in the first place; the
original motivation was egg-bin's own fixtures, which now use the env.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@elrrrrrrr elrrrrrrr marked this pull request as ready for review April 14, 2026 07:40
Copilot AI review requested due to automatic review settings April 14, 2026 07:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated no new comments.

@fengmk2 fengmk2 merged commit a8a7572 into next Apr 14, 2026
28 of 30 checks passed
@fengmk2 fengmk2 deleted the chore-ut-ci branch April 14, 2026 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore: gitAction Actions of GitHub such as CI...ect

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants