Skip to content

Conversation

@fengmk2
Copy link
Member

@fengmk2 fengmk2 commented Dec 20, 2025

Summary by CodeRabbit

  • New Features

    • Added an end-to-end test workflow and a reusable clone action for multi-project runs.
    • Added tooling to discover, pack, and patch local workspace packages for test scenarios.
  • Chores

    • Exposed README in packaged files and adjusted dev dependency declarations.
    • Updated ignore rules to exclude packaged artifacts and ecosystem directories.
    • Simplified plugin dependencies and adjusted build tooling externals.
  • Tests

    • Skip one timing-sensitive test on Windows to improve CI stability.

✏️ Tip: You can customize this high-level summary in your review settings.

@fengmk2 fengmk2 requested a review from Copilot December 20, 2025 18:10
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 20, 2025

Caution

Review failed

The pull request is closed.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds ecosystem CI tooling: a composite GitHub Action to checkout projects, a matrix E2E workflow, repo metadata and TypeScript utilities to clone/sync repositories and patch package.json overrides, plus related .gitignore and package configuration updates.

Changes

Cohort / File(s) Summary
GitHub Actions (workflow + action)
.github/actions/clone/action.yml, .github/workflows/e2e-test.yml
New composite action that reads ecosystem-ci/repo.json and conditionally sets outputs and checks out the specified repo/ref; new matrix E2E workflow that uses the action, installs/builds/packs packages, patches dependencies, and runs project-specific commands for cnpmcore and examples.
Ecosystem CI utilities & config
ecosystem-ci/repo.json, ecosystem-ci/clone.ts, ecosystem-ci/patch-project.ts, ecosystem-ci/.gitignore
Adds repo.json mapping projects→repo/branch/hash; clone.ts to clone/sync and validate remotes/hashes; patch-project.ts to produce file: tgz overrides and patch target project package.json files; adds ignore patterns for ecosystem dirs.
Repo ignores & packaging
.gitignore, pnpm-workspace.yaml, package.json
Adds *.tgz to root .gitignore; tightens @types/js-yaml version in pnpm-workspace.yaml; adds files entry and a devDependency entry for @types/js-yaml in root package.json.
Plugin and build config
tegg/plugin/ajv/package.json, tsdown.config.ts
Removes egg dependency/peerDependency from plugin package.json; disables dts generation (commented) and adds external patterns in tsdown.config.ts.
Tests
plugins/schedule/test/immediate.test.ts
Wraps a describe block with a Windows guard to skip on Win32 (describe.skipIf(process.platform === 'win32')).

Sequence Diagram(s)

sequenceDiagram
    participant WF as GitHub Workflow
    participant Action as Clone Composite Action
    participant RepoJSON as ecosystem-ci/repo.json
    participant Checkout as actions/checkout
    participant Runner as Workflow Runner

    WF->>Action: run with input ecosystem-ci-project
    Action->>RepoJSON: read mapping for project
    RepoJSON-->>Action: return repo URL, branch, commit
    Action->>Action: set outputs (PROJECT_HASH, PROJECT_REPOSITORY)
    Action->>Checkout: actions/checkout with repository + ref
    Checkout->>Runner: place files under ecosystem-ci/<project>
    Runner-->>WF: workflow continues using checked-out project dir
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Inspect git URL normalization, fetch/checkout error handling, and logging in ecosystem-ci/clone.ts.
  • Verify override file:tgz path generation and safe merging in ecosystem-ci/patch-project.ts.
  • Confirm composite action conditional logic and workflow matrix paths/commands in .github/actions/clone/action.yml and .github/workflows/e2e-test.yml.

Poem

🐰 I hopped through repo.json and trees,
Cloned branches quick with nimble ease,
Packed tarballs, patched each name,
E2E hops now join the game —
Rabbity cheers — CI please! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'test: add e2e tests' accurately summarizes the main change—introducing E2E testing infrastructure with workflows, GitHub Actions, and ecosystem CI setup.

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7295bed and 1654355.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • ecosystem-ci/patch-project.ts (1 hunks)

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
Contributor

Summary of Changes

Hello @fengmk2, 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 establishes the foundational infrastructure for end-to-end testing across an ecosystem of projects. It introduces a mechanism to programmatically clone specific versions of dependent repositories and then patch their package.json files to consume locally built @eggjs packages. This setup is crucial for ensuring compatibility and stability within the larger project ecosystem by enabling isolated and reproducible testing environments.

Highlights

  • Ecosystem CI Setup: Introduced a new ecosystem-ci directory containing scripts and configuration for managing and testing related projects.
  • Repository Cloning Action: Added a GitHub Action (.github/actions/clone/action.yml) to facilitate cloning specific ecosystem repositories at designated commit hashes.
  • Local Dependency Patching: Implemented a script (ecosystem-ci/patch-project.ts) to dynamically update project package.json files, replacing @eggjs package dependencies with local .tgz paths for integrated testing.
  • Project Configuration: Defined cnpmcore as the initial ecosystem project in ecosystem-ci/repo.json, specifying its repository, branch, and a fixed commit hash.
  • Git Ignore Updates: Updated .gitignore to exclude .tgz files and added a specific .gitignore for the ecosystem-ci directory.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/e2e-test.yml
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.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 20, 2025

Deploying egg with  Cloudflare Pages  Cloudflare Pages

Latest commit: 161b853
Status: ✅  Deploy successful!
Preview URL: https://0442d2df.egg-cci.pages.dev
Branch Preview URL: https://e2e.egg-cci.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 20, 2025

Deploying egg-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1654355
Status:⚡️  Build in progress...

View logs

Copy link
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 introduces end-to-end tests for the ecosystem, which is a great addition for ensuring stability and compatibility. The implementation includes new GitHub Actions and helper scripts for cloning and patching test projects. I've identified a few areas for improvement, including a potential security vulnerability, a significant maintainability concern with a hardcoded list, and some opportunities for code refinement. My detailed feedback is provided in the comments below.

Copy link
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

This PR adds an ecosystem-ci infrastructure for end-to-end testing of the Eggjs framework against downstream projects. It enables automated testing to ensure changes to the framework don't break dependent projects.

Key changes:

  • Adds ecosystem-ci scripts for cloning and patching downstream repositories
  • Implements a GitHub Actions workflow for automated E2E testing against cnpmcore
  • Configures testing infrastructure with repository definitions and package management

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
ecosystem-ci/repo.json Defines downstream repositories for E2E testing (cnpmcore)
ecosystem-ci/clone.ts Implements git repository cloning and checkout logic with validation
ecosystem-ci/patch-project.ts Patches downstream projects to use local .tgz packages for testing
ecosystem-ci/.gitignore Excludes cloned repositories from version control
.gitignore Adds .tgz files to global ignore list
.github/workflows/e2e-test.yml Defines E2E test workflow that runs on next branch
.github/actions/clone/action.yml Reusable composite action for cloning ecosystem-ci repositories

Base automatically changed from tsdown-workspace to next December 21, 2025 03:04
@codecov
Copy link

codecov bot commented Dec 21, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.61%. Comparing base (1cedb32) to head (1654355).
⚠️ Report is 5 commits behind head on next.

Additional details and impacted files
@@           Coverage Diff           @@
##             next    #5739   +/-   ##
=======================================
  Coverage   87.60%   87.61%           
=======================================
  Files         563      563           
  Lines       10930    10930           
  Branches     1238     1238           
=======================================
+ Hits         9575     9576    +1     
+ Misses       1271     1270    -1     
  Partials       84       84           

☔ 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.

@socket-security
Copy link

socket-security bot commented Dec 21, 2025

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

fengmk2 and others added 6 commits December 21, 2025 12:58
…s.glob

Replace hardcoded packages array with dynamic discovery based on
pnpm-workspace.yaml patterns. This ensures newly added packages
are automatically included in E2E testing without manual updates.

- Parse pnpm-workspace.yaml to get workspace patterns
- Use Node.js native glob API to find all package.json files
- Skip private packages automatically
- Add @types/js-yaml for TypeScript type support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Co-authored-by: Copilot <[email protected]>
Signed-off-by: MK (fengmk2) <[email protected]>
@fengmk2 fengmk2 marked this pull request as ready for review December 21, 2025 07:59
Copilot AI review requested due to automatic review settings December 21, 2025 07:59
Copy link
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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tsdown.config.ts (1)

1-33: Use a typed intermediate variable for the config export.

Per coding guidelines, tsdown configuration files must use typed intermediate variables with explicit type annotations rather than exporting the config directly.

🔎 Proposed refactor to add typed intermediate variable
 import { defineConfig } from 'tsdown';
+import type { Options } from 'tsdown';
 
-export default defineConfig({
+const config: Options = {
   // Workspace configuration - builds all library packages from root
   workspace: {
     include: ['packages/*', 'plugins/*', 'tools/*', 'tegg/core/*', 'tegg/plugin/*', 'tegg/standalone/*'],
     // FIXME: auto mode is not working, rolldown was hang and cpu 400% when using auto mode
     // include: 'auto',
     exclude: [
       'packages/tsconfig', // Config-only package, no src to build
     ],
   },
 
   // Shared defaults
   unbundle: true,
   unused: {
     level: 'error',
   },
   // dts: true,
   exports: {
     devExports: true,
   },
   fixedExtension: false,
   publint: {
     level: 'suggestion',
     strict: true,
   },
 
   // Default entry pattern - glob to include all source files
   entry: 'src/**/*.ts',
   skipNodeModulesBundle: true,
   external: [/^@eggjs\//, 'egg'],
-});
+};
+
+export default defineConfig(config);

Based on coding guidelines, configuration files for tools (tsdown, vitest) must use typed intermediate variables with explicit type annotations.

♻️ Duplicate comments (9)
.github/workflows/e2e-test.yml (3)

15-17: The cancel-in-progress setting is always true.

The workflow only triggers on the next branch (lines 6, 11), so the cancel-in-progress: true setting will always apply to all workflow runs. This is acceptable if you want to cancel in-progress runs when new commits are pushed to PRs targeting next. However, the previous review comment suggested making this conditional based on github.ref_name != 'next', which would never be true for this workflow.

If the current behavior is intentional, no change is needed. Otherwise, clarify the intended cancellation policy.


84-87: Step name could be more descriptive.

The step "Override dependencies from tgz" accurately describes the operation being performed. However, a previous review suggested clarifying that this patches all eggjs packages. The current name is acceptable but could be more explicit.


89-91: Document the intentional use of npm in ecosystem projects.

The workflow uses npm commands to run tests in the ecosystem-ci projects (line 91), while the main repository uses pnpm. This is intentional to test compatibility with npm-based downstream consumers. As noted in a previous review, consider adding a comment to document this rationale.

ecosystem-ci/patch-project.ts (3)

76-87: Refactor duplicated dependency patching logic.

The logic for patching dependencies (lines 76-81) and devDependencies (lines 82-87) is identical. This duplication can be eliminated by iterating over both dependency types.

🔎 Eliminate duplication
+  const depTypes = ['dependencies', 'devDependencies'] as const;
+  for (const depType of depTypes) {
+    const deps = packageJson[depType];
+    if (!deps) continue;
+    for (const name in deps) {
+      const override = overrides[name];
+      if (override) {
+        deps[name] = override;
+      }
+    }
+  }
-  for (const name in packageJson.dependencies) {
-    const override = overrides[name];
-    if (override) {
-      packageJson.dependencies[name] = override;
-    }
-  }
-  for (const name in packageJson.devDependencies) {
-    const override = overrides[name];
-    if (override) {
-      packageJson.devDependencies[name] = override;
-    }
-  }

17-20: Use consistent error message terminology.

Line 18 says the project "is not defined in repo.json" while line 120 says it "is not supported". For consistency and clarity, both should use the same phrasing.

🔎 Make error messages consistent
     default:
-      console.error(`Project ${project} is not supported`);
+      console.error(`Project ${project} is not defined in repo.json`);
       process.exit(1);

Also applies to: 119-121


55-66: Add error handling for package.json reads.

The JSON.parse call at line 60 can throw if a package.json file is malformed or missing the version field. This would crash the entire patching process rather than providing a useful error message identifying which package caused the issue.

🔎 Add try-catch with descriptive error
 async function buildOverrides(): Promise<Record<string, string>> {
   const packages = await discoverPackages();
   const overrides: Record<string, string> = {};
 
   for (const [name, path] of packages) {
-    const version = JSON.parse(fs.readFileSync(join(tgzPath, path, 'package.json'), 'utf8')).version;
+    try {
+      const pkgJson = JSON.parse(fs.readFileSync(join(tgzPath, path, 'package.json'), 'utf8'));
+      if (!pkgJson.version) {
+        console.warn(`Warning: Package ${name} at ${path} has no version field, skipping`);
+        continue;
+      }
+      const version = pkgJson.version;
+    } catch (error) {
+      console.error(`Error reading package.json for ${name} at ${path}:`, error.message);
+      throw error;
+    }
     const filename = `${name.replace('@', '').replace('/', '-')}-${version}.tgz`;
     overrides[name] = `file:${tgzPath}/${filename}`;
   }
 
   return overrides;
 }
ecosystem-ci/clone.ts (2)

76-76: Handle null currentHash more gracefully.

When getCurrentHash() returns null, the expression currentHash?.slice(0, 7) evaluates to undefined, resulting in a log message like "Current: undefined, expected: ...". Displaying 'unknown' would be more user-friendly.

🔎 Display 'unknown' for null hash
-      console.info(`  → Current: ${currentHash?.slice(0, 7)}, expected: ${repo.hash.slice(0, 7)}`);
+      console.info(`  → Current: ${currentHash?.slice(0, 7) ?? 'unknown'}, expected: ${repo.hash.slice(0, 7)}`);

9-11: The stdio configuration suppresses error output.

The stdio: ['pipe', 'pipe', 'pipe'] configuration prevents stderr from being displayed, making it difficult to diagnose git command failures. While the function catches errors and returns null, users won't see what went wrong (e.g., network issues, invalid repository URLs).

🔎 Allow stderr to be visible
 function exec(cmd: string, execCwd: string = cwd): string {
-  return execSync(cmd, { cwd: execCwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
+  return execSync(cmd, { cwd: execCwd, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'inherit'] }).trim();
 }

This configuration:

  • Ignores stdin (not needed)
  • Pipes stdout (for return value)
  • Inherits stderr (shows errors to user)
.github/actions/clone/action.yml (1)

13-19: Security: Command injection vulnerability via input embedding.

The inputs.ecosystem-ci-project value is directly embedded into the shell command at lines 18-19 without sanitization. If a malicious value is provided (e.g., via workflow_dispatch), it could execute arbitrary code.

Additionally, the script uses CommonJS require() in a project that follows ESM conventions elsewhere. Consider consolidating these calls into a single, safer operation.

🔎 Safer implementation using environment variables and fs.readFileSync
     - name: Output ecosystem ci project hash
       shell: bash
       id: ecosystem-ci-project-hash
       if: ${{ inputs.ecosystem-ci-project != '' }}
+      env:
+        PROJECT_NAME: ${{ inputs.ecosystem-ci-project }}
       run: |
-        node -e "const fs = require('fs'); const data = JSON.parse(fs.readFileSync('./ecosystem-ci/repo.json', 'utf8')); const project = data['${{ inputs.ecosystem-ci-project }}']; console.log('ECOSYSTEM_CI_PROJECT_HASH=' + project.hash);" >> $GITHUB_OUTPUT
-        node -e "const fs = require('fs'); const data = JSON.parse(fs.readFileSync('./ecosystem-ci/repo.json', 'utf8')); const project = data['${{ inputs.ecosystem-ci-project }}']; console.log('ECOSYSTEM_CI_PROJECT_REPOSITORY=' + project.repository.replace('https://github.com/', '').replace('.git', ''));" >> $GITHUB_OUTPUT
+        node -e "const fs = require('fs'); const data = JSON.parse(fs.readFileSync('./ecosystem-ci/repo.json', 'utf8')); const project = data[process.env.PROJECT_NAME]; if (!project) { console.error('Project not found'); process.exit(1); } console.log('ECOSYSTEM_CI_PROJECT_HASH=' + project.hash); console.log('ECOSYSTEM_CI_PROJECT_REPOSITORY=' + project.repository.replace('https://github.com/', '').replace('.git', ''));" >> $GITHUB_OUTPUT

This uses an environment variable to safely pass the input and combines both operations into a single node -e call.

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

7-8: Address the FIXME comment about auto mode.

The comment indicates that auto mode causes rolldown to hang with 400% CPU usage. This issue should be investigated or tracked.

Do you want me to open a new issue to track this auto mode problem, or would you like me to help investigate potential workarounds?

package.json (1)

11-13: Consider removing the "files" property from the private package.

The "files" array typically controls which files are included when a package is published. Since this is a private monorepo root ("private": true at line 4), it will never be published to npm. This property serves no functional purpose here and could be removed to avoid confusion.

ecosystem-ci/clone.ts (1)

42-50: Consider validating branch and hash existence before operations.

The cloneRepo and checkoutHash functions don't validate that the specified branch or commit hash exist in the remote repository. If the hash in repo.json becomes invalid (e.g., force-pushed away), the checkout will fail with a cryptic error.

Consider adding validation or improving error messages to help diagnose such issues.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1cedb32 and 1f5ccd8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • .github/actions/clone/action.yml (1 hunks)
  • .github/workflows/e2e-test.yml (1 hunks)
  • .gitignore (1 hunks)
  • ecosystem-ci/.gitignore (1 hunks)
  • ecosystem-ci/clone.ts (1 hunks)
  • ecosystem-ci/patch-project.ts (1 hunks)
  • ecosystem-ci/repo.json (1 hunks)
  • package.json (2 hunks)
  • tegg/plugin/ajv/package.json (0 hunks)
  • tsdown.config.ts (3 hunks)
💤 Files with no reviewable changes (1)
  • tegg/plugin/ajv/package.json
🧰 Additional context used
📓 Path-based instructions (4)
package.json

📄 CodeRabbit inference engine (CLAUDE.md)

Use workspace:* for internal package dependencies and catalog: for external dependencies defined in pnpm-workspace.yaml

Files:

  • package.json
**/*.{ts,tsx,js,mjs}

📄 CodeRabbit inference engine (AGENTS.md)

Use .ts sources over CommonJS and prefer ESM for exports

Files:

  • ecosystem-ci/patch-project.ts
  • ecosystem-ci/clone.ts
  • tsdown.config.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Name classes in PascalCase
Name functions and variables in camelCase

**/*.{ts,tsx}: Use explicit return types for all exported functions, methods, and getters to support TypeScript's --isolatedDeclarations flag
Avoid computed property names with symbols in class declarations; use override methods instead for compatibility with --isolatedDeclarations
Add explicit type annotations for class properties, particularly for exported symbols which should use unique symbol type
Enable strict mode in all TypeScript packages and use explicit return types for public APIs
Prefer interfaces over type aliases for object shapes in TypeScript
Use readonly modifiers where appropriate in TypeScript classes and interfaces
Avoid any type; use unknown when type is truly unknown

Files:

  • ecosystem-ci/patch-project.ts
  • ecosystem-ci/clone.ts
  • tsdown.config.ts
{tsdown,vitest}.config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

{tsdown,vitest}.config.ts: Use typed intermediate variables for tsdown and vitest config exports with explicit UserConfig/UserWorkspaceConfig type annotations
Configuration files for tools (tsdown, vitest) must use typed intermediate variables with explicit type annotations for config objects

Files:

  • tsdown.config.ts
🧠 Learnings (47)
📓 Common learnings
Learnt from: CR
Repo: eggjs/egg PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-20T09:24:59.960Z
Learning: Ensure PRs pass lint, typecheck, and tests before submission
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: All packages must include TypeScript type checking with `tsc --noEmit` in the `typecheck` script

Applied to files:

  • .github/actions/clone/action.yml
  • package.json
📚 Learning: 2025-12-20T09:24:59.960Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-20T09:24:59.960Z
Learning: Maintain Egg as a pnpm monorepo with core runtime code in `packages/egg`, supporting modules in `packages/core`, `packages/cluster`, and `packages/utils`, optional integrations under `plugins/`, examples in `examples/`, documentation site in `site/`, and unit tests beside packages under `test/` directories with fixtures in `test/fixtures/`

Applied to files:

  • package.json
  • ecosystem-ci/repo.json
  • .github/workflows/e2e-test.yml
  • ecosystem-ci/patch-project.ts
  • tsdown.config.ts
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to plugins/*/package.json : All plugins must include egg in peerDependencies and define `build`, `clean`, and `prepublishOnly` scripts in package.json

Applied to files:

  • package.json
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: All packages must define a `src/types.ts` file that extends the Egg module declarations using `declare module 'egg'` pattern

Applied to files:

  • package.json
  • tsdown.config.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/package.json : Egg.js version must be >= 4.1.0

Applied to files:

  • package.json
  • .github/workflows/e2e-test.yml
  • tsdown.config.ts
📚 Learning: 2025-11-27T14:37:59.711Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T14:37:59.711Z
Learning: Applies to pnpm-workspace.yaml : Define dependencies in pnpm-workspace.yaml catalog section and reference catalog entries with 'package-name': 'catalog:' or internal workspace dependencies with 'package-name': 'workspace:*'

Applied to files:

  • package.json
  • ecosystem-ci/patch-project.ts
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to package.json : Use `workspace:*` for internal package dependencies and `catalog:` for external dependencies defined in pnpm-workspace.yaml

Applied to files:

  • package.json
  • .github/workflows/e2e-test.yml
  • ecosystem-ci/patch-project.ts
  • tsdown.config.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/pnpm-workspace.yaml : Use pnpm workspaces with `catalog:` protocol for shared external dependencies

Applied to files:

  • package.json
  • .github/workflows/e2e-test.yml
  • ecosystem-ci/patch-project.ts
  • tsdown.config.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/package.json : Use `workspace:*` protocol for internal monorepo dependencies (both tegg and egg packages)

Applied to files:

  • package.json
  • .github/workflows/e2e-test.yml
  • ecosystem-ci/patch-project.ts
  • tsdown.config.ts
📚 Learning: 2025-11-27T14:37:59.711Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T14:37:59.711Z
Learning: Applies to packages/**/*.ts : Use TypeScript throughout all packages in the Eggjs monorepo

Applied to files:

  • package.json
  • .github/workflows/e2e-test.yml
  • tsdown.config.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/pnpm-workspace.yaml : Tegg packages should be defined in root pnpm-workspace.yaml with patterns `tegg/core/*`, `tegg/plugin/*`, `tegg/standalone/*`

Applied to files:

  • package.json
  • ecosystem-ci/patch-project.ts
  • tsdown.config.ts
  • .gitignore
📚 Learning: 2025-12-20T09:24:59.960Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-20T09:24:59.960Z
Learning: Keep local Node.js and pnpm versions aligned with the repository's `packageManager` field

Applied to files:

  • ecosystem-ci/repo.json
  • .github/workflows/e2e-test.yml
📚 Learning: 2025-11-27T14:37:59.711Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T14:37:59.711Z
Learning: Run 'pnpm run test' to validate changes (set timeout to 180+ seconds for all tests, 120+ seconds for coverage) and never cancel the command

Applied to files:

  • .github/workflows/e2e-test.yml
📚 Learning: 2025-12-20T09:24:59.960Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-20T09:24:59.960Z
Learning: Add regression cases that exercise both CommonJS and TypeScript example apps when features affect HTTP or process orchestration

Applied to files:

  • .github/workflows/e2e-test.yml
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/plugin/*/package.json : New plugins should define `eggPlugin` in `package.json` with dependencies

Applied to files:

  • .github/workflows/e2e-test.yml
📚 Learning: 2025-12-20T09:24:59.960Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-20T09:24:59.960Z
Learning: Run `pnpm install` to hydrate the workspace (Node.js ≥ 20.19.0 required)

Applied to files:

  • .github/workflows/e2e-test.yml
  • ecosystem-ci/patch-project.ts
📚 Learning: 2025-11-27T14:37:59.711Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T14:37:59.711Z
Learning: Build all packages first using 'pnpm run build' before making changes, then validate with lint, tests, and documentation site checks

Applied to files:

  • .github/workflows/e2e-test.yml
  • ecosystem-ci/patch-project.ts
📚 Learning: 2025-12-20T09:24:59.960Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-20T09:24:59.960Z
Learning: Use pnpm filters for package-specific workflows (e.g. `pnpm --filter=egg run test`)

Applied to files:

  • .github/workflows/e2e-test.yml
  • ecosystem-ci/patch-project.ts
📚 Learning: 2025-12-20T09:24:59.960Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-20T09:24:59.960Z
Learning: Run `pnpm run test` for Vitest suite or `pnpm run test:cov` for coverage before submitting

Applied to files:

  • .github/workflows/e2e-test.yml
📚 Learning: 2025-12-20T09:24:59.960Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-20T09:24:59.960Z
Learning: Build all packages with `pnpm run build`

Applied to files:

  • .github/workflows/e2e-test.yml
  • ecosystem-ci/patch-project.ts
  • tsdown.config.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/__tests__/**/*.test.{ts,tsx,js} : Use Vitest for testing all tegg packages

Applied to files:

  • .github/workflows/e2e-test.yml
  • .gitignore
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to packages/*/tsconfig.json : Create minimal tsconfig.json files in sub-packages containing only `{"extends": "../../tsconfig.json"}`

Applied to files:

  • ecosystem-ci/patch-project.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/pnpm-workspace.yaml : Centralize all shared dependency versions in the root `pnpm-workspace.yaml` rather than in individual tegg package files

Applied to files:

  • ecosystem-ci/patch-project.ts
  • tsdown.config.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/core/*/package.json : New core packages should include standard scripts in `package.json` with `typecheck` script using tsgo

Applied to files:

  • ecosystem-ci/patch-project.ts
  • .gitignore
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to **/tsconfig.json : Always extend the root tsconfig.json in sub-project TypeScript configurations using the minimal `extends` pattern

Applied to files:

  • ecosystem-ci/patch-project.ts
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to packages/*/tsconfig.json : Sub-project TypeScript configurations must be minimal with only an `extends` field pointing to the root `tsconfig.json`; no additional options should be added

Applied to files:

  • ecosystem-ci/patch-project.ts
  • tsdown.config.ts
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Use `pnpm` workspace commands with `--filter` flag for package-specific operations instead of running commands in individual directories

Applied to files:

  • ecosystem-ci/patch-project.ts
📚 Learning: 2025-11-27T14:37:59.711Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T14:37:59.711Z
Learning: Run bootstrap and build commands in sequence: corepack enable pnpm → pnpm install → pnpm run build → pnpm run lint

Applied to files:

  • ecosystem-ci/patch-project.ts
📚 Learning: 2025-11-27T14:37:59.711Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T14:37:59.711Z
Learning: Applies to packages/*/tsdown.config.ts : Use tsdown for unbundled ESM builds that preserves file structure; configure via tsdown.config.ts in each package

Applied to files:

  • tsdown.config.ts
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to {tsdown,vitest}.config.ts : Use typed intermediate variables for tsdown and vitest config exports with explicit UserConfig/UserWorkspaceConfig type annotations

Applied to files:

  • tsdown.config.ts
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to {tsdown,vitest}.config.ts : Configuration files for tools (tsdown, vitest) must use typed intermediate variables with explicit type annotations for config objects

Applied to files:

  • tsdown.config.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/core/*/tsconfig.json : Each new core package should include `tsconfig.json` extending `eggjs/tsconfig`

Applied to files:

  • tsdown.config.ts
  • .gitignore
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/tsconfig.json : Use `emitDecoratorMetadata` in TypeScript configuration for type inference in dependency injection

Applied to files:

  • tsdown.config.ts
📚 Learning: 2025-12-20T09:24:59.960Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-20T09:24:59.960Z
Learning: Applies to **/*.{ts,tsx,js,mjs} : Use `.ts` sources over CommonJS and prefer ESM for exports

Applied to files:

  • tsdown.config.ts
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Most plugins do NOT need a `tsdown.config.ts` file - only create one if you need custom options like copying assets or custom entry points

Applied to files:

  • tsdown.config.ts
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to **/*.{ts,tsx} : Use explicit return types for all exported functions, methods, and getters to support TypeScript's `--isolatedDeclarations` flag

Applied to files:

  • tsdown.config.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/vitest.config.ts : Configure test discovery through monorepo root `vitest.config.ts` which includes all tegg packages

Applied to files:

  • tsdown.config.ts
  • .gitignore
📚 Learning: 2025-11-27T14:37:59.711Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T14:37:59.711Z
Learning: Applies to packages/**/*.ts : Use strict TypeScript mode in all packages

Applied to files:

  • tsdown.config.ts
📚 Learning: 2025-11-27T14:37:59.711Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T14:37:59.711Z
Learning: Applies to packages/*/tsconfig.json : All sub-project tsconfig.json files MUST extend from root tsconfig.json using 'extends': '../../tsconfig.json'

Applied to files:

  • tsdown.config.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/*.{js,ts,mjs,cjs} : Use ESM only (no CommonJS)

Applied to files:

  • tsdown.config.ts
  • .gitignore
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to plugins/*/package.json : Plugin packages must configure exports in package.json with both development (`./src/*.ts`) and published (`./dist/*.js`) entry points

Applied to files:

  • tsdown.config.ts
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/*.{ts,tsx} : Do not use circular dependencies between prototypes or modules

Applied to files:

  • .gitignore
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/*.{ts,tsx} : All imports should use `.js` extensions for ESM files

Applied to files:

  • .gitignore
📚 Learning: 2025-12-21T03:05:13.313Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/package.json : Node.js version must be >= 22.18.0

Applied to files:

  • .gitignore
📚 Learning: 2025-12-21T03:04:53.982Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to test/**/*.test.ts : Test files should follow the pattern `test/**/*.test.ts` and use vitest for new test files

Applied to files:

  • .gitignore
📚 Learning: 2025-12-20T09:24:59.960Z
Learnt from: CR
Repo: eggjs/egg PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-20T09:24:59.960Z
Learning: Applies to **/test/**/*.test.ts : Configure Vitest to discover `**/test/**/*.test.ts` within each package and mirror this pattern when adding test suites

Applied to files:

  • .gitignore
🧬 Code graph analysis (1)
ecosystem-ci/patch-project.ts (1)
scripts/utils.js (1)
  • workspaceConfig (15-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: Agent
  • GitHub Check: Cloudflare Pages: egg-v3
🔇 Additional comments (10)
tsdown.config.ts (2)

32-32: External configuration looks correct.

The external array properly excludes @eggjs/ scoped packages and egg from bundling, which is appropriate for a monorepo setup where these are workspace dependencies.


19-19: No action needed — declaration files are automatically generated through tsdown's auto-detection mechanism. If your package.json contains a types or typings field, declaration file generation will be enabled by default in tsdown. All packages declare the "types": "./dist/index.d.ts" field in their package.json, which triggers automatic .d.ts generation. Additionally, with isolatedDeclarations enabled, tsdown will use oxc-transform for .d.ts generation, which is extremely fast and highly recommended for optimal performance. The commented-out dts: true is redundant but harmless.

Likely an incorrect or invalid review comment.

ecosystem-ci/.gitignore (1)

1-2: LGTM!

The ignore patterns correctly exclude the cloned ecosystem-ci project directories (cnpmcore and examples) that are managed by the clone script.

.gitignore (1)

105-106: LGTM!

Adding *.tgz correctly excludes packaged tarballs generated by the pnpm -r pack command in the e2e workflow.

package.json (1)

51-51: LGTM!

Adding @types/js-yaml as a dev dependency correctly provides TypeScript types for the js-yaml library used in ecosystem-ci/patch-project.ts. The catalog: protocol follows the coding guidelines for external dependencies.

ecosystem-ci/patch-project.ts (3)

1-10: LGTM on imports and directory setup.

The imports follow ESM conventions correctly, and the directory path setup using import.meta.dirname is appropriate.


94-107: LGTM on project-specific patching functions.

The patchCnpmcore and patchExamples functions correctly apply overrides to their respective project package.json files. The examples function appropriately handles multiple sub-projects.


28-53: Add explicit return type and improve error handling.

The discoverPackages function lacks an explicit return type annotation, which violates the coding guideline requiring explicit return types for all exported/public functions to support TypeScript's --isolatedDeclarations flag.

Additionally, the error handling at line 47 silently warns and continues. Consider whether skipping invalid package.json files is the desired behavior for all cases.

Based on coding guidelines, add explicit return type:

🔎 Add explicit return type annotation
-async function discoverPackages(): Promise<[string, string][]> {
+async function discoverPackages(): Promise<Array<[string, string]>> {

Or for better type safety:

type PackageInfo = [name: string, path: string];

async function discoverPackages(): Promise<PackageInfo[]> {
⛔ Skipped due to learnings
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to **/*.{ts,tsx} : Use explicit return types for all exported functions, methods, and getters to support TypeScript's `--isolatedDeclarations` flag
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to **/*.{ts,tsx} : Enable strict mode in all TypeScript packages and use explicit return types for public APIs
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to **/*.{ts,tsx} : Add explicit type annotations for class properties, particularly for exported symbols which should use `unique symbol` type
Learnt from: CR
Repo: eggjs/egg PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T14:37:59.711Z
Learning: Applies to packages/**/*.ts : Use strict TypeScript mode in all packages
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: All packages must include TypeScript type checking with `tsc --noEmit` in the `typecheck` script
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to **/*.{ts,tsx} : Avoid `any` type; use `unknown` when type is truly unknown
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to package.json : Use `workspace:*` for internal package dependencies and `catalog:` for external dependencies defined in pnpm-workspace.yaml
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/pnpm-workspace.yaml : Tegg packages should be defined in root pnpm-workspace.yaml with patterns `tegg/core/*`, `tegg/plugin/*`, `tegg/standalone/*`
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/package.json : Use `workspace:*` protocol for internal monorepo dependencies (both tegg and egg packages)
Learnt from: CR
Repo: eggjs/egg PR: 0
File: tegg/CLAUDE.md:0-0
Timestamp: 2025-12-21T03:05:13.313Z
Learning: Applies to tegg/**/pnpm-workspace.yaml : Use pnpm workspaces with `catalog:` protocol for shared external dependencies
Learnt from: CR
Repo: eggjs/egg PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T14:37:59.711Z
Learning: Applies to pnpm-workspace.yaml : Define dependencies in pnpm-workspace.yaml catalog section and reference catalog entries with 'package-name': 'catalog:' or internal workspace dependencies with 'package-name': 'workspace:*'
ecosystem-ci/clone.ts (2)

53-85: LGTM on the main cloning and validation logic.

The main loop correctly handles both existing and new repository directories, validates remote URLs with normalization, checks commit hashes, and performs cloning/checkout operations with appropriate logging. The error handling allows the script to continue processing other repositories even if one fails.


9-52: Add explicit return type annotations to all functions.

The functions exec, getRemoteUrl, normalizeGitUrl, isSameRepo, getCurrentHash, cloneRepo, and checkoutHash lack explicit return type annotations. Per the coding guidelines, all functions should have explicit return types to support TypeScript's --isolatedDeclarations flag.

Based on coding guidelines:

🔎 Add explicit return types
-function exec(cmd: string, execCwd: string = cwd): string {
+function exec(cmd: string, execCwd: string = cwd): string {
   // Already has return type ✓
 }

-function getRemoteUrl(dir: string): string | null {
+function getRemoteUrl(dir: string): string | null {
   // Already has return type ✓
 }

-function normalizeGitUrl(url: string): string {
+function normalizeGitUrl(url: string): string {
   // Already has return type ✓
 }

-function isSameRepo(url1: string, url2: string): boolean {
+function isSameRepo(url1: string, url2: string): boolean {
   // Already has return type ✓
 }

-function getCurrentHash(dir: string): string | null {
+function getCurrentHash(dir: string): string | null {
   // Already has return type ✓
 }

-function cloneRepo(repoUrl: string, branch: string, targetDir: string): void {
+function cloneRepo(repoUrl: string, branch: string, targetDir: string): void {
   // Already has return type ✓
 }

-function checkoutHash(dir: string, hash: string): void {
+function checkoutHash(dir: string, hash: string): void {
   // Already has return type ✓
 }

Actually, upon closer inspection, all functions already have explicit return types. No changes needed here.

⛔ Skipped due to learnings
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to **/*.{ts,tsx} : Use explicit return types for all exported functions, methods, and getters to support TypeScript's `--isolatedDeclarations` flag
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to **/*.{ts,tsx} : Enable strict mode in all TypeScript packages and use explicit return types for public APIs
Learnt from: CR
Repo: eggjs/egg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-21T03:04:53.982Z
Learning: Applies to **/*.{ts,tsx} : Add explicit type annotations for class properties, particularly for exported symbols which should use `unique symbol` type

Copy link
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 9 out of 11 changed files in this pull request and generated 8 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Copilot AI review requested due to automatic review settings December 21, 2025 08:19
@socket-security
Copy link

socket-security bot commented Dec 21, 2025

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​types/​mocha@​10.0.101001007780100

View full report

Copy link
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 11 out of 13 changed files in this pull request and generated 6 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

await patchExamples(overrides);
break;
default:
console.error(`Project ${project} is not supported`);
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

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

The error message when an unsupported project is encountered in the switch statement is inconsistent with the earlier validation. At this point, the project has already been validated to exist in repo.json (line 17-20), so this error message is misleading. Consider changing to something like console.error(\Project ${project} exists in repo.json but has no patch handler defined`)` to accurately reflect the issue.

Suggested change
console.error(`Project ${project} is not supported`);
console.error(`Project ${project} exists in repo.json but has no patch handler defined`);

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +44
function cloneRepo(repoUrl: string, branch: string, targetDir: string): void {
console.info(`Cloning ${repoUrl} (branch: ${branch})...`);
exec(`git clone --branch ${branch} ${repoUrl} ${targetDir}`);
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

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

The git command construction in cloneRepo is vulnerable to command injection. The repoUrl, branch, and targetDir parameters are directly interpolated into the shell command without sanitization. While currently these values come from a static JSON file, if the source of these values changes in the future, malicious input could execute arbitrary commands. Use array syntax for execSync or properly escape/validate these parameters to prevent potential command injection.

Copilot uses AI. Check for mistakes.
Comment on lines +45 to +48
} catch {
// Skip if package.json is invalid or cannot be read
console.warn(`Warning: Could not read ${pkgJsonPath}`);
}
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

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

The error handling in this catch block silently ignores all errors by logging a warning and continuing. If package.json parsing fails for important packages, the script will silently skip them without clearly indicating the impact. Consider either failing fast when critical packages cannot be read, or collecting and reporting all warnings at the end so users are aware of skipped packages.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <[email protected]>
Signed-off-by: MK (fengmk2) <[email protected]>
Copilot AI review requested due to automatic review settings December 21, 2025 08:35
@fengmk2 fengmk2 merged commit a025213 into next Dec 21, 2025
38 of 50 checks passed
@fengmk2 fengmk2 deleted the e2e branch December 21, 2025 08:35
Copy link
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 11 out of 13 changed files in this pull request and generated 7 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment on lines +7 to +8
// FIXME: auto mode is not working, rolldown was hang and cpu 400% when using auto mode
// include: 'auto',
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

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

The comment states "FIXME: auto mode is not working" which indicates an unresolved issue. This commented-out code should either be removed if not needed, or the underlying issue should be fixed before merging.

Suggested change
// FIXME: auto mode is not working, rolldown was hang and cpu 400% when using auto mode
// include: 'auto',

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +13
"files": [
"README.md"
],
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

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

Adding a "files" field with only "README.md" to a private monorepo package is unnecessary since private packages are never published to npm. This field has no effect and should be removed to avoid confusion.

Suggested change
"files": [
"README.md"
],

Copilot uses AI. Check for mistakes.
}

const packageJsonString = JSON.stringify(packageJson, null, 2) + '\n';
console.log(packageJsonString);
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

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

The console.log output on line 90 will be mixed with the actual execution output, making it difficult to distinguish between debug information and actual results. Consider using console.error for debug output or adding a flag to control verbosity.

Suggested change
console.log(packageJsonString);
console.error(packageJsonString);

Copilot uses AI. Check for mistakes.
}
}

main();
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

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

Missing error handling for the main function. If any of the async operations fail, the process will exit with a success code (0) by default. Add a catch block to ensure the process exits with a non-zero code on failure.

Suggested change
main();
main().catch((err) => {
console.error(err);
process.exitCode = 1;
});

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +50
function cloneRepo(repoUrl: string, branch: string, targetDir: string): void {
console.info(`Cloning ${repoUrl} (branch: ${branch})...`);
exec(`git clone --branch ${branch} ${repoUrl} ${targetDir}`);
}

function checkoutHash(dir: string, hash: string): void {
console.info(`Checking out ${hash}...`);
exec(`git fetch origin`, dir);
exec(`git checkout ${hash}`, dir);
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

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

Potential command injection vulnerability. The git commands use unsanitized input from repo.json (branch, repository URL, and hash). While these are configuration values, if repo.json is ever modified maliciously, this could lead to command injection. Consider validating or sanitizing these inputs before using them in shell commands.

Suggested change
function cloneRepo(repoUrl: string, branch: string, targetDir: string): void {
console.info(`Cloning ${repoUrl} (branch: ${branch})...`);
exec(`git clone --branch ${branch} ${repoUrl} ${targetDir}`);
}
function checkoutHash(dir: string, hash: string): void {
console.info(`Checking out ${hash}...`);
exec(`git fetch origin`, dir);
exec(`git checkout ${hash}`, dir);
function validateGitUrl(name: string, url: string): string {
// Allow typical Git URL characters, disallow whitespace and shell metacharacters.
const gitUrlPattern = /^[A-Za-z0-9@._:/%+-]+$/;
if (!gitUrlPattern.test(url)) {
throw new Error(`Invalid ${name}: contains unsafe characters`);
}
return url;
}
function validateGitRef(name: string, ref: string): string {
// Allow typical Git ref characters (no spaces or shell metacharacters).
const gitRefPattern = /^[A-Za-z0-9._\/\-]+$/;
if (!gitRefPattern.test(ref)) {
throw new Error(`Invalid ${name}: contains unsafe characters`);
}
return ref;
}
function validateGitHash(name: string, hash: string): string {
// Git hashes are hex strings, usually 40 chars, but allow shorter prefixes.
const gitHashPattern = /^[0-9a-fA-F]{7,40}$/;
if (!gitHashPattern.test(hash)) {
throw new Error(`Invalid ${name}: must be a hex commit hash`);
}
return hash;
}
function cloneRepo(repoUrl: string, branch: string, targetDir: string): void {
const safeRepoUrl = validateGitUrl('repository URL', repoUrl);
const safeBranch = validateGitRef('branch', branch);
console.info(`Cloning ${safeRepoUrl} (branch: ${safeBranch})...`);
exec(`git clone --branch ${safeBranch} ${safeRepoUrl} ${targetDir}`);
}
function checkoutHash(dir: string, hash: string): void {
const safeHash = validateGitHash('hash', hash);
console.info(`Checking out ${safeHash}...`);
exec(`git fetch origin`, dir);
exec(`git checkout ${safeHash}`, dir);

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +87
for (const [repoName, repo] of Object.entries(repos)) {
const targetDir = join(cwd, repoName);

if (existsSync(targetDir)) {
console.info(`\nDirectory ${repoName} exists, validating...`);

const remoteUrl = getRemoteUrl(targetDir);
if (!remoteUrl) {
console.error(` ✗ ${repoName} is not a git repository`);
continue;
}

if (!isSameRepo(remoteUrl, repo.repository)) {
console.error(` ✗ Remote mismatch: expected ${repo.repository}, got ${remoteUrl}`);
continue;
}

console.info(` ✓ Remote matches`);

const currentHash = getCurrentHash(targetDir);
if (currentHash === repo.hash) {
console.info(` ✓ Already at correct commit ${repo.hash.slice(0, 7)}`);
} else {
console.info(` → Current: ${currentHash?.slice(0, 7)}, expected: ${repo.hash.slice(0, 7)}`);
checkoutHash(targetDir, repo.hash);
console.info(` ✓ Checked out ${repo.hash.slice(0, 7)}`);
}
} else {
cloneRepo(repo.repository, repo.branch, targetDir);
checkoutHash(targetDir, repo.hash);
console.info(`✓ Cloned and checked out ${repo.hash.slice(0, 7)}`);
}
}

console.info('\nDone!');
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

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

Missing error handling for git command failures. When cloneRepo or checkoutHash fail (lines 81-82), the script continues execution and prints "Done!" even though the operation may have failed. This could lead to false positives in CI/CD. Consider wrapping the main loop in a try-catch block or tracking failures to exit with an appropriate error code.

Suggested change
for (const [repoName, repo] of Object.entries(repos)) {
const targetDir = join(cwd, repoName);
if (existsSync(targetDir)) {
console.info(`\nDirectory ${repoName} exists, validating...`);
const remoteUrl = getRemoteUrl(targetDir);
if (!remoteUrl) {
console.error(` ✗ ${repoName} is not a git repository`);
continue;
}
if (!isSameRepo(remoteUrl, repo.repository)) {
console.error(` ✗ Remote mismatch: expected ${repo.repository}, got ${remoteUrl}`);
continue;
}
console.info(` ✓ Remote matches`);
const currentHash = getCurrentHash(targetDir);
if (currentHash === repo.hash) {
console.info(` ✓ Already at correct commit ${repo.hash.slice(0, 7)}`);
} else {
console.info(` → Current: ${currentHash?.slice(0, 7)}, expected: ${repo.hash.slice(0, 7)}`);
checkoutHash(targetDir, repo.hash);
console.info(` ✓ Checked out ${repo.hash.slice(0, 7)}`);
}
} else {
cloneRepo(repo.repository, repo.branch, targetDir);
checkoutHash(targetDir, repo.hash);
console.info(`✓ Cloned and checked out ${repo.hash.slice(0, 7)}`);
}
}
console.info('\nDone!');
let hasError = false;
for (const [repoName, repo] of Object.entries(repos)) {
const targetDir = join(cwd, repoName);
try {
if (existsSync(targetDir)) {
console.info(`\nDirectory ${repoName} exists, validating...`);
const remoteUrl = getRemoteUrl(targetDir);
if (!remoteUrl) {
console.error(` ✗ ${repoName} is not a git repository`);
continue;
}
if (!isSameRepo(remoteUrl, repo.repository)) {
console.error(` ✗ Remote mismatch: expected ${repo.repository}, got ${remoteUrl}`);
continue;
}
console.info(` ✓ Remote matches`);
const currentHash = getCurrentHash(targetDir);
if (currentHash === repo.hash) {
console.info(` ✓ Already at correct commit ${repo.hash.slice(0, 7)}`);
} else {
console.info(` → Current: ${currentHash?.slice(0, 7)}, expected: ${repo.hash.slice(0, 7)}`);
checkoutHash(targetDir, repo.hash);
console.info(` ✓ Checked out ${repo.hash.slice(0, 7)}`);
}
} else {
cloneRepo(repo.repository, repo.branch, targetDir);
checkoutHash(targetDir, repo.hash);
console.info(`✓ Cloned and checked out ${repo.hash.slice(0, 7)}`);
}
} catch (error) {
hasError = true;
console.error(`\n✗ Failed to process ${repoName}:`, error);
}
}
if (hasError) {
console.error('\nDone with errors.');
process.exitCode = 1;
} else {
console.info('\nDone!');
}

Copilot uses AI. Check for mistakes.
level: 'error',
},
dts: true,
// dts: true,
Copy link

Copilot AI Dec 21, 2025

Choose a reason for hiding this comment

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

The dts generation is commented out which will prevent TypeScript declaration files from being generated. This will break TypeScript support for consumers of these packages. If this is intentional for testing purposes, it should be reverted before merging or documented why it's disabled.

Suggested change
// dts: true,
dts: true,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants