From ab76d577991b7a50c38e0202d64be40014f3462f Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 19:33:34 +0800 Subject: [PATCH 01/15] chore(repo): switch package manager references from pnpm to utoo Replace `pnpm` with `utoo` across docs, top-level scripts, and CI workflows. Lockfile / workspace filenames (`pnpm-lock.yaml`, `pnpm-workspace.yaml`) and the `ut install --from pnpm` flag value are preserved because they refer to real artifacts on disk and to a CLI argument, not to a tool invocation. - AGENTS.md, README.md/README.zh-CN.md, packages/egg/README.md, tools/create-egg/README.md, plugins/redis/README.md, wiki/concepts/repository-map.md, tegg/CLAUDE.md, .github/copilot-instructions.md: rewrite command snippets and prose. - package.json: bump `packageManager` to `utoo@1.0.28`. - scripts/{publish,version,utils}.js: invoke `utoo` instead of `pnpm` and update comments. - .github/workflows/release.yml, .github/workflows/e2e-test.yml: swap pnpm/action-setup for utooland/setup-utoo and call `ut` / `utoo`. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/copilot-instructions.md | 64 ++++++++++++++++----------------- .github/workflows/e2e-test.yml | 18 +++++----- .github/workflows/release.yml | 8 ++--- AGENTS.md | 16 ++++----- README.md | 22 ++++++------ README.zh-CN.md | 6 ++-- package.json | 2 +- packages/egg/README.md | 6 ++-- plugins/redis/README.md | 2 +- scripts/publish.js | 6 ++-- scripts/utils.js | 2 +- scripts/version.js | 2 +- tegg/CLAUDE.md | 48 ++++++++++++------------- tools/create-egg/README.md | 8 ++--- wiki/concepts/repository-map.md | 2 +- 15 files changed, 106 insertions(+), 106 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 2c22dc367c..efd35f0ce4 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -6,12 +6,12 @@ Eggjs is a progressive Node.js framework for building enterprise-class server-side applications. Built on top of Koa.js, it provides a plugin system, conventions over configuration, and enterprise-grade features like clustering, logging, and security. -This is a **pnpm monorepo** with multiple packages using pnpm workspaces and catalog mode for centralized dependency management. +This is a **utoo monorepo** with multiple packages using utoo workspaces and catalog mode for centralized dependency management. ## Prerequisites and Environment Setup - **Node.js >= 20.19.0 required** - This is a hard requirement -- Enable pnpm first: `corepack enable pnpm` (installs pnpm v10.16.0) +- Enable utoo first: `corepack enable utoo` (installs utoo v10.16.0) - **NEVER CANCEL** any build or test commands - they can take several minutes to complete ## Bootstrap and Build Process @@ -19,17 +19,17 @@ This is a **pnpm monorepo** with multiple packages using pnpm workspaces and cat **Always run these commands in sequence after fresh clone:** ```bash -# 1. Enable pnpm (required first) -corepack enable pnpm +# 1. Enable utoo (required first) +corepack enable utoo # 2. Install all dependencies - takes ~63 seconds. NEVER CANCEL. Set timeout to 120+ seconds. -pnpm install +utoo install # 3. Build all packages - takes ~14 seconds. NEVER CANCEL. Set timeout to 60+ seconds. -pnpm run build +utoo run build # 4. Run linting (optional but recommended) - takes ~2 seconds -pnpm run lint +utoo run lint ``` ## Monorepo Structure @@ -54,45 +54,45 @@ pnpm run lint ### Build Commands -- `pnpm run build` - **Build all packages (~14 seconds). NEVER CANCEL. Set timeout to 60+ seconds.** -- `pnpm run clean` - Clean all dist directories +- `utoo run build` - **Build all packages (~14 seconds). NEVER CANCEL. Set timeout to 60+ seconds.** +- `utoo run clean` - Clean all dist directories ### Testing Commands -- `pnpm run test` - **Run all tests (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** -- `pnpm run test:cov` - **Run tests with coverage (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** -- `pnpm run ci` - **Run test coverage + build (~2.1 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** +- `utoo run test` - **Run all tests (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** +- `utoo run test:cov` - **Run tests with coverage (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** +- `utoo run ci` - **Run test coverage + build (~2.1 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** ### Linting Commands -- `pnpm run lint` - Run oxlint across all packages (~2 seconds) +- `utoo run lint` - Run oxlint across all packages (~2 seconds) ### Documentation Commands -- `pnpm run site:dev` - Start documentation dev server at http://localhost:8000 -- `cd site && pnpm run build:skip` - **Build documentation site (~24 seconds). NEVER CANCEL. Set timeout to 60+ seconds.** +- `utoo run site:dev` - Start documentation dev server at http://localhost:8000 +- `cd site && utoo run build:skip` - **Build documentation site (~24 seconds). NEVER CANCEL. Set timeout to 60+ seconds.** ### Example Applications (Currently Not Working) -- `pnpm run example:commonjs` - Start CommonJS example (has runtime issues) -- `pnpm run example:typescript` - Start TypeScript example (has runtime issues) +- `utoo run example:commonjs` - Start CommonJS example (has runtime issues) +- `utoo run example:typescript` - Start TypeScript example (has runtime issues) ## Package-Specific Commands -Run commands for specific packages using `pnpm --filter=`: +Run commands for specific packages using `utoo --filter=`: ```bash # Examples -pnpm --filter=egg run test -pnpm --filter=@eggjs/core run build -pnpm --filter=site run dev +utoo --filter=egg run test +utoo --filter=@eggjs/core run build +utoo --filter=site run dev ``` ## Development Workflow ### 1. Making Changes -- Always build packages first: `pnpm run build` +- Always build packages first: `utoo run build` - Work primarily in `packages/egg/src/` for core framework features - Use TypeScript throughout - all packages are TypeScript-based - Follow the existing directory conventions in `packages/egg/src/`: @@ -108,16 +108,16 @@ pnpm --filter=site run dev ```bash # 1. Build all packages (required) -pnpm run build +utoo run build # 2. Run linting -pnpm run lint +utoo run lint # 3. Run tests (some failures are expected in fresh environment) -pnpm run test +utoo run test # 4. Test documentation site -pnpm run site:dev +utoo run site:dev ``` ### 3. Testing Strategy @@ -162,7 +162,7 @@ pnpm run site:dev - **All sub-project tsconfig.json files MUST extend from root:** `"extends": "../../tsconfig.json"` - Root tsconfig.json includes all packages in `references` array -## pnpm Workspace & Catalog Dependencies +## utoo Workspace & Catalog Dependencies - Dependencies defined in `pnpm-workspace.yaml` catalog section - Reference catalog entries: `"package-name": "catalog:"` @@ -179,7 +179,7 @@ pnpm run site:dev ### Build Issues -- Always run `pnpm run build` after making changes +- Always run `utoo run build` after making changes - TypeScript compilation errors will show clearly - Build warnings are generally acceptable @@ -217,10 +217,10 @@ pnpm run site:dev After making changes, always verify: -1. **Build Success**: `pnpm run build` completes without errors -2. **Linting Passes**: `pnpm run lint` shows no new errors -3. **Documentation Loads**: `pnpm run site:dev` starts successfully and site loads at http://localhost:8000 -4. **Tests Run**: `pnpm run test` executes (some failures expected, focus on your changes) +1. **Build Success**: `utoo run build` completes without errors +2. **Linting Passes**: `utoo run lint` shows no new errors +3. **Documentation Loads**: `utoo run site:dev` starts successfully and site loads at http://localhost:8000 +4. **Tests Run**: `utoo run test` executes (some failures expected, focus on your changes) **Remember**: This is a complex enterprise framework. Always build first, validate incrementally, and focus on the core packages (`egg`, `core`, `utils`) for most development work. diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 3ab3c54181..94b57110fb 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -141,8 +141,8 @@ jobs: with: ecosystem-ci-project: ${{ matrix.project.name }} - - name: Install pnpm - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + - name: Install utoo + uses: utooland/setup-utoo@3a51006d0b66afcc32d1b9177a4b200b74f4a8cb # main - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 @@ -150,19 +150,19 @@ jobs: node-version: ${{ matrix.project.node-version }} - name: Install dependencies - run: pnpm install --no-frozen-lockfile + run: ut install --from pnpm - name: Build all packages env: - # publint pack defaults to npm (main CI env has no pnpm); in E2E we - # already have pnpm installed and npm pack against pnpm's symlinked - # node_modules is ~10x slower, so prefer pnpm pack here - PUBLINT_PACK: pnpm - run: pnpm build + # publint pack defaults to npm (main CI env has no utoo); in E2E we + # already have utoo installed and npm pack against utoo's symlinked + # node_modules is ~10x slower, so prefer utoo pack here + PUBLINT_PACK: utoo + run: ut run build - name: Pack packages into tgz run: | - pnpm -r pack + utoo -r pack - name: Override dependencies from tgz in ${{ matrix.project.name }} working-directory: ecosystem-ci/${{ matrix.project.name }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2dac019c96..4956f0d8e8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,8 +62,8 @@ jobs: fetch-depth: 0 token: ${{ secrets.GIT_TOKEN }} - - name: Setup pnpm - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + - name: Setup utoo + uses: utooland/setup-utoo@3a51006d0b66afcc32d1b9177a4b200b74f4a8cb # main - name: Setup Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 @@ -72,7 +72,7 @@ jobs: registry-url: 'https://registry.npmjs.org' - name: Install dependencies - run: pnpm install --no-frozen-lockfile + run: ut install --from pnpm - name: Configure Git run: | @@ -149,7 +149,7 @@ jobs: git push origin ${{ github.event.inputs.branch }} --tags - name: Run build - run: pnpm build + run: ut run build - name: Publish packages (dry run) if: ${{ github.event.inputs.dry_run == 'true' }} diff --git a/AGENTS.md b/AGENTS.md index 30ce7bc48c..60e0c0e9c2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,7 @@ If another agent-specific file exists, it should import or defer to this file fo ## Project Map -Egg is maintained as a pnpm monorepo. +Egg is maintained as a utoo monorepo. - `packages/` contains core framework packages and shared internals. - `plugins/` contains optional Egg integrations. @@ -18,12 +18,12 @@ Egg is maintained as a pnpm monorepo. ## Core Commands -- `pnpm install` hydrates the workspace. -- `pnpm run build` builds all packages. -- `pnpm run test` runs the main test suite. -- `pnpm run lint` runs linting. -- `pnpm run typecheck` runs TypeScript checking. -- use filtered commands for focused work, for example `pnpm --filter=egg run test` or `pnpm --filter=site run dev`. +- `utoo install` hydrates the workspace. +- `utoo run build` builds all packages. +- `utoo run test` runs the main test suite. +- `utoo run lint` runs linting. +- `utoo run typecheck` runs TypeScript checking. +- use filtered commands for focused work, for example `utoo --filter=egg run test` or `utoo --filter=site run dev`. ### Local CI @@ -65,7 +65,7 @@ Then re-run tests. - review `SECURITY.md` before handling vulnerability-related work - do not commit secrets, credentials, or local-only URLs -- keep local Node.js and pnpm versions aligned with the repository configuration +- keep local Node.js and utoo versions aligned with the repository configuration ## Shared Knowledge Workflow diff --git a/README.md b/README.md index ed27699833..f1bfb0c824 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,9 @@ Follow the commands listed below. ```bash $ mkdir showcase && cd showcase -$ pnpm create egg@beta -$ pnpm install -$ pnpm run dev +$ utoo create egg@beta +$ utoo install +$ utoo run dev $ open http://localhost:7001 ``` @@ -38,31 +38,31 @@ $ open http://localhost:7001 ## Monorepo Structure -This project is structured as a pnpm monorepo with the following packages: +This project is structured as a utoo monorepo with the following packages: - `packages/egg` - Main Eggjs framework - `examples/helloworld-commonjs` - CommonJS example application - `examples/helloworld-typescript` - TypeScript example application - `site` - Documentation website -The monorepo uses **pnpm catalog mode** for centralized dependency management, ensuring consistent versions across all packages. +The monorepo uses **utoo catalog mode** for centralized dependency management, ensuring consistent versions across all packages. ### Development Commands ```bash # Install dependencies for all packages -pnpm install +utoo install # Build all packages -pnpm run build +utoo run build # Test all packages -pnpm run test +utoo run test # Run specific package commands -pnpm --filter=egg run test -pnpm --filter=@examples/helloworld-typescript run dev -pnpm --filter=site run dev +utoo --filter=egg run test +utoo --filter=@examples/helloworld-typescript run dev +utoo --filter=site run dev ``` ### Local External Services diff --git a/README.zh-CN.md b/README.zh-CN.md index 3025d7bea8..0729ba3dd1 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -27,9 +27,9 @@ ```bash mkdir showcase && cd showcase -pnpm create egg@beta -pnpm install -pnpm run dev +utoo create egg@beta +utoo install +utoo run dev open http://localhost:7001 ``` diff --git a/package.json b/package.json index bbbfba3389..c7ef0c6220 100644 --- a/package.json +++ b/package.json @@ -90,5 +90,5 @@ "optionalDependencies": { "@utoo/utoo-mingw64_nt-10.0-26100-x64": "npm:@utoo/utoo-win32-x64@1.0.28" }, - "packageManager": "pnpm@10.28.0" + "packageManager": "utoo@1.0.28" } diff --git a/packages/egg/README.md b/packages/egg/README.md index d13350e60d..29128016ee 100644 --- a/packages/egg/README.md +++ b/packages/egg/README.md @@ -22,9 +22,9 @@ Follow the commands listed below. ```bash $ mkdir showcase && cd showcase -$ npm init egg --type=simple # Optionally pnpm create egg --type=simple -$ pnpm install -$ pnpm run dev +$ npm init egg --type=simple # Optionally utoo create egg --type=simple +$ utoo install +$ utoo run dev $ open http://localhost:7001 ``` diff --git a/plugins/redis/README.md b/plugins/redis/README.md index 1f8ad4c5ae..339b9120fb 100644 --- a/plugins/redis/README.md +++ b/plugins/redis/README.md @@ -268,7 +268,7 @@ docker compose -f docker-compose.yml up -d Run the unit tests ```bash -pnpm test +utoo test ``` Stop test redis service diff --git a/scripts/publish.js b/scripts/publish.js index 90814bd95f..a744a77dc6 100644 --- a/scripts/publish.js +++ b/scripts/publish.js @@ -3,7 +3,7 @@ /** * Resilient per-package publish script. * - * Unlike `pnpm -r publish`, this script: + * Unlike `utoo -r publish`, this script: * - Skips packages that are already published on npm (safe for retries) * - Publishes each package individually so one failure doesn't block others * - Retries failed packages once @@ -54,7 +54,7 @@ function isPublished(name, version) { } /** - * Publish a single package using pnpm --filter (preserves workspace context + * Publish a single package using utoo --filter (preserves workspace context * so that workspace: protocol references are properly resolved). */ function publishOne(pkg) { @@ -62,7 +62,7 @@ function publishOne(pkg) { if (useProvenance) publishArgs.push('--provenance'); if (isDryRun) publishArgs.push('--dry-run'); - execFileSync('pnpm', publishArgs, { + execFileSync('utoo', publishArgs, { cwd: baseDir, stdio: 'inherit', env: { ...process.env, NPM_CONFIG_LOGLEVEL: 'verbose' }, diff --git a/scripts/utils.js b/scripts/utils.js index 822889c384..90b1978bdc 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -3,7 +3,7 @@ import path from 'node:path'; import yaml from 'js-yaml'; -// Get all publishable packages from pnpm workspace +// Get all publishable packages from utoo workspace export function getPublishablePackages(baseDir) { const workspaceFile = path.join(baseDir, 'pnpm-workspace.yaml'); diff --git a/scripts/version.js b/scripts/version.js index b17008d0c9..e006df1ee7 100644 --- a/scripts/version.js +++ b/scripts/version.js @@ -121,7 +121,7 @@ if (eggVersion) { if (isDryRun) { console.log('\n✅ Dry run complete! No changes were made.'); console.log('\nTo apply these changes, run:'); - console.log(` pnpm run version:${versionType}`); + console.log(` utoo run version:${versionType}`); process.exit(0); } diff --git a/tegg/CLAUDE.md b/tegg/CLAUDE.md index 6ce219b27b..6f68b4e2a7 100644 --- a/tegg/CLAUDE.md +++ b/tegg/CLAUDE.md @@ -26,7 +26,7 @@ standalone/ # 1 standalone package - standalone runtime without Egg.js **Dependency Management:** -- Uses pnpm workspaces with `catalog:` protocol for shared external dependencies +- Uses utoo workspaces with `catalog:` protocol for shared external dependencies - Uses `workspace:*` protocol for internal monorepo dependencies (both tegg and egg packages) - All shared dependency versions centralized in the root `pnpm-workspace.yaml` (not in tegg/) - `catalogMode: prefer` set in root `.npmrc` for automatic catalog usage @@ -60,8 +60,8 @@ standalone/ # 1 standalone package - standalone runtime without Egg.js ### Build & Clean ```bash -pnpm run build # Build all packages including tegg (runs build in all workspaces) -pnpm run clean # Clean all build artifacts including tegg (removes dist, tsbuildinfo) +utoo run build # Build all packages including tegg (runs build in all workspaces) +utoo run clean # Clean all build artifacts including tegg (removes dist, tsbuildinfo) ``` ### Testing @@ -69,9 +69,9 @@ pnpm run clean # Clean all build artifacts including tegg (removes All tegg packages use **Vitest** for testing and are integrated with the main Egg.js monorepo test suite. ```bash -pnpm test # Run vitest tests for all packages (from monorepo root) -pnpm run test:cov # Run tests with coverage -pnpm run ci # Full CI: vitest with coverage and bail on first failure +utoo test # Run vitest tests for all packages (from monorepo root) +utoo run test:cov # Run tests with coverage +utoo run ci # Full CI: vitest with coverage and bail on first failure ``` **Note:** Tests are configured in the monorepo root `vitest.config.ts` which includes all tegg packages (`tegg/core/*`, `tegg/plugin/*`, `tegg/standalone/*`). @@ -79,9 +79,9 @@ pnpm run ci # Full CI: vitest with coverage and bail on first f ### Type Checking & Linting ```bash -pnpm run typecheck # Clean and type check all workspaces (including tegg) -pnpm run lint # Run oxlint with type-aware checking on all packages -pnpm run fmtcheck # Check code formatting with oxfmt +utoo run typecheck # Clean and type check all workspaces (including tegg) +utoo run lint # Run oxlint with type-aware checking on all packages +utoo run fmtcheck # Check code formatting with oxfmt ``` **Note:** oxlint automatically runs with `--type-aware` flag for enhanced TypeScript checking. @@ -91,15 +91,15 @@ pnpm run fmtcheck # Check code formatting with oxfmt **Note:** Run these commands from the monorepo root (`../egg`). ```bash -pnpm run version:patch # Bump patch version (0.0.X) -pnpm run version:minor # Bump minor version (0.X.0) -pnpm run version:major # Bump major version (X.0.0) -pnpm run version:prepatch # Bump to next prerelease patch version -pnpm run version:preminor # Bump to next prerelease minor version -pnpm run version:premajor # Bump to next prerelease major version -pnpm run version:alpha # Bump prerelease alpha version -pnpm run version:beta # Bump prerelease beta version -pnpm run version:rc # Bump prerelease rc version +utoo run version:patch # Bump patch version (0.0.X) +utoo run version:minor # Bump minor version (0.X.0) +utoo run version:major # Bump major version (X.0.0) +utoo run version:prepatch # Bump to next prerelease patch version +utoo run version:preminor # Bump to next prerelease minor version +utoo run version:premajor # Bump to next prerelease major version +utoo run version:alpha # Bump prerelease alpha version +utoo run version:beta # Bump prerelease beta version +utoo run version:rc # Bump prerelease rc version ``` ### Working with Individual Packages @@ -108,18 +108,18 @@ pnpm run version:rc # Bump prerelease rc version ```bash # Install dependencies -pnpm install # Install all dependencies using catalog versions +utoo install # Install all dependencies using catalog versions # Type check specific packages -pnpm -r run typecheck # Type check all packages recursively -pnpm --filter @eggjs/tegg-runtime run typecheck +utoo -r run typecheck # Type check all packages recursively +utoo --filter @eggjs/tegg-runtime run typecheck # Build specific packages -pnpm --filter @eggjs/metadata run build -pnpm --filter @eggjs/tegg-runtime run build +utoo --filter @eggjs/metadata run build +utoo --filter @eggjs/tegg-runtime run build # Clean specific package -pnpm --filter @eggjs/tegg-runtime run clean +utoo --filter @eggjs/tegg-runtime run clean ``` **Note:** Individual tegg packages don't have test scripts in their package.json. Tests are run via the monorepo root vitest configuration. diff --git a/tools/create-egg/README.md b/tools/create-egg/README.md index c3d688552b..ae13ab7545 100644 --- a/tools/create-egg/README.md +++ b/tools/create-egg/README.md @@ -27,10 +27,10 @@ With Yarn: yarn create egg ``` -With PNPM: +With utoo: ```bash -pnpm create egg +utoo create egg ``` Then follow the prompts! @@ -44,8 +44,8 @@ npm create egg@latest my-egg-app -- --template tegg # yarn yarn create egg my-egg-app --template tegg -# pnpm -pnpm create egg my-egg-app --template tegg +# utoo +utoo create egg my-egg-app --template tegg ``` Currently supported template presets include: diff --git a/wiki/concepts/repository-map.md b/wiki/concepts/repository-map.md index 7464dbbfaf..1c53650e02 100644 --- a/wiki/concepts/repository-map.md +++ b/wiki/concepts/repository-map.md @@ -15,7 +15,7 @@ status: active # Repository Map -This repo is a pnpm monorepo centered on the Egg.js framework and related packages. +This repo is a utoo monorepo centered on the Egg.js framework and related packages. ## Main Areas From 26b1a408c244c5bdf43ba0e8318325fb8793cd0f Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 19:45:13 +0800 Subject: [PATCH 02/15] fix(ci,docs): drop unsupported PUBLINT_PACK value, sync utoo/node versions - E2E `Build all packages` was failing because `PUBLINT_PACK: utoo` is not in publint's supported set (`npm | pnpm | yarn | bun`). Falling back to the default (`npm`) so publint's per-package pack succeeds again, matching the main CI environment. - Align `.github/copilot-instructions.md` Node and utoo versions with the values declared in `package.json` (`engines.node >=22.18.0`, `packageManager: utoo@1.0.28`). Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/copilot-instructions.md | 4 ++-- .github/workflows/e2e-test.yml | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index efd35f0ce4..577b4f2a36 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -10,8 +10,8 @@ This is a **utoo monorepo** with multiple packages using utoo workspaces and cat ## Prerequisites and Environment Setup -- **Node.js >= 20.19.0 required** - This is a hard requirement -- Enable utoo first: `corepack enable utoo` (installs utoo v10.16.0) +- **Node.js >= 22.18.0 required** - This is a hard requirement +- Enable utoo first: `corepack enable utoo` (installs utoo v1.0.28) - **NEVER CANCEL** any build or test commands - they can take several minutes to complete ## Bootstrap and Build Process diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 94b57110fb..905571ef04 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -153,11 +153,6 @@ jobs: run: ut install --from pnpm - name: Build all packages - env: - # publint pack defaults to npm (main CI env has no utoo); in E2E we - # already have utoo installed and npm pack against utoo's symlinked - # node_modules is ~10x slower, so prefer utoo pack here - PUBLINT_PACK: utoo run: ut run build - name: Pack packages into tgz From 8a96e3ee88960f2a38ab797dbfd02a15928e879a Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 19:49:14 +0800 Subject: [PATCH 03/15] chore(repo): address CodeRabbit review feedback - scripts/publish.js: invoke `utoo publish` from each package's own directory so utoo's supported flag set works. Drop pnpm-only flags (`--filter`, `--no-git-checks`); keep the npm-standard `--access` and `--provenance` flags that utoo forwards to npm. - AGENTS.md: prepend `corepack enable utoo` to the canonical commands so a clean machine boots into the pinned utoo version. - scripts/version.js: print the `ut run version:` alias used by the rest of the repo (workflows + package.json scripts). Co-Authored-By: Claude Opus 4.7 (1M context) --- AGENTS.md | 1 + scripts/publish.js | 10 ++++++---- scripts/version.js | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 60e0c0e9c2..8a2211baad 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,6 +18,7 @@ Egg is maintained as a utoo monorepo. ## Core Commands +- `corepack enable utoo` enables the pinned utoo version on a clean machine. - `utoo install` hydrates the workspace. - `utoo run build` builds all packages. - `utoo run test` runs the main test suite. diff --git a/scripts/publish.js b/scripts/publish.js index a744a77dc6..55cc18d3ba 100644 --- a/scripts/publish.js +++ b/scripts/publish.js @@ -54,16 +54,18 @@ function isPublished(name, version) { } /** - * Publish a single package using utoo --filter (preserves workspace context - * so that workspace: protocol references are properly resolved). + * Publish a single package by running `utoo publish` from the package + * directory. utoo's publish only documents --tag/--dry-run/--otp, so we + * keep the npm-standard --access/--provenance flags (forwarded to npm) + * and drop pnpm-only flags (--filter, --no-git-checks). */ function publishOne(pkg) { - const publishArgs = ['--filter', pkg.name, 'publish', '--no-git-checks', '--access', 'public', '--tag', npmTag]; + const publishArgs = ['publish', '--access', 'public', '--tag', npmTag]; if (useProvenance) publishArgs.push('--provenance'); if (isDryRun) publishArgs.push('--dry-run'); execFileSync('utoo', publishArgs, { - cwd: baseDir, + cwd: path.join(baseDir, pkg.directory, pkg.folder), stdio: 'inherit', env: { ...process.env, NPM_CONFIG_LOGLEVEL: 'verbose' }, timeout: 120000, diff --git a/scripts/version.js b/scripts/version.js index e006df1ee7..082249a160 100644 --- a/scripts/version.js +++ b/scripts/version.js @@ -121,7 +121,7 @@ if (eggVersion) { if (isDryRun) { console.log('\n✅ Dry run complete! No changes were made.'); console.log('\nTo apply these changes, run:'); - console.log(` utoo run version:${versionType}`); + console.log(` ut run version:${versionType}`); process.exit(0); } From a0c2ddfd883e80ae638c7c7c31fe5e05b895448b Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 19:54:41 +0800 Subject: [PATCH 04/15] fix(ci): replace unsupported `utoo -r pack` with per-package npm pack utoo doesn't implement pnpm's recursive `-r pack`, so the E2E "Pack packages into tgz" step was failing with `error: unexpected argument '-r' found`. Replace it with a small node script that reuses the publish-script's package discovery and runs `npm pack --pack-destination ` per publishable package, matching the tgz layout `ecosystem-ci/patch-project.ts` expects (repo-root-relative file:// overrides). Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/e2e-test.yml | 3 +-- scripts/pack-all.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 scripts/pack-all.js diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 905571ef04..3e99c43f2f 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -156,8 +156,7 @@ jobs: run: ut run build - name: Pack packages into tgz - run: | - utoo -r pack + run: node scripts/pack-all.js - name: Override dependencies from tgz in ${{ matrix.project.name }} working-directory: ecosystem-ci/${{ matrix.project.name }} diff --git a/scripts/pack-all.js b/scripts/pack-all.js new file mode 100644 index 0000000000..2bf240e412 --- /dev/null +++ b/scripts/pack-all.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +/** + * Pack every publishable workspace package into the repository root, + * matching the tgz layout that `ecosystem-ci/patch-project.ts` expects. + * + * utoo does not implement `pnpm -r pack`, so we drive `npm pack` per + * package using the same package discovery the publish script uses. + */ + +import { execFileSync } from 'node:child_process'; +import path from 'node:path'; + +import { getPublishablePackages } from './utils.js'; + +const baseDir = path.join(import.meta.dirname, '..'); +const packages = getPublishablePackages(baseDir); + +console.log(`đŸ“Ļ Packing ${packages.length} package(s) into ${baseDir}`); + +for (const pkg of packages) { + const cwd = path.join(baseDir, pkg.directory, pkg.folder); + execFileSync('npm', ['pack', '--pack-destination', baseDir], { + cwd, + stdio: 'inherit', + timeout: 120000, + }); +} + +console.log('✅ Pack complete'); From 585d9810238d32d018429d46b56b88aa9e7b1dd2 Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 20:02:34 +0800 Subject: [PATCH 05/15] fix(docs,scripts): use \`ut\` CLI alias and real script names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeRabbit / Copilot caught that the docs reference \`utoo run â€Ļ\` while package.json scripts and CI workflows all use the \`ut\` alias, and some referenced root scripts (\`clean\`, \`build:skip\`, \`example:commonjs\`/\`example:typescript\`) don't exist. - Rewrite \`utoo install/run/create/test/pack/publish/--filter/-r\` to the matching \`ut â€Ļ\` form in README.md, README.zh-CN.md, packages/egg/README.md, tools/create-egg/README.md, plugins/redis/README.md, tegg/CLAUDE.md, AGENTS.md, .github/copilot-instructions.md, scripts/publish.js, and scripts/dev-services.js. Keep the \`utoo\` package name (corepack, \`packageManager\`, prose) intact. - Fix script name drift: \`ut run clean\` → \`ut run clean-dist\`, \`ut run build:skip\` → \`ut run build\`, \`ut run example:{commonjs,typescript}\` → \`ut run example:dev:{commonjs,typescript}\`. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/copilot-instructions.md | 54 ++++++++++++++++----------------- AGENTS.md | 12 ++++---- README.md | 32 +++++++++---------- README.zh-CN.md | 6 ++-- packages/egg/README.md | 6 ++-- plugins/redis/README.md | 2 +- scripts/dev-services.js | 4 +-- scripts/publish.js | 6 ++-- tegg/CLAUDE.md | 46 ++++++++++++++-------------- tools/create-egg/README.md | 4 +-- 10 files changed, 86 insertions(+), 86 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 577b4f2a36..954259a32f 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -23,13 +23,13 @@ This is a **utoo monorepo** with multiple packages using utoo workspaces and cat corepack enable utoo # 2. Install all dependencies - takes ~63 seconds. NEVER CANCEL. Set timeout to 120+ seconds. -utoo install +ut install # 3. Build all packages - takes ~14 seconds. NEVER CANCEL. Set timeout to 60+ seconds. -utoo run build +ut run build # 4. Run linting (optional but recommended) - takes ~2 seconds -utoo run lint +ut run lint ``` ## Monorepo Structure @@ -54,45 +54,45 @@ utoo run lint ### Build Commands -- `utoo run build` - **Build all packages (~14 seconds). NEVER CANCEL. Set timeout to 60+ seconds.** -- `utoo run clean` - Clean all dist directories +- `ut run build` - **Build all packages (~14 seconds). NEVER CANCEL. Set timeout to 60+ seconds.** +- `ut run clean-dist` - Clean all dist directories ### Testing Commands -- `utoo run test` - **Run all tests (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** -- `utoo run test:cov` - **Run tests with coverage (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** -- `utoo run ci` - **Run test coverage + build (~2.1 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** +- `ut run test` - **Run all tests (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** +- `ut run test:cov` - **Run tests with coverage (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** +- `ut run ci` - **Run test coverage + build (~2.1 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** ### Linting Commands -- `utoo run lint` - Run oxlint across all packages (~2 seconds) +- `ut run lint` - Run oxlint across all packages (~2 seconds) ### Documentation Commands -- `utoo run site:dev` - Start documentation dev server at http://localhost:8000 -- `cd site && utoo run build:skip` - **Build documentation site (~24 seconds). NEVER CANCEL. Set timeout to 60+ seconds.** +- `ut run site:dev` - Start documentation dev server at http://localhost:8000 +- `cd site && ut run build` - **Build documentation site (~24 seconds). NEVER CANCEL. Set timeout to 60+ seconds.** ### Example Applications (Currently Not Working) -- `utoo run example:commonjs` - Start CommonJS example (has runtime issues) -- `utoo run example:typescript` - Start TypeScript example (has runtime issues) +- `ut run example:dev:commonjs` - Start CommonJS example (has runtime issues) +- `ut run example:dev:typescript` - Start TypeScript example (has runtime issues) ## Package-Specific Commands -Run commands for specific packages using `utoo --filter=`: +Run commands for specific packages using `ut --filter=`: ```bash # Examples -utoo --filter=egg run test -utoo --filter=@eggjs/core run build -utoo --filter=site run dev +ut --filter=egg run test +ut --filter=@eggjs/core run build +ut --filter=site run dev ``` ## Development Workflow ### 1. Making Changes -- Always build packages first: `utoo run build` +- Always build packages first: `ut run build` - Work primarily in `packages/egg/src/` for core framework features - Use TypeScript throughout - all packages are TypeScript-based - Follow the existing directory conventions in `packages/egg/src/`: @@ -108,16 +108,16 @@ utoo --filter=site run dev ```bash # 1. Build all packages (required) -utoo run build +ut run build # 2. Run linting -utoo run lint +ut run lint # 3. Run tests (some failures are expected in fresh environment) -utoo run test +ut run test # 4. Test documentation site -utoo run site:dev +ut run site:dev ``` ### 3. Testing Strategy @@ -179,7 +179,7 @@ utoo run site:dev ### Build Issues -- Always run `utoo run build` after making changes +- Always run `ut run build` after making changes - TypeScript compilation errors will show clearly - Build warnings are generally acceptable @@ -217,10 +217,10 @@ utoo run site:dev After making changes, always verify: -1. **Build Success**: `utoo run build` completes without errors -2. **Linting Passes**: `utoo run lint` shows no new errors -3. **Documentation Loads**: `utoo run site:dev` starts successfully and site loads at http://localhost:8000 -4. **Tests Run**: `utoo run test` executes (some failures expected, focus on your changes) +1. **Build Success**: `ut run build` completes without errors +2. **Linting Passes**: `ut run lint` shows no new errors +3. **Documentation Loads**: `ut run site:dev` starts successfully and site loads at http://localhost:8000 +4. **Tests Run**: `ut run test` executes (some failures expected, focus on your changes) **Remember**: This is a complex enterprise framework. Always build first, validate incrementally, and focus on the core packages (`egg`, `core`, `utils`) for most development work. diff --git a/AGENTS.md b/AGENTS.md index 8a2211baad..36c6548c9c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,12 +19,12 @@ Egg is maintained as a utoo monorepo. ## Core Commands - `corepack enable utoo` enables the pinned utoo version on a clean machine. -- `utoo install` hydrates the workspace. -- `utoo run build` builds all packages. -- `utoo run test` runs the main test suite. -- `utoo run lint` runs linting. -- `utoo run typecheck` runs TypeScript checking. -- use filtered commands for focused work, for example `utoo --filter=egg run test` or `utoo --filter=site run dev`. +- `ut install` hydrates the workspace. +- `ut run build` builds all packages. +- `ut run test` runs the main test suite. +- `ut run lint` runs linting. +- `ut run typecheck` runs TypeScript checking. +- use filtered commands for focused work, for example `ut --filter=egg run test` or `ut --filter=site run dev`. ### Local CI diff --git a/README.md b/README.md index f1bfb0c824..f8a0c2f238 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,9 @@ Follow the commands listed below. ```bash $ mkdir showcase && cd showcase -$ utoo create egg@beta -$ utoo install -$ utoo run dev +$ ut create egg@beta +$ ut install +$ ut run dev $ open http://localhost:7001 ``` @@ -51,18 +51,18 @@ The monorepo uses **utoo catalog mode** for centralized dependency management, e ```bash # Install dependencies for all packages -utoo install +ut install # Build all packages -utoo run build +ut run build # Test all packages -utoo run test +ut run test # Run specific package commands -utoo --filter=egg run test -utoo --filter=@examples/helloworld-typescript run dev -utoo --filter=site run dev +ut --filter=egg run test +ut --filter=@examples/helloworld-typescript run dev +ut --filter=site run dev ``` ### Local External Services @@ -70,7 +70,7 @@ utoo --filter=site run dev Some DAL, ORM, Redis, and ecosystem benchmark paths need local MySQL and Redis services. Start the repository-aligned Docker services before running those tests on a clean machine: ```bash -utoo run dev:services:start +ut run dev:services:start ``` This starts MySQL 8 and Redis 7, matching the main CI service versions, and creates the databases used by local DAL/ORM/e2e fixtures: `test`, `apple`, `banana`, `test_runtime_datasource`, `test_runtime_dao`, `test_dal_plugin`, `test_dal_standalone`, `cnpmcore`, and `cnpmcore_unittest`. @@ -78,9 +78,9 @@ This starts MySQL 8 and Redis 7, matching the main CI service versions, and crea Useful commands: ```bash -utoo run dev:services:status -utoo run dev:services:stop -utoo run dev:services:reset +ut run dev:services:status +ut run dev:services:stop +ut run dev:services:reset ``` The default host ports are `127.0.0.1:3306` for MySQL and `127.0.0.1:6379` for Redis. If either port is already used, the start command stops before changing containers. Keep using the existing service if it is compatible with CI, or stop it and run the command again. You can change Docker host ports with `EGG_DEV_SERVICES_MYSQL_PORT` and `EGG_DEV_SERVICES_REDIS_PORT`; however, the full DAL/ORM/Redis local test path still expects the default host ports. @@ -88,11 +88,11 @@ The default host ports are `127.0.0.1:3306` for MySQL and `127.0.0.1:6379` for R Image overrides are available for compatibility checks: ```bash -EGG_DEV_SERVICES_MYSQL_IMAGE=mysql:5.7 utoo run dev:services:start -EGG_DEV_SERVICES_REDIS_IMAGE=redis:7 utoo run dev:services:start +EGG_DEV_SERVICES_MYSQL_IMAGE=mysql:5.7 ut run dev:services:start +EGG_DEV_SERVICES_REDIS_IMAGE=redis:7 ut run dev:services:start ``` -Run `utoo run dev:services:reset` before switching MySQL image families, for example between MySQL 8 and MySQL 5.7, because MySQL data directories are not downgrade-compatible across major versions. +Run `ut run dev:services:reset` before switching MySQL image families, for example between MySQL 8 and MySQL 5.7, because MySQL data directories are not downgrade-compatible across major versions. Current hard-coded service assumptions: diff --git a/README.zh-CN.md b/README.zh-CN.md index 0729ba3dd1..e923fb6bec 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -27,9 +27,9 @@ ```bash mkdir showcase && cd showcase -utoo create egg@beta -utoo install -utoo run dev +ut create egg@beta +ut install +ut run dev open http://localhost:7001 ``` diff --git a/packages/egg/README.md b/packages/egg/README.md index 29128016ee..38dfd06d83 100644 --- a/packages/egg/README.md +++ b/packages/egg/README.md @@ -22,9 +22,9 @@ Follow the commands listed below. ```bash $ mkdir showcase && cd showcase -$ npm init egg --type=simple # Optionally utoo create egg --type=simple -$ utoo install -$ utoo run dev +$ npm init egg --type=simple # Optionally ut create egg --type=simple +$ ut install +$ ut run dev $ open http://localhost:7001 ``` diff --git a/plugins/redis/README.md b/plugins/redis/README.md index 339b9120fb..dd1e0ff477 100644 --- a/plugins/redis/README.md +++ b/plugins/redis/README.md @@ -268,7 +268,7 @@ docker compose -f docker-compose.yml up -d Run the unit tests ```bash -utoo test +ut test ``` Stop test redis service diff --git a/scripts/dev-services.js b/scripts/dev-services.js index 037064465f..851570bbc3 100644 --- a/scripts/dev-services.js +++ b/scripts/dev-services.js @@ -131,7 +131,7 @@ async function assertPortAvailable(service, port, containerPort, running) { throw new Error( [ `${service} is already running for this compose project on ${current}, but this run requested 127.0.0.1:${port}.`, - 'Re-run with the same EGG_DEV_SERVICES_* port override, or use `utoo run dev:services:reset` before changing ports.', + 'Re-run with the same EGG_DEV_SERVICES_* port override, or use `ut run dev:services:reset` before changing ports.', ].join('\n'), ); } @@ -195,7 +195,7 @@ async function start() { [ message, 'The compose stack is still running so Docker health status and logs can be inspected.', - 'After fixing the issue, run `utoo run dev:services:reset` to clean up before starting again.', + 'After fixing the issue, run `ut run dev:services:reset` to clean up before starting again.', ].join('\n'), { cause: err }, ); diff --git a/scripts/publish.js b/scripts/publish.js index 55cc18d3ba..be75d393c4 100644 --- a/scripts/publish.js +++ b/scripts/publish.js @@ -3,7 +3,7 @@ /** * Resilient per-package publish script. * - * Unlike `utoo -r publish`, this script: + * Unlike `ut -r publish`, this script: * - Skips packages that are already published on npm (safe for retries) * - Publishes each package individually so one failure doesn't block others * - Retries failed packages once @@ -54,7 +54,7 @@ function isPublished(name, version) { } /** - * Publish a single package by running `utoo publish` from the package + * Publish a single package by running `ut publish` from the package * directory. utoo's publish only documents --tag/--dry-run/--otp, so we * keep the npm-standard --access/--provenance flags (forwarded to npm) * and drop pnpm-only flags (--filter, --no-git-checks). @@ -64,7 +64,7 @@ function publishOne(pkg) { if (useProvenance) publishArgs.push('--provenance'); if (isDryRun) publishArgs.push('--dry-run'); - execFileSync('utoo', publishArgs, { + execFileSync('ut', publishArgs, { cwd: path.join(baseDir, pkg.directory, pkg.folder), stdio: 'inherit', env: { ...process.env, NPM_CONFIG_LOGLEVEL: 'verbose' }, diff --git a/tegg/CLAUDE.md b/tegg/CLAUDE.md index 6f68b4e2a7..7ab65f9c9b 100644 --- a/tegg/CLAUDE.md +++ b/tegg/CLAUDE.md @@ -60,8 +60,8 @@ standalone/ # 1 standalone package - standalone runtime without Egg.js ### Build & Clean ```bash -utoo run build # Build all packages including tegg (runs build in all workspaces) -utoo run clean # Clean all build artifacts including tegg (removes dist, tsbuildinfo) +ut run build # Build all packages including tegg (runs build in all workspaces) +ut run clean-dist # Clean all build artifacts including tegg (removes dist, tsbuildinfo) ``` ### Testing @@ -69,9 +69,9 @@ utoo run clean # Clean all build artifacts including tegg (removes All tegg packages use **Vitest** for testing and are integrated with the main Egg.js monorepo test suite. ```bash -utoo test # Run vitest tests for all packages (from monorepo root) -utoo run test:cov # Run tests with coverage -utoo run ci # Full CI: vitest with coverage and bail on first failure +ut test # Run vitest tests for all packages (from monorepo root) +ut run test:cov # Run tests with coverage +ut run ci # Full CI: vitest with coverage and bail on first failure ``` **Note:** Tests are configured in the monorepo root `vitest.config.ts` which includes all tegg packages (`tegg/core/*`, `tegg/plugin/*`, `tegg/standalone/*`). @@ -79,9 +79,9 @@ utoo run ci # Full CI: vitest with coverage and bail on first f ### Type Checking & Linting ```bash -utoo run typecheck # Clean and type check all workspaces (including tegg) -utoo run lint # Run oxlint with type-aware checking on all packages -utoo run fmtcheck # Check code formatting with oxfmt +ut run typecheck # Clean and type check all workspaces (including tegg) +ut run lint # Run oxlint with type-aware checking on all packages +ut run fmtcheck # Check code formatting with oxfmt ``` **Note:** oxlint automatically runs with `--type-aware` flag for enhanced TypeScript checking. @@ -91,15 +91,15 @@ utoo run fmtcheck # Check code formatting with oxfmt **Note:** Run these commands from the monorepo root (`../egg`). ```bash -utoo run version:patch # Bump patch version (0.0.X) -utoo run version:minor # Bump minor version (0.X.0) -utoo run version:major # Bump major version (X.0.0) -utoo run version:prepatch # Bump to next prerelease patch version -utoo run version:preminor # Bump to next prerelease minor version -utoo run version:premajor # Bump to next prerelease major version -utoo run version:alpha # Bump prerelease alpha version -utoo run version:beta # Bump prerelease beta version -utoo run version:rc # Bump prerelease rc version +ut run version:patch # Bump patch version (0.0.X) +ut run version:minor # Bump minor version (0.X.0) +ut run version:major # Bump major version (X.0.0) +ut run version:prepatch # Bump to next prerelease patch version +ut run version:preminor # Bump to next prerelease minor version +ut run version:premajor # Bump to next prerelease major version +ut run version:alpha # Bump prerelease alpha version +ut run version:beta # Bump prerelease beta version +ut run version:rc # Bump prerelease rc version ``` ### Working with Individual Packages @@ -108,18 +108,18 @@ utoo run version:rc # Bump prerelease rc version ```bash # Install dependencies -utoo install # Install all dependencies using catalog versions +ut install # Install all dependencies using catalog versions # Type check specific packages -utoo -r run typecheck # Type check all packages recursively -utoo --filter @eggjs/tegg-runtime run typecheck +ut -r run typecheck # Type check all packages recursively +ut --filter @eggjs/tegg-runtime run typecheck # Build specific packages -utoo --filter @eggjs/metadata run build -utoo --filter @eggjs/tegg-runtime run build +ut --filter @eggjs/metadata run build +ut --filter @eggjs/tegg-runtime run build # Clean specific package -utoo --filter @eggjs/tegg-runtime run clean +ut --filter @eggjs/tegg-runtime run clean ``` **Note:** Individual tegg packages don't have test scripts in their package.json. Tests are run via the monorepo root vitest configuration. diff --git a/tools/create-egg/README.md b/tools/create-egg/README.md index ae13ab7545..717c0ae30d 100644 --- a/tools/create-egg/README.md +++ b/tools/create-egg/README.md @@ -30,7 +30,7 @@ yarn create egg With utoo: ```bash -utoo create egg +ut create egg ``` Then follow the prompts! @@ -45,7 +45,7 @@ npm create egg@latest my-egg-app -- --template tegg yarn create egg my-egg-app --template tegg # utoo -utoo create egg my-egg-app --template tegg +ut create egg my-egg-app --template tegg ``` Currently supported template presets include: From 80b413bc60b52f4a0b790bcaaac01da0c534c08e Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 20:07:45 +0800 Subject: [PATCH 06/15] fix(ci): restore pnpm for E2E pack step `ut pm-pack` does not yet resolve `workspace:` / `catalog:` protocols inside the packed manifests, so downstream `npm install` in the ecosystem-ci projects fails with `EUNSUPPORTEDPROTOCOL`. `npm pack` has the same limitation, which is why the previous attempt with scripts/pack-all.js also broke. Keep pnpm available just for the pack step and drop the unused scripts/pack-all.js. The rest of the workflow stays on utoo. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/e2e-test.yml | 11 ++++++++++- scripts/pack-all.js | 30 ------------------------------ 2 files changed, 10 insertions(+), 31 deletions(-) delete mode 100644 scripts/pack-all.js diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 3e99c43f2f..0ac5f23a01 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -144,6 +144,13 @@ jobs: - name: Install utoo uses: utooland/setup-utoo@3a51006d0b66afcc32d1b9177a4b200b74f4a8cb # main + - name: Install pnpm (for `pnpm -r pack`) + # utoo's `ut pm-pack` does not resolve `workspace:` / `catalog:` + # protocols inside the packed manifests, so downstream `npm install` + # in the ecosystem-ci projects fails with EUNSUPPORTEDPROTOCOL. + # Keep pnpm available just for the pack step. + uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: @@ -156,7 +163,9 @@ jobs: run: ut run build - name: Pack packages into tgz - run: node scripts/pack-all.js + # `pnpm -r pack` resolves workspace:/catalog: deps in the emitted + # manifests, which `ut pm-pack` does not yet do. + run: pnpm -r pack - name: Override dependencies from tgz in ${{ matrix.project.name }} working-directory: ecosystem-ci/${{ matrix.project.name }} diff --git a/scripts/pack-all.js b/scripts/pack-all.js deleted file mode 100644 index 2bf240e412..0000000000 --- a/scripts/pack-all.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node - -/** - * Pack every publishable workspace package into the repository root, - * matching the tgz layout that `ecosystem-ci/patch-project.ts` expects. - * - * utoo does not implement `pnpm -r pack`, so we drive `npm pack` per - * package using the same package discovery the publish script uses. - */ - -import { execFileSync } from 'node:child_process'; -import path from 'node:path'; - -import { getPublishablePackages } from './utils.js'; - -const baseDir = path.join(import.meta.dirname, '..'); -const packages = getPublishablePackages(baseDir); - -console.log(`đŸ“Ļ Packing ${packages.length} package(s) into ${baseDir}`); - -for (const pkg of packages) { - const cwd = path.join(baseDir, pkg.directory, pkg.folder); - execFileSync('npm', ['pack', '--pack-destination', baseDir], { - cwd, - stdio: 'inherit', - timeout: 120000, - }); -} - -console.log('✅ Pack complete'); From f88b87b917b6b4ef3c8f9d25d4eca2eef7427672 Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 20:11:11 +0800 Subject: [PATCH 07/15] fix(ci): pin pnpm version in E2E setup-pnpm action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without an explicit \`version\` input, \`pnpm/action-setup\` reads \`packageManager\` from package.json — which now declares \`utoo@1.0.28\`, not pnpm — and aborts with \`Invalid packageManager field in package.json\`. Pin to \`10\` (matches the prior \`pnpm@10.28.0\` we used) so the pack step bootstraps regardless of the \`packageManager\` value. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/e2e-test.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 0ac5f23a01..303202f7ef 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -148,8 +148,12 @@ jobs: # utoo's `ut pm-pack` does not resolve `workspace:` / `catalog:` # protocols inside the packed manifests, so downstream `npm install` # in the ecosystem-ci projects fails with EUNSUPPORTEDPROTOCOL. - # Keep pnpm available just for the pack step. + # Keep pnpm available just for the pack step. The explicit `version` + # is required because `packageManager` in package.json now points at + # utoo, so the action can't infer the pnpm version itself. uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + with: + version: 10 - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 From 2a4c085607018467fa4580fb35023e1639b7497a Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 20:14:25 +0800 Subject: [PATCH 08/15] docs: fix script descriptions and prepend corepack bootstrap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - .github/copilot-instructions.md: `ut run ci` actually runs tests with coverage only (no build); rewrite description accordingly. Site dev server uses VitePress' default port, not :8000; drop the hard-coded URL. Replace the `cd site && ut run build` invocation with the root `ut run site:build` script. - scripts/utils.js: clarify the workspace-file comment — utoo reads `pnpm-workspace.yaml` as-is, so naming the file matters. - README.md / README.zh-CN.md / packages/egg/README.md: prepend `corepack enable utoo` to the quickstart so clean machines get the pinned utoo before `ut create`/`ut install`. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/copilot-instructions.md | 8 ++++---- README.md | 1 + README.zh-CN.md | 1 + packages/egg/README.md | 1 + scripts/utils.js | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 954259a32f..78b1d17ef9 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -61,7 +61,7 @@ ut run lint - `ut run test` - **Run all tests (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** - `ut run test:cov` - **Run tests with coverage (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** -- `ut run ci` - **Run test coverage + build (~2.1 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** +- `ut run ci` - **Run tests with coverage (~2 minutes). NEVER CANCEL. Set timeout to 180+ seconds.** ### Linting Commands @@ -69,8 +69,8 @@ ut run lint ### Documentation Commands -- `ut run site:dev` - Start documentation dev server at http://localhost:8000 -- `cd site && ut run build` - **Build documentation site (~24 seconds). NEVER CANCEL. Set timeout to 60+ seconds.** +- `ut run site:dev` - Start documentation dev server (defaults to VitePress port 5173) +- `ut run site:build` - **Build documentation site (~24 seconds). NEVER CANCEL. Set timeout to 60+ seconds.** ### Example Applications (Currently Not Working) @@ -219,7 +219,7 @@ After making changes, always verify: 1. **Build Success**: `ut run build` completes without errors 2. **Linting Passes**: `ut run lint` shows no new errors -3. **Documentation Loads**: `ut run site:dev` starts successfully and site loads at http://localhost:8000 +3. **Documentation Loads**: `ut run site:dev` starts successfully and the printed VitePress URL responds 4. **Tests Run**: `ut run test` executes (some failures expected, focus on your changes) **Remember**: This is a complex enterprise framework. Always build first, validate incrementally, and focus on the core packages (`egg`, `core`, `utils`) for most development work. diff --git a/README.md b/README.md index f8a0c2f238..c928ebcaca 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ English | [įŽ€äŊ“中文](./README.zh-CN.md) Follow the commands listed below. ```bash +$ corepack enable utoo $ mkdir showcase && cd showcase $ ut create egg@beta $ ut install diff --git a/README.zh-CN.md b/README.zh-CN.md index e923fb6bec..345aca0f72 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -26,6 +26,7 @@ ## åŋĢ速åŧ€å§‹ ```bash +corepack enable utoo mkdir showcase && cd showcase ut create egg@beta ut install diff --git a/packages/egg/README.md b/packages/egg/README.md index 38dfd06d83..fca881d760 100644 --- a/packages/egg/README.md +++ b/packages/egg/README.md @@ -21,6 +21,7 @@ Follow the commands listed below. ```bash +$ corepack enable utoo $ mkdir showcase && cd showcase $ npm init egg --type=simple # Optionally ut create egg --type=simple $ ut install diff --git a/scripts/utils.js b/scripts/utils.js index 90b1978bdc..8cb4e8b2cb 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -3,7 +3,8 @@ import path from 'node:path'; import yaml from 'js-yaml'; -// Get all publishable packages from utoo workspace +// Get all publishable packages by reading pnpm-workspace.yaml +// (utoo consumes the same workspace manifest). export function getPublishablePackages(baseDir) { const workspaceFile = path.join(baseDir, 'pnpm-workspace.yaml'); From 38ee2ad5b016f615f820b3d2b3ced50f1736df8d Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 20:21:01 +0800 Subject: [PATCH 09/15] fix(ci): disable pnpm's packageManager strict check for the pack step pnpm sees \`packageManager: utoo@1.0.28\` in package.json and refuses to run with \`This project is configured to use utoo\`. Set \`PNPM_PACKAGE_MANAGER_STRICT=false\` for just the \`pnpm -r pack\` step so the workaround until utoo's own pack supports workspace:/catalog: resolution doesn't get blocked. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/e2e-test.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 303202f7ef..5d2ba87620 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -168,7 +168,11 @@ jobs: - name: Pack packages into tgz # `pnpm -r pack` resolves workspace:/catalog: deps in the emitted - # manifests, which `ut pm-pack` does not yet do. + # manifests, which `ut pm-pack` does not yet do. pnpm refuses to + # run when `packageManager` points at another tool, so disable + # that strict check for just this step. + env: + PNPM_PACKAGE_MANAGER_STRICT: 'false' run: pnpm -r pack - name: Override dependencies from tgz in ${{ matrix.project.name }} From e38249cbc709d8f1f3ff7840dd6a5bb38063b79a Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 20:23:19 +0800 Subject: [PATCH 10/15] =?UTF-8?q?docs:=20fix=20\`ut=20test\`=20=E2=86=92?= =?UTF-8?q?=20\`ut=20run=20test\`=20and=20Dumi=20=E2=86=92=20VitePress=20r?= =?UTF-8?q?eference?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - tegg/CLAUDE.md: switch the test command to the script form (\`ut run test\`) so it matches the root \`test\` script and the rest of the repo guidance. - .github/copilot-instructions.md: site/ is on VitePress (per site/package.json), not Dumi. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/copilot-instructions.md | 2 +- tegg/CLAUDE.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 78b1d17ef9..9a5d44aacf 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -48,7 +48,7 @@ ut run lint ### Supporting Directories - **`examples/`** - Two example apps: `helloworld-commonjs` and `helloworld-typescript` (currently have runtime issues) -- **`site/`** - Documentation website built with Dumi +- **`site/`** - Documentation website built with VitePress ## Essential Commands and Timing diff --git a/tegg/CLAUDE.md b/tegg/CLAUDE.md index 7ab65f9c9b..78a27ca2cd 100644 --- a/tegg/CLAUDE.md +++ b/tegg/CLAUDE.md @@ -69,7 +69,7 @@ ut run clean-dist # Clean all build artifacts including tegg (removes d All tegg packages use **Vitest** for testing and are integrated with the main Egg.js monorepo test suite. ```bash -ut test # Run vitest tests for all packages (from monorepo root) +ut run test # Run vitest tests for all packages (from monorepo root) ut run test:cov # Run tests with coverage ut run ci # Full CI: vitest with coverage and bail on first failure ``` From 5f8b4c335f88a8ec1576176e0950f31eb029e9fd Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 20:32:21 +0800 Subject: [PATCH 11/15] fix(ci): move pnpm setup after \`ut install\` to avoid SIGPIPE \`pnpm/action-setup\` exports PNPM_HOME, which makes \`ut install --from pnpm\` read pnpm's config and crash with exit code 141 (SIGPIPE) right after the workspace summary is printed. Moving the pnpm setup step until after \`ut install\` / \`ut run build\` keeps PNPM_HOME out of utoo's environment, while still having pnpm available for the pack step that follows. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/e2e-test.yml | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 5d2ba87620..4a44888197 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -144,17 +144,6 @@ jobs: - name: Install utoo uses: utooland/setup-utoo@3a51006d0b66afcc32d1b9177a4b200b74f4a8cb # main - - name: Install pnpm (for `pnpm -r pack`) - # utoo's `ut pm-pack` does not resolve `workspace:` / `catalog:` - # protocols inside the packed manifests, so downstream `npm install` - # in the ecosystem-ci projects fails with EUNSUPPORTEDPROTOCOL. - # Keep pnpm available just for the pack step. The explicit `version` - # is required because `packageManager` in package.json now points at - # utoo, so the action can't infer the pnpm version itself. - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 - with: - version: 10 - - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 with: @@ -166,6 +155,20 @@ jobs: - name: Build all packages run: ut run build + - name: Install pnpm (for `pnpm -r pack`) + # utoo's `ut pm-pack` does not resolve `workspace:` / `catalog:` + # protocols inside the packed manifests, so downstream `npm install` + # in the ecosystem-ci projects fails with EUNSUPPORTEDPROTOCOL. + # Keep pnpm available just for the pack step. The explicit `version` + # is required because `packageManager` in package.json now points at + # utoo, so the action can't infer the pnpm version itself. + # Setup must come AFTER `ut install`: action-setup exports PNPM_HOME, + # which makes utoo's install path read pnpm config and crash with + # exit 141 (SIGPIPE). + uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4 + with: + version: 10 + - name: Pack packages into tgz # `pnpm -r pack` resolves workspace:/catalog: deps in the emitted # manifests, which `ut pm-pack` does not yet do. pnpm refuses to From 842a307dddfa5c360298115c5d2c0fd0942849a0 Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 20:43:35 +0800 Subject: [PATCH 12/15] ci: retry \`ut install\` up to 3 times for transient SIGPIPE (141) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit \`ut install --from pnpm\` intermittently exits with 141 (SIGPIPE) right after printing the workspace summary — observed on typecheck and on cnpmcore E2E in the same workflow run while other ubuntu jobs (\`Test bin\`, \`Test scripts\`, \`Test\`) using the identical command succeed. Wrap every install invocation in a 3-attempt retry with a 5s / 10s backoff so the workflow absorbs the flake while the upstream utoo bug is investigated. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci.yml | 9 +++++---- .github/workflows/e2e-test.yml | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 863000fbc6..0fb13e46f0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,8 @@ jobs: node-version: '24' - name: Install dependencies - run: ut install --from pnpm + # Retry to absorb transient `exit 141` (SIGPIPE) from `ut install`. + run: ut install --from pnpm || (sleep 5 && ut install --from pnpm) || (sleep 10 && ut install --from pnpm) - name: Run lint run: ut run lint @@ -160,7 +161,7 @@ jobs: node-version: ${{ matrix.node }} - name: Install dependencies - run: ut install --from pnpm + run: ut install --from pnpm || (sleep 5 && ut install --from pnpm) || (sleep 10 && ut install --from pnpm) - name: Run tests run: ut run ci @@ -204,7 +205,7 @@ jobs: node-version: ${{ matrix.node }} - name: Install dependencies - run: ut install --from pnpm + run: ut install --from pnpm || (sleep 5 && ut install --from pnpm) || (sleep 10 && ut install --from pnpm) - name: Run tests run: | @@ -245,7 +246,7 @@ jobs: node-version: ${{ matrix.node }} - name: Install dependencies - run: ut install --from pnpm + run: ut install --from pnpm || (sleep 5 && ut install --from pnpm) || (sleep 10 && ut install --from pnpm) - name: Run tests run: | diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 4a44888197..a156d24ea7 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -150,7 +150,7 @@ jobs: node-version: ${{ matrix.project.node-version }} - name: Install dependencies - run: ut install --from pnpm + run: ut install --from pnpm || (sleep 5 && ut install --from pnpm) || (sleep 10 && ut install --from pnpm) - name: Build all packages run: ut run build From c5221972206693b3cfd44b75bfb3350d936a986b Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 20:47:50 +0800 Subject: [PATCH 13/15] fix(ci): use correct env name for pnpm packageManager strict bypass The previous env var \`PNPM_PACKAGE_MANAGER_STRICT\` is not recognized by pnpm, so pnpm kept refusing the pack step with \`This project is configured to use utoo\`. The actual setting is \`package-manager-strict\`, exposed via \`NPM_CONFIG_PACKAGE_MANAGER_STRICT\`. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/e2e-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index a156d24ea7..944120404a 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -175,7 +175,7 @@ jobs: # run when `packageManager` points at another tool, so disable # that strict check for just this step. env: - PNPM_PACKAGE_MANAGER_STRICT: 'false' + NPM_CONFIG_PACKAGE_MANAGER_STRICT: 'false' run: pnpm -r pack - name: Override dependencies from tgz in ${{ matrix.project.name }} From 5c856b3ab3d5661ef52fe8d0f4ce7ac89fc2d169 Mon Sep 17 00:00:00 2001 From: killagu Date: Tue, 2 Jun 2026 20:51:45 +0800 Subject: [PATCH 14/15] fix(ci): run \`pnpm install\` before \`pnpm -r pack\` so workspace deps resolve MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit \`pnpm -r pack\` needs pnpm's own \`node_modules\` symlink layout to resolve \`workspace:*\` versions; otherwise it errors with \`ERR_PNPM_CANNOT_RESOLVE_WORKSPACE_PROTOCOL\`. Run \`pnpm install --no-frozen-lockfile --ignore-scripts\` first — the packages are already in the global utoo store, so this is cheap. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/e2e-test.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 944120404a..d695ab53a6 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -173,10 +173,15 @@ jobs: # `pnpm -r pack` resolves workspace:/catalog: deps in the emitted # manifests, which `ut pm-pack` does not yet do. pnpm refuses to # run when `packageManager` points at another tool, so disable - # that strict check for just this step. + # that strict check for just this step. pnpm needs its own + # node_modules layout to resolve `workspace:` versions, so run + # `pnpm install --no-frozen-lockfile` first (cheap on top of the + # ut install since the deps are already in the global store). env: NPM_CONFIG_PACKAGE_MANAGER_STRICT: 'false' - run: pnpm -r pack + run: | + pnpm install --no-frozen-lockfile --ignore-scripts + pnpm -r pack - name: Override dependencies from tgz in ${{ matrix.project.name }} working-directory: ecosystem-ci/${{ matrix.project.name }} From 2a5ba8621904dec6b0c9b31f2eb75ee64c0b1142 Mon Sep 17 00:00:00 2001 From: killagu Date: Thu, 4 Jun 2026 10:48:32 +0800 Subject: [PATCH 15/15] =?UTF-8?q?perf(ci):=20shard=20tests=20for=20?= =?UTF-8?q?=E2=89=A460s=20per=20ubuntu=20job;=20PR=20runs=20ubuntu-only=20?= =?UTF-8?q?fast=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cut the monolithic test job (single ~190s vitest run, gated by a 170s cluster file; 12-29min on CI) into parallel, wall-time-balanced shards so every job on the PR critical path stays ≤60s — verified on real CI (48 ubuntu shards run 15-59s). PR critical path = ubuntu only: - Test sharding (scripts/run-shard.js, driven by the CI matrix): fork-heavy packages split via vitest --shard (cluster→3, egg→2, mock→2, schedule→4, security→2, plus redis/multipart/development standalone), each capped with --maxWorkers so forked egg cluster processes don't oversubscribe the CPU; the light remainder greedy bin-packed by per-dir cpu weight into 8 rest-* shards. - Long single test files split by `describe` block (no semantic change, no removed cases) so vitest can parallelize them. - quality split into a parallel matrix (lint/typecheck/fmtcheck/build/site) so the slowest check — not their sum — bounds wall time. - egg-bin runs without --coverage to stay ≤60s (no threshold; report only). macOS/Windows whole-suite compatibility (slow: ~13-25min; macOS has only ~5 runner slots) moved to a `test-compat` job that runs at merge time (merge_group) and on push to next — NOT on pull_request — so it no longer gates the PR wall while still enforcing cross-platform coverage before code lands. CI test jobs on a PR drop from 132 to the 48 ubuntu shards. Latent bugs fixed along the way: - tegg controller ControllerMetaManager.test.ts triggers a duplicate-proto error that polluted the process-global registry under isolate:false, failing sibling files; isolated that project (isolate:true). - clean-dist used `ut run clean --workspaces` which aborts the && chain (root has no clean script) → scripts/clean-dist.js. - typecheck/pretest used `ut run --workspaces`, which includes the root and recurses infinitely → scripts/run-workspaces.js (concurrent, root-bin PATH). - Windows runner images no longer set %HOME%, breaking egg_loader getHomedir; export HOME=%USERPROFILE% on the windows compat job. Windows flakes absorbed by --retry. No test semantics changed or cases removed. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 197 ++++++-- .gitignore | 5 + AGENTS.md | 41 +- package.json | 10 +- .../cluster/test/agent_custom_logger.test.ts | 28 ++ packages/cluster/test/agent_worker.test.ts | 181 ------- .../test/agent_worker_boot_error.test.ts | 33 ++ .../test/agent_worker_forkapp_error.test.ts | 40 ++ .../test/agent_worker_framework_error.test.ts | 33 ++ .../cluster/test/agent_worker_skipped.test.ts | 75 +++ .../cluster/test/agent_worker_spawn.test.ts | 26 + packages/cluster/test/app_worker.test.ts | 369 +-------------- .../test/app_worker_eaddrinuse.test.ts | 35 ++ packages/cluster/test/app_worker_env.test.ts | 104 ++++ .../cluster/test/app_worker_error.test.ts | 98 ++++ .../cluster/test/app_worker_listen.test.ts | 139 ++++++ .../cluster/test/app_worker_refork.test.ts | 54 +++ packages/cluster/test/https.test.ts | 22 - packages/cluster/test/https_config.test.ts | 37 ++ .../cluster/test/master/before-close.test.ts | 27 ++ packages/cluster/test/master/others.test.ts | 448 +----------------- .../test/master/others_skipped.test.ts | 418 ++++++++++++++++ packages/cluster/test/master/sticky.test.ts | 27 ++ .../lib/plugins/watcher-type-default.test.ts | 27 ++ packages/egg/test/lib/plugins/watcher.test.ts | 20 +- plugins/development/test/override.test.ts | 35 +- .../development/test/override_ignore.test.ts | 42 ++ plugins/mock/test/cluster.test.ts | 351 +------------- plugins/mock/test/cluster_cache.test.ts | 56 +++ plugins/mock/test/cluster_custom_port.test.ts | 30 ++ plugins/mock/test/cluster_eggpath.test.ts | 29 ++ plugins/mock/test/cluster_skipped.test.ts | 195 ++++++++ plugins/mock/test/cluster_workers.test.ts | 30 ++ plugins/mock/test/cluster_yadan.test.ts | 25 + .../schedule/test/immediate-onlyonce.test.ts | 28 ++ plugins/schedule/test/immediate.test.ts | 22 - .../schedule-type-worker-cronoptions.test.ts | 26 + .../schedule-type-worker-ctxstorage.test.ts | 33 ++ .../test/schedule-type-worker1.test.ts | 47 -- ...ription-enable-fast-context-logger.test.ts | 31 ++ .../test/subscription-generator.test.ts | 25 + plugins/schedule/test/subscription.test.ts | 44 -- scripts/clean-dist.js | 59 +++ scripts/run-shard.js | 205 ++++++++ scripts/run-workspaces.js | 130 +++++ tegg/plugin/controller/vitest.config.ts | 16 + 46 files changed, 2400 insertions(+), 1553 deletions(-) create mode 100644 packages/cluster/test/agent_custom_logger.test.ts delete mode 100644 packages/cluster/test/agent_worker.test.ts create mode 100644 packages/cluster/test/agent_worker_boot_error.test.ts create mode 100644 packages/cluster/test/agent_worker_forkapp_error.test.ts create mode 100644 packages/cluster/test/agent_worker_framework_error.test.ts create mode 100644 packages/cluster/test/agent_worker_skipped.test.ts create mode 100644 packages/cluster/test/agent_worker_spawn.test.ts create mode 100644 packages/cluster/test/app_worker_eaddrinuse.test.ts create mode 100644 packages/cluster/test/app_worker_env.test.ts create mode 100644 packages/cluster/test/app_worker_error.test.ts create mode 100644 packages/cluster/test/app_worker_listen.test.ts create mode 100644 packages/cluster/test/app_worker_refork.test.ts create mode 100644 packages/cluster/test/https_config.test.ts create mode 100644 packages/cluster/test/master/before-close.test.ts create mode 100644 packages/cluster/test/master/others_skipped.test.ts create mode 100644 packages/cluster/test/master/sticky.test.ts create mode 100644 packages/egg/test/lib/plugins/watcher-type-default.test.ts create mode 100644 plugins/development/test/override_ignore.test.ts create mode 100644 plugins/mock/test/cluster_cache.test.ts create mode 100644 plugins/mock/test/cluster_custom_port.test.ts create mode 100644 plugins/mock/test/cluster_eggpath.test.ts create mode 100644 plugins/mock/test/cluster_skipped.test.ts create mode 100644 plugins/mock/test/cluster_workers.test.ts create mode 100644 plugins/mock/test/cluster_yadan.test.ts create mode 100644 plugins/schedule/test/immediate-onlyonce.test.ts create mode 100644 plugins/schedule/test/schedule-type-worker-cronoptions.test.ts create mode 100644 plugins/schedule/test/schedule-type-worker-ctxstorage.test.ts create mode 100644 plugins/schedule/test/subscription-enable-fast-context-logger.test.ts create mode 100644 plugins/schedule/test/subscription-generator.test.ts create mode 100644 scripts/clean-dist.js create mode 100644 scripts/run-shard.js create mode 100644 scripts/run-workspaces.js create mode 100644 tegg/plugin/controller/vitest.config.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0fb13e46f0..bdfea3f22c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,11 +18,20 @@ permissions: actions: write jobs: - typecheck: + # Static-analysis / build checks. Each check runs as its own parallel job + # (instead of serial steps) so the slowest one — not their sum — bounds the + # wall time. Goal: keep each ≤ 60s. + quality: + strategy: + fail-fast: false + matrix: + check: ['lint', 'typecheck', 'fmtcheck', 'build', 'site'] + + name: Quality (${{ matrix.check }}) runs-on: ubuntu-latest concurrency: - group: typecheck-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }} + group: quality-${{ matrix.check }}-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }} cancel-in-progress: true steps: - name: Checkout repository @@ -41,40 +50,151 @@ jobs: run: ut install --from pnpm || (sleep 5 && ut install --from pnpm) || (sleep 10 && ut install --from pnpm) - name: Run lint + if: ${{ matrix.check == 'lint' }} run: ut run lint - name: Run typecheck + if: ${{ matrix.check == 'typecheck' }} run: ut run typecheck - name: Run format check + if: ${{ matrix.check == 'fmtcheck' }} run: ut run fmtcheck - name: Run build + if: ${{ matrix.check == 'build' }} run: ut run build - name: Run site build + if: ${{ matrix.check == 'site' }} run: ut run site:build test: strategy: fail-fast: false matrix: - os: ['ubuntu-latest', 'macos-latest', 'windows-latest'] + # ubuntu-latest runs the fine-grained shards: fork-heavy packages are + # split into vitest --shard slices and the light remainder into + # weight-balanced rest-* shards (see scripts/run-shard.js). Sized so each + # shard's `vitest run` step stays ≤ ~60s on ubuntu-latest, where runner + # concurrency is high enough to run them all in parallel. + os: ['ubuntu-latest'] node: ['22', '24'] + shard: + - cluster-1 + - cluster-2 + - cluster-3 + - egg-1 + - egg-2 + - mock-1 + - mock-2 + - schedule-1 + - schedule-2 + - schedule-3 + - schedule-4 + - development + - security-1 + - security-2 + - redis + - multipart + - rest-1 + - rest-2 + - rest-3 + - rest-4 + - rest-5 + - rest-6 + - rest-7 + - rest-8 + # macOS/Windows whole-suite compatibility runs live in `test-compat`, + # which only runs at merge time (merge_group / push to next) — not on + # every PR — because those runners are slow (~13-25min whole-suite) and + # macOS has only ~5 concurrent slots, so they would dominate the PR wall. + # The PR critical path is this ubuntu fan-out, every shard ≤60s. + + name: Test (${{ matrix.os }}, ${{ matrix.node }}, ${{ matrix.shard }}) + runs-on: ${{ matrix.os }} + + concurrency: + group: test-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}-(${{ matrix.os }}, ${{ matrix.node }}, ${{ matrix.shard }}) + cancel-in-progress: true + + steps: + - name: Checkout repository + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 + + - name: Start Redis + uses: shogo82148/actions-setup-redis@cff708d63a30aebc0bfaa7276fb709d173f36cb6 # v1 + with: + redis-version: '7' + auto-start: 'true' - name: Test (${{ matrix.os }}, ${{ matrix.node }}) + - name: Start MySQL + uses: shogo82148/actions-setup-mysql@27e74fac04c136a9f4c2dc2ed457df57331b3e0c # v1 + with: + mysql-version: '8' + auto-start: 'true' + - name: Init DB + run: | + mysql -uroot -e "CREATE DATABASE IF NOT EXISTS test;" + + - name: Setup utoo + uses: utooland/setup-utoo@3a51006d0b66afcc32d1b9177a4b200b74f4a8cb # main + + - name: Set up Node.js + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version: ${{ matrix.node }} + + - name: Install dependencies + run: ut install --from pnpm || (sleep 5 && ut install --from pnpm) || (sleep 10 && ut install --from pnpm) + + - name: Prepare test fixtures (clean dist + db) + # Mirrors the original `preci` (pretest) step: clears stale dist so tegg + # plugin tests don't double-load src+dist, and runs per-workspace + # pretest (e.g. orm DB table init). The shard runner invokes vitest + # directly, bypassing the npm `preci` lifecycle, so do it explicitly. + run: ut run pretest + + - name: Run tests (shard ${{ matrix.shard }}) + run: node scripts/run-shard.js ${{ matrix.shard }} -- --coverage + + - name: Run example tests + # Run once (on the rest-1 shard) to avoid duplication across shards. + if: ${{ matrix.shard == 'rest-1' }} + run: | + ut run example:test:all + + - name: Code Coverage + uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5 + with: + use_oidc: true + + # macOS / Windows whole-suite compatibility runs. These are slow (~13-25min) + # and macOS has only ~5 concurrent runner slots, so they would dominate the + # PR wall. They run only at merge time (merge_group) and on push to next, so + # the PR critical path stays the ubuntu `test` fan-out (each shard ≤60s) while + # cross-platform coverage is still enforced before code lands. + test-compat: + if: ${{ github.event_name != 'pull_request' }} + strategy: + fail-fast: false + matrix: + os: ['macos-latest', 'windows-latest'] + node: ['22', '24'] + + name: Test compat (${{ matrix.os }}, ${{ matrix.node }}) runs-on: ${{ matrix.os }} concurrency: - group: test-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}-(${{ matrix.os }}, ${{ matrix.node }}) + group: test-compat-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}-(${{ matrix.os }}, ${{ matrix.node }}) cancel-in-progress: true steps: - name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - - name: Start Redis (MacOS or Linux) - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'ubuntu-latest' }} + - name: Start Redis (macOS) + if: ${{ matrix.os == 'macos-latest' }} uses: shogo82148/actions-setup-redis@cff708d63a30aebc0bfaa7276fb709d173f36cb6 # v1 with: redis-version: '7' @@ -130,15 +250,14 @@ jobs: Write-Host "Memurai is ready on 127.0.0.1:6379" - # install and start MySQL (will automatically start mysqld) - - name: Start MySQL (macOS or Linux) - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'ubuntu-latest' }} + - name: Start MySQL (macOS) + if: ${{ matrix.os == 'macos-latest' }} uses: shogo82148/actions-setup-mysql@27e74fac04c136a9f4c2dc2ed457df57331b3e0c # v1 with: mysql-version: '8' auto-start: 'true' - - name: Init DB (macOS or Linux) - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'ubuntu-latest' }} + - name: Init DB (macOS) + if: ${{ matrix.os == 'macos-latest' }} run: | mysql -uroot -e "CREATE DATABASE IF NOT EXISTS test;" @@ -148,8 +267,6 @@ jobs: run: | choco install -y mysql refreshenv - # MySQL default root has no password, set a password and create database/user - # & mysqladmin -u root password root & mysql -uroot -e "CREATE DATABASE IF NOT EXISTS test;" - name: Setup utoo @@ -163,26 +280,29 @@ jobs: - name: Install dependencies run: ut install --from pnpm || (sleep 5 && ut install --from pnpm) || (sleep 10 && ut install --from pnpm) - - name: Run tests - run: ut run ci + - name: Prepare test fixtures (clean dist + db) + run: ut run pretest - - name: Run example tests - if: ${{ matrix.os != 'windows-latest' }} - run: | - ut run example:test:all + - name: Set HOME on Windows + if: ${{ matrix.os == 'windows-latest' }} + shell: pwsh + run: echo "HOME=$env:USERPROFILE" >> $env:GITHUB_ENV - - name: Code Coverage - # skip on windows, it will hangup on codecov - if: ${{ matrix.os != 'windows-latest' }} - uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5 - with: - use_oidc: true + - name: Run tests (whole suite) + run: node scripts/run-shard.js all -- --coverage + + - name: Run egg-bin tests + # egg-bin has its own vitest project (built first); cover it on + # macos/windows here so the PR-fast egg-bin job can stay ubuntu-only. + run: | + ut run build -- --workspace ./tools/egg-bin + ut run test --workspace @eggjs/bin test-egg-bin: strategy: fail-fast: false matrix: - os: ['ubuntu-latest', 'windows-latest'] + os: ['ubuntu-latest'] node: ['24'] name: Test bin (${{ matrix.os }}, ${{ matrix.node }}) @@ -207,17 +327,19 @@ jobs: - name: Install dependencies run: ut install --from pnpm || (sleep 5 && ut install --from pnpm) || (sleep 10 && ut install --from pnpm) + - name: Set HOME on Windows + if: ${{ matrix.os == 'windows-latest' }} + shell: pwsh + run: echo "HOME=$env:USERPROFILE" >> $env:GITHUB_ENV + - name: Run tests + # `ci` (vitest --coverage) adds ~50s of instrumentation on egg-bin's + # fork-heavy suite, pushing it past 60s. Run without coverage (`test`) + # to keep the job ≤60s; egg-bin's fork tests can't be sharded (they + # depend on cross-file shared state under isolate:false). run: | ut run build -- --workspace ./tools/egg-bin - ut run ci --workspace @eggjs/bin - - - name: Code Coverage - # skip on windows, it will hangup on codecov https://github.com/codecov/codecov-action/issues/1787 - if: ${{ matrix.os != 'windows-latest' }} - uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5 - with: - use_oidc: true + ut run test --workspace @eggjs/bin test-egg-scripts: strategy: @@ -263,9 +385,12 @@ jobs: runs-on: ubuntu-latest needs: - test + - test-compat - test-egg-bin - test-egg-scripts - - typecheck + - quality steps: - run: exit 1 + # test-compat is skipped on pull_request (result 'skipped'), which does + # not trip this gate — only real failures/cancellations do. if: ${{ always() && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) }} diff --git a/.gitignore b/.gitignore index b89f7ba95d..c35799ca6e 100644 --- a/.gitignore +++ b/.gitignore @@ -120,3 +120,8 @@ ecosystem-ci/examples pnpm-lock.yaml .utoo.toml .claude/ + +# benchmark output directories +benchmark/ci-test/baseline* +benchmark/ci-test/run* +benchmark/ci-test/2* diff --git a/AGENTS.md b/AGENTS.md index 36c6548c9c..263f84b18a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -28,9 +28,15 @@ Egg is maintained as a utoo monorepo. ### Local CI -Run tests **without building first**. The CI workflow (`ut install → ut run ci`) never runs `build` before tests. If `dist/` directories exist from a prior build, tegg plugin tests will fail with `duplicate proto` errors because globby scans both `src/*.ts` and `dist/*.js`, loading the same decorated class twice. +Run tests **without building first**. The CI test jobs run `ut run pretest` +(clean dist + per-workspace pretest) then a vitest shard; they never `build` +before tests. If `dist/` directories exist from a prior build, tegg plugin tests +will fail with `duplicate proto` errors because globby scans both `src/*.ts` and +`dist/*.js`, loading the same decorated class twice. `scripts/clean-dist.js` +(run by `ut run clean-dist`) removes every `dist/` for you. -When you see `duplicate proto` failures locally: +When you see `duplicate proto` failures locally, run `ut run clean-dist` (or the +equivalent find below) and re-run: ```bash find tegg packages plugins tools -name dist -type d \ @@ -38,8 +44,39 @@ find tegg packages plugins tools -name dist -type d \ -exec rm -rf {} + ``` +### Aggregator scripts (avoid `ut run --workspaces` recursion) + +The root `typecheck` / `pretest` aggregate per-workspace scripts via +`node scripts/run-workspaces.js