Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Aug 31, 2025

Summary by CodeRabbit

  • New Features

    • CLI now auto-checks for newer releases before running commands and prints a notice when an update is available.
    • Added an opt-out flag (--no-version-check) available globally and on most commands.
  • Bug Fixes

    • Info command no longer lists private packages when showing dependency info.
  • Chores

    • Added runtime and dev type dependencies to support semantic version checking.

Copilot AI review requested due to automatic review settings August 31, 2025 08:42
@coderabbitai
Copy link

coderabbitai bot commented Aug 31, 2025

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 a version-check feature to the CLI: introduces semver dependency, implements utilities to fetch the latest npm version, wires a pre-action hook with a --no-version-check option across commands, and skips private packages in info resolution. Prints a notice when a newer version is available; network errors are ignored.

Changes

Cohort / File(s) Summary
Dependencies
packages/cli/package.json
Added runtime dependency semver (^7.7.2) and dev dependency @types/semver (^7.7.0).
CLI command wiring
packages/cli/src/index.ts
Added import and use of checkNewVersion() in a program-wide preAction hook; introduced a --no-version-check option and attached it to multiple commands to opt out; preserved existing program.version(getVersion(...)).
Version utilities
packages/cli/src/utils/version-utils.ts
Added checkNewVersion() and getLatestVersion() which fetch dist-tags.next from the npm registry with a 2s timeout, validate via semver, and print a colored message when a newer version is detected; network/fetch errors are swallowed.
Info action adjustment
packages/cli/src/actions/info.ts
Skip dependencies whose package.json has private: true when resolving per-package info; filter out undefined entries so private packages do not appear in the returned array.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I’m a rabbit in the CLI glen, sniffing versions on the breeze,
If a fresher sprout is found, I tap-tap and say, “Please upgrade, please.”
If you’d prefer me quiet, add --no-version-check to your run,
I’ll nibble softly, hop along, and leave your output undone. 🥕🐇

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/update-chck

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@claude
Copy link

claude bot commented Aug 31, 2025

Claude finished @ymc9's task —— View job


PR Review: feat: new version check

Todo List:

  • Read repository guidelines (CLAUDE.md)
  • Examine changed files and understand implementation
  • Analyze code quality and best practices
  • Check for potential bugs and issues
  • Assess performance considerations
  • Review security concerns
  • Evaluate test coverage needs
  • Provide comprehensive feedback

Implementation Overview

This PR adds version checking functionality to the ZenStack CLI. The implementation:

  • Adds semver dependency to check version comparison
  • Creates version-utils.ts with version checking logic
  • Integrates version check into CLI commands via preAction hook
  • Adds --no-version-check option to disable the feature

Code Quality & Best Practices

✅ Positive aspects:

  • Clean separation of concerns with dedicated version-utils.ts module
  • Consistent error handling with try-catch blocks
  • Good use of semantic versioning comparison with semver library
  • Proper timeout handling for network requests (2s timeout)
  • Graceful degradation when version check fails

⚠️ Areas for improvement:

  • Missing JSDoc comments for exported functions
  • Hard-coded constants could be made configurable
  • No logging/debugging information when version check fails silently

Potential Bugs & Issues

🔍 Found issues:

  1. Version check logic inconsistency (packages/cli/src/index.ts:146-148):

    if (actionCommand.getOptionValue('versionCheck')) {
        await checkNewVersion();
    }

    This checks for versionCheck but the option is defined as --no-version-check which would set versionCheck to false when the flag is used. The logic should be:

    if (actionCommand.getOptionValue('versionCheck') !== false) {
        await checkNewVersion();
    }
  2. Unsafe type assertion (packages/cli/src/utils/version-utils.ts:42):

    const data: any = await fetchResult.json();

    Using any type bypasses TypeScript's type safety. Consider defining a proper interface.

  3. TAG inconsistency (packages/cli/src/utils/version-utils.ts:8):

    const VERSION_CHECK_TAG = 'next';

    The code checks for 'next' tag but for CLI tools, 'latest' is more appropriate for stable releases.

Performance Considerations

✅ Good performance practices:

  • 2-second timeout prevents hanging CLI commands
  • Uses AbortSignal for proper request cancellation
  • Asynchronous operation doesn't block CLI startup

💡 Suggestions:

  • Consider caching version check results to avoid repeated network calls in the same session
  • Could implement exponential backoff for network failures

Security Concerns

✅ Security aspects handled well:

  • Uses HTTPS for registry requests
  • Proper timeout to prevent hanging requests
  • Validates semver format before using version string

⚠️ Minor security considerations:

  • No certificate pinning (though not critical for npm registry)
  • Could validate response content-type header

Test Coverage

❌ Missing test coverage:

  • No tests found for version-utils.ts functions
  • Version checking integration not tested in existing CLI tests

📝 Recommended tests:

  • Unit tests for getVersion(), checkNewVersion(), getLatestVersion()
  • Mock network requests to test success/failure scenarios
  • Integration tests to verify --no-version-check flag behavior
  • Error handling tests for network failures and invalid responses

Recommendations

High Priority:

  1. Fix version check logic - The conditional logic needs to be corrected
  2. Add comprehensive tests - Critical for network-dependent functionality

Medium Priority:
3. Improve type safety - Define proper interfaces instead of any
4. Consider TAG configuration - Evaluate if 'next' vs 'latest' is correct
5. Add JSDoc documentation - Especially for exported functions

Low Priority:
6. Add caching mechanism - For better user experience
7. Enhance error reporting - Optional verbose mode for debugging

Overall Assessment

This is a solid implementation of version checking functionality with good architectural decisions. The main concern is the logic bug that would prevent the version check from working correctly with the --no-version-check flag. Once the critical bug is fixed and tests are added, this will be a valuable feature for keeping users updated.

Recommendation: Approve after addressing the version check logic bug and adding basic test coverage.

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 a new version checking feature to the CLI that notifies users when a newer version is available.

  • Implements version checking functionality that fetches the latest version from npm registry
  • Adds a --no-version-check option to all CLI commands to allow users to opt out
  • Integrates version checking as a pre-action hook that runs before each command

Reviewed Changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
packages/cli/src/utils/version-utils.ts Adds version checking utilities including fetching latest version from npm registry
packages/cli/src/index.ts Integrates version checking into CLI commands with opt-out option
packages/cli/package.json Adds semver dependency and type definitions for version comparison
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (7)
packages/cli/package.json (1)

41-41: Declare Node engine to guarantee fetch + AbortSignal.timeout support

The new version check relies on global fetch and AbortSignal.timeout, which are reliably available from Node 18.17+. Consider declaring the engine to prevent runtime surprises.

Add to package.json (top-level):
{
"engines": { "node": ">=18.17.0" }
}

packages/cli/src/utils/version-utils.ts (4)

7-8: Select dist-tag dynamically instead of hard-coding 'next'

Stable users may be prompted to install pre-releases. Pick 'latest' for stable installs and 'next' for pre-release installs.

Apply this diff:

-const CHECK_VERSION_TIMEOUT = 2000;
-const VERSION_CHECK_TAG = 'next';
+const CHECK_VERSION_TIMEOUT = 2000;
+const DEFAULT_VERSION_CHECK_TAG = 'latest';
@@
-export async function checkNewVersion() {
+export async function checkNewVersion() {
     const currVersion = getVersion();
     let latestVersion: string;
     try {
-        latestVersion = await getLatestVersion();
+        const tag = currVersion && semver.prerelease(currVersion) ? 'next' : 'latest';
+        latestVersion = await getLatestVersion(tag);
     } catch {
         // noop
         return;
     }
@@
-export async function getLatestVersion() {
-    const fetchResult = await fetch('https://registry.npmjs.org/@zenstackhq/cli', {
+export async function getLatestVersion(tag: 'latest' | 'next' = DEFAULT_VERSION_CHECK_TAG) {
+    const fetchResult = await fetch('https://registry.npmjs.org/@zenstackhq/cli', {
         headers: { accept: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*' },
         signal: AbortSignal.timeout(CHECK_VERSION_TIMEOUT),
     });
@@
     if (fetchResult.ok) {
         const data: any = await fetchResult.json();
-        const latestVersion = data?.['dist-tags']?.[VERSION_CHECK_TAG];
+        const latestVersion = data?.['dist-tags']?.[tag];
         if (typeof latestVersion === 'string' && semver.valid(latestVersion)) {
             return latestVersion;
         }
     }

Also applies to: 20-33, 35-46


30-32: Make the update notice actionable

Provide a one-liner the user can copy-paste.

-        console.log(`A newer version ${colors.cyan(latestVersion)} is available.`);
+        const tagHint = semver.prerelease(latestVersion) ? 'next' : 'latest';
+        console.log(`A newer version ${colors.cyan(latestVersion)} is available. Run "npm i -g @zenstackhq/cli@${tagHint}" to update.`);

36-39: Respect custom npm registries

Honor npm_config_registry/NPM_CONFIG_REGISTRY before falling back to the public registry.

-    const fetchResult = await fetch('https://registry.npmjs.org/@zenstackhq/cli', {
+    const base = (process.env.npm_config_registry || process.env.NPM_CONFIG_REGISTRY || 'https://registry.npmjs.org').replace(/\/$/, '');
+    const fetchResult = await fetch(`${base}/@zenstackhq/cli`, {
         headers: { accept: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*' },
         signal: AbortSignal.timeout(CHECK_VERSION_TIMEOUT),
     });

23-28: Surface failures when debugging

Keep default silent behavior, but emit details when ZENSTACK_DEBUG is set.

-    } catch {
-        // noop
-        return;
-    }
+    } catch (e) {
+        if (process.env.ZENSTACK_DEBUG) {
+            console.debug('[version-check] failed:', e);
+        }
+        return;
+    }
packages/cli/src/index.ts (2)

54-61: Reduce repetition when adding the --no-version-check option

Define a small helper to attach the option, or (if acceptable with Commander constraints) make it a global option inherited by subcommands. This cuts maintenance overhead when adding new commands.

Example:

const withVersionCheck = <T extends Command>(cmd: T) => cmd.addOption(noVersionCheckOption);
withVersionCheck(program.command('generate') /* ... */);

Also applies to: 71-71, 83-83, 91-91, 99-99, 107-107, 119-119, 129-129, 136-136, 142-142


145-149: Gate version check for CI/silent/non-TTY to avoid noisy output and latency

Skip the network call when not helpful.

-    program.hook('preAction', async (_thisCommand, actionCommand) => {
-        if (actionCommand.getOptionValue('versionCheck')) {
-            await checkNewVersion();
-        }
-    });
+    program.hook('preAction', async (_thisCommand, actionCommand) => {
+        const enabled = actionCommand.getOptionValue('versionCheck');
+        const silent = Boolean(actionCommand.getOptionValue('silent'));
+        const inCI = process.env.CI === 'true' || process.env.CI === '1';
+        const isTTY = process.stdout.isTTY;
+        if (enabled && !silent && !inCI && isTTY) {
+            await checkNewVersion();
+        }
+    });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 11658f2 and 8a9f920.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • packages/cli/package.json (1 hunks)
  • packages/cli/src/index.ts (6 hunks)
  • packages/cli/src/utils/version-utils.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
{packages,samples,tests}/**

📄 CodeRabbit inference engine (CLAUDE.md)

Packages are located in packages/, samples/, and tests/

Files:

  • packages/cli/package.json
  • packages/cli/src/utils/version-utils.ts
  • packages/cli/src/index.ts
🧬 Code graph analysis (1)
packages/cli/src/index.ts (1)
packages/cli/src/utils/version-utils.ts (1)
  • checkNewVersion (20-33)
⏰ 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). (1)
  • GitHub Check: build-test (20.x)
🔇 Additional comments (2)
packages/cli/package.json (2)

41-41: semver runtime dependency addition looks good

Using semver at runtime for version comparison is appropriate. Version range ^7.7.2 matches the TS types added below.


49-49: @types/semver devDependency looks good

Typings align with the runtime version; no issues.

@claude
Copy link

claude bot commented Aug 31, 2025

Claude finished @ymc9's task —— View job


PR Review: feat: new version check

Todo List:

  • Read repository guidelines (CLAUDE.md)
  • Examine changed files and understand implementation
  • Analyze code quality and best practices
  • Check for potential bugs and issues
  • Assess performance considerations
  • Review security concerns
  • Evaluate test coverage needs
  • Provide comprehensive feedback

Implementation Overview

This PR adds version checking functionality to the ZenStack CLI. The implementation:

  • Adds semver dependency to check version comparison
  • Creates version-utils.ts with version checking logic
  • Integrates version check into CLI commands via preAction hook
  • Adds --no-version-check option to disable the feature

Code Quality & Best Practices

✅ Positive aspects:

  • Clean separation of concerns with dedicated version-utils.ts module
  • Consistent error handling with try-catch blocks
  • Good use of semantic versioning comparison with semver library
  • Proper timeout handling for network requests (2s timeout)
  • Graceful degradation when version check fails silently

⚠️ Areas for improvement:

  • Missing JSDoc comments for exported functions
  • Hard-coded constants could be made configurable
  • No logging/debugging information when version check fails silently

Potential Bugs & Issues

🔍 Found issues:

  1. Version check logic inconsistency (packages/cli/src/index.ts:146-148):

    if (actionCommand.getOptionValue('versionCheck') !== false) {
        await checkNewVersion();
    }

    This checks for versionCheck but the option is defined as --no-version-check which would set versionCheck to false when the flag is used. The logic should be:

    if (actionCommand.getOptionValue('versionCheck') !== false) {
        await checkNewVersion();
    }
  2. Unsafe type assertion (packages/cli/src/utils/version-utils.ts:42):

    const data: any = await fetchResult.json();

    Using any type bypasses TypeScript's type safety. Consider defining a proper interface.

  3. TAG inconsistency (packages/cli/src/utils/version-utils.ts:8):

    const VERSION_CHECK_TAG = 'next';

    The code checks for 'next' tag but for CLI tools, 'latest' is more appropriate for stable releases.

Performance Considerations

✅ Good performance practices:

  • 2-second timeout prevents hanging CLI commands
  • Uses AbortSignal for proper request cancellation
  • Asynchronous operation doesn't block CLI startup

💡 Suggestions:

  • Consider caching version check results to avoid repeated network calls in the same session
  • Could implement exponential backoff for network failures

Security Concerns

✅ Security aspects handled well:

  • Uses HTTPS for registry requests
  • Proper timeout to prevent hanging requests
  • Validates semver format before using version string

⚠️ Minor security considerations:

  • No certificate pinning (though not critical for npm registry)
  • Could validate response content-type header

Test Coverage

❌ Missing test coverage:

  • No tests found for version-utils.ts functions
  • Version checking integration not tested in existing CLI tests

📝 Recommended tests:

  • Unit tests for getVersion(), checkNewVersion(), getLatestVersion()
  • Mock network requests to test success/failure scenarios
  • Integration tests to verify --no-version-check flag behavior
  • Error handling tests for network failures and invalid responses

Recommendations

High Priority:

  1. Fix version check logic - The conditional logic needs to be corrected
  2. Add comprehensive tests - Critical for network-dependent functionality

Medium Priority:
3. Improve type safety - Define proper interfaces instead of any
4. Consider TAG configuration - Evaluate if 'next' vs 'latest' is correct
5. Add JSDoc documentation - Especially for exported functions

Low Priority:
6. Add caching mechanism - For better user experience
7. Enhance error reporting - Optional verbose mode for debugging

Overall Assessment

This is a solid implementation of version checking functionality with good architectural decisions. The main concern is the logic bug that would prevent the version check from working correctly with the --no-version-check flag. Once the critical bug is fixed and tests are added, this will be a valuable feature for keeping users updated.

Recommendation: Approve after addressing the version check logic bug and adding basic test coverage.


Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8a9f920 and 9fc8f3d.

📒 Files selected for processing (3)
  • packages/cli/src/actions/info.ts (1 hunks)
  • packages/cli/src/index.ts (6 hunks)
  • packages/cli/src/utils/version-utils.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/cli/src/utils/version-utils.ts
  • packages/cli/src/index.ts
🧰 Additional context used
📓 Path-based instructions (1)
{packages,samples,tests}/**

📄 CodeRabbit inference engine (CLAUDE.md)

Packages are located in packages/, samples/, and tests/

Files:

  • packages/cli/src/actions/info.ts
⏰ 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). (2)
  • GitHub Check: claude-review
  • GitHub Check: build-test (20.x)
🔇 Additional comments (1)
packages/cli/src/actions/info.ts (1)

60-62: Skipping private packages is correct for workspace setups

Good call—this avoids listing non-publishable, workspace-only packages.

@ymc9 ymc9 merged commit 1d1f2c9 into dev Aug 31, 2025
6 checks passed
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