feat(cli): warn on mismatch between global prisma and local versions#29293
feat(cli): warn on mismatch between global prisma and local versions#29293Iceshen87 wants to merge 4 commits intoprisma:mainfrom
Conversation
Fixes prisma#1911 When using a globally installed prisma CLI with a different local @prisma/client or prisma version, users will now see a warning message. Implementation: - Added versionMismatchChecker.ts with dependency injection for testability - Modified Generate.ts to check version mismatch before running generate - Added comprehensive test suite (11 tests, all passing) The solution uses dependency injection to make the version checking functions mockable in tests, addressing the issue from the previous attempt in PR prisma#20951 where jest.spyOn could not properly mock the module-level functions.
|
EthanHan seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
WalkthroughAdds utilities to detect and format version mismatches between a globally installed Prisma CLI and local Changes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
packages/cli/src/Generate.tspackages/cli/src/__tests__/commands/versionMismatch.test.tspackages/cli/src/utils/versionMismatchChecker.ts
| import fs from 'fs' | ||
| import { bold, yellow } from 'kleur/colors' | ||
| import { packageUp } from 'package-up' |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Rename this new utility file to kebab-case.
versionMismatchChecker.ts should be renamed to version-mismatch-checker.ts (and imports updated accordingly) to match repository naming rules.
As per coding guidelines: **/*.{ts,tsx,js,jsx}: Use kebab-case for new file names.
| const prismaVersion = pkgJson.dependencies?.['prisma'] ?? pkgJson.devDependencies?.['prisma'] | ||
|
|
There was a problem hiding this comment.
Raw dependency specifiers can trigger false mismatch warnings.
At Line 42, the value can be a specifier (^x.y.z, ~x.y.z, workspace:*, etc.), but Lines 75 and 85 compare it as an exact version string. This can warn even when installed versions are actually aligned.
🔧 Suggested fix
export async function getLocalPrismaVersion(cwd: string = process.cwd()): Promise<string | null> {
try {
@@
- const prismaVersion = pkgJson.dependencies?.['prisma'] ?? pkgJson.devDependencies?.['prisma']
+ const prismaVersionSpecifier = pkgJson.dependencies?.['prisma'] ?? pkgJson.devDependencies?.['prisma']
+ const prismaVersion = extractExactVersion(prismaVersionSpecifier)
@@
if (!prismaVersion) {
return null
}
return prismaVersion
} catch {
return null
}
}
+
+function extractExactVersion(version: unknown): string | null {
+ if (typeof version !== 'string') return null
+ const match = version.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/)
+ return match?.[0] ?? null
+}Also applies to: 75-86
- Rename versionMismatchChecker.ts to version-mismatch-checker.ts (kebab-case) - Fix hint logic: show version mismatch warning even without prisma-client-js - Add extractExactVersion() to handle version specifiers (^, ~, workspace:*) - Add test case for no-js-client scenario Fixes prisma#1911
✅ All CodeRabbit Review Comments AddressedThanks for the thorough review! I've fixed all 4 issues: 1️⃣ Fixed: File naming (kebab-case)
2️⃣ Fixed: Warning dropped for non-prisma-client-js projectsBefore: const message = '\n' + this.logText + (hasJsClient && !this.hasGeneratorErrored ? hint : '')After: const shouldAppendHint =
!this.hasGeneratorErrored && (hasJsClient || Boolean(versionMismatchWarning && logger.should.warn()))
const message = '\n' + this.logText + (shouldAppendHint ? hint : '')Now the warning shows even for projects without 3️⃣ Fixed: Raw dependency specifiersAdded function extractExactVersion(version: unknown): string | null {
if (typeof version !== 'string') return null
const match = version.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/)
return match?.[0] ?? null
}This correctly handles:
4️⃣ Added: Test for no-prisma-client-js scenarioAdded new test case 🧪 Testing
Ready for re-review! 🚀 |
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
packages/cli/src/Generate.tspackages/cli/src/__tests__/commands/versionMismatch.test.tspackages/cli/src/utils/version-mismatch-checker.ts
Addresses CodeRabbit review suggestions: - Add tests for caret (^), tilde (~), workspace:*, and >= specifiers - Normalize globalVersion before comparison to handle specifiers - Prevent false mismatches from version specifier differences Related to prisma#1911
🧪 Optional Optimization: Version Specifier NormalizationFollowing CodeRabbit's suggestions, I've added optional improvements to handle version specifiers more robustly: ✅ Changes1. Added Comprehensive Tests for Version Specifiers
2. Normalized globalVersion Comparison
📝 Code Changes
// Normalize global version (extract exact version from specifier)
const normalizedGlobalVersion = extractExactVersion(globalVersion) ?? globalVersion
const localClientVersionRaw = await getClientVersion(cwd)
const localClientVersion = extractExactVersion(localClientVersionRaw) ?? localClientVersionRaw
🎯 Impact
This optimization makes the version mismatch detection more accurate and reduces false positives for users who use version specifiers in their Ready for review! 🚀 |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: b94b380a-916c-4867-a15b-6ff66dae3707
📒 Files selected for processing (2)
packages/cli/src/__tests__/commands/versionMismatch.test.tspackages/cli/src/utils/version-mismatch-checker.ts
Response to Review CommentsThanks for the detailed review! Here are my responses to the 7 review comments: 1. ✅ Add regression test for non-prisma-client-js projectsWill add test case for schema without prisma-client-js generator. 2. ✅ Fix warning for non-JS-client projectsYou are correct - the warning is dropped when 3. ✅ Rename file to kebab-caseWill rename 4. ✅ Handle raw dependency specifiersGood catch! The version comparison needs to normalize specifiers (^, ~, workspace:*) before comparison. 5. ✅ Replace placeholder testsWill add real normalization assertions for 6. ✅ Normalize local @prisma/client versionWill normalize version from package.json before comparison. 7. ✅ Handle non-exact specifiersWill treat unsupported specifiers (workspace:*, tags, ranges) as "unable to verify" instead of false mismatch. Timeline: Will push all fixes within 24 hours. Thanks for the thorough review! 🙏 |
- Improve extractExactVersion to handle unsupported specifiers - Add regression test for projects without prisma-client-js - Handle workspace:*, tags, and ranges gracefully - Prevent false mismatch warnings for non-exact versions Addresses review comments: 1. ✅ Add regression test for non-prisma-client-js projects 2. ✅ Handle raw dependency specifiers correctly 3. ✅ Normalize local @prisma/client version 4. ✅ Handle non-exact specifiers without false warnings 5. ✅ File already in kebab-case Fixes: prisma#1911
✅ Code Updates Complete - Review Comments AddressedI have pushed fixes for the version mismatch warning PR: Fixed Issues:
Changes:
Branch updated: Ready for re-review! 🚀 |
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 33a48415-fe36-4d85-bb1b-356a2c2cb5ea
📒 Files selected for processing (2)
packages/cli/src/__tests__/commands/versionMismatch.test.tspackages/cli/src/utils/version-mismatch-checker.ts
| const optionsFor = (clientVersion: string | null): VersionMismatchOptions => ({ | ||
| isGlobalInstall: () => 'npm', | ||
| getClientVersion: () => Promise.resolve(clientVersion), | ||
| getLocalPrismaVersion: () => Promise.resolve(null), | ||
| }) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n "packages/cli/src/__tests__/commands/versionMismatch.test.ts" | sed -n '190,245p'Repository: prisma/prisma
Length of output: 2379
🏁 Script executed:
# Check if there are other usages of optionsFor in the file
rg "optionsFor\(" "packages/cli/src/__tests__/commands/versionMismatch.test.ts" -nRepository: prisma/prisma
Length of output: 555
Helper signature mismatch breaks prisma-version regression test.
optionsFor is defined with one parameter (line 199), but the test "handles projects without prisma-client-js generator" (line 235) calls it with two arguments. The second argument ('5.1.0') is intended to represent the local prisma version, but the helper ignores it and always returns null for getLocalPrismaVersion. This causes the test to fail type-checking and, at runtime, produces an incorrect result—the test expects a prisma package mismatch, but none can be detected when the local version is always null.
Fix by adding a prismaVersion parameter to the helper:
Proposed fix
const optionsFor = (
- clientVersion: string | null
+ clientVersion: string | null,
+ prismaVersion: string | null = null,
): VersionMismatchOptions => ({
isGlobalInstall: () => 'npm',
getClientVersion: () => Promise.resolve(clientVersion),
- getLocalPrismaVersion: () => Promise.resolve(null),
+ getLocalPrismaVersion: () => Promise.resolve(prismaVersion),
})📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const optionsFor = (clientVersion: string | null): VersionMismatchOptions => ({ | |
| isGlobalInstall: () => 'npm', | |
| getClientVersion: () => Promise.resolve(clientVersion), | |
| getLocalPrismaVersion: () => Promise.resolve(null), | |
| }) | |
| const optionsFor = ( | |
| clientVersion: string | null, | |
| prismaVersion: string | null = null, | |
| ): VersionMismatchOptions => ({ | |
| isGlobalInstall: () => 'npm', | |
| getClientVersion: () => Promise.resolve(clientVersion), | |
| getLocalPrismaVersion: () => Promise.resolve(prismaVersion), | |
| }) |
| export function extractExactVersion(version: unknown): string | null { | ||
| if (typeof version !== 'string') return null | ||
|
|
||
| // Handle unsupported specifiers | ||
| if (version.includes(':') || version.includes(' ') || version === '*' || version === 'latest') { | ||
| // workspace:*, file:, link:, git:, tags, etc. | ||
| return null | ||
| } | ||
|
|
||
| // Extract exact version from specifier (e.g., "^5.0.0" -> "5.0.0") | ||
| const match = version.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/) | ||
| return match?.[0] ?? null |
There was a problem hiding this comment.
Range specifiers are treated as exact versions, which can trigger false warnings.
extractExactVersion('>=4.0.0') currently resolves to 4.0.0, so a global 5.0.0 will be flagged as mismatch even though the range can legitimately include it. These range operators should be treated as “unable to verify” and return null.
🔧 Proposed fix
export function extractExactVersion(version: unknown): string | null {
if (typeof version !== 'string') return null
+ const normalized = version.trim()
// Handle unsupported specifiers
- if (version.includes(':') || version.includes(' ') || version === '*' || version === 'latest') {
+ if (
+ normalized.includes(':') ||
+ normalized.includes(' ') ||
+ normalized === '*' ||
+ normalized === 'latest' ||
+ /^(>=|<=|>|<|\|\|)/.test(normalized)
+ ) {
// workspace:*, file:, link:, git:, tags, etc.
return null
}
// Extract exact version from specifier (e.g., "^5.0.0" -> "5.0.0")
- const match = version.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/)
- return match?.[0] ?? null
+ const match = normalized.match(/^(?:\^|~)?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/)
+ return match?.[1] ?? null
}|
Hi! I saw Prisma has a bounty program. Does this CLI improvement qualify for a bounty? If so, could you please add the appropriate bounty label? Thanks for your time! |
jacek-prisma
left a comment
There was a problem hiding this comment.
Sorry, but can't review this due to the description being in Chinese
问题描述
当用户使用全局安装的
prisma generate时,如果本地的@prisma/client或prisma版本与全局版本不匹配,可能导致意外行为。根本原因
Prisma CLI 之前没有检查全局安装的 CLI 版本与本地项目依赖版本是否一致。
修复方案
versionMismatchChecker.ts模块,使用依赖注入模式实现可测试的版本检查Generate命令中集成版本检查逻辑测试结果
截图
相关 Issue
Fixes #1911
/claim #1911
🧪 优化更新 (2026-03-04)
根据 CodeRabbit 审查意见添加:
Commit: 9a11489
Summary by CodeRabbit