mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-16 04:50:29 -07:00
fa975395bc
Co-authored-by: Jerry Lin <jerrysf@google.com>
118 lines
3.4 KiB
JavaScript
118 lines
3.4 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import fs from 'node:fs';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const root = join(__dirname, '..');
|
|
const lockfilePath = join(root, 'package-lock.json');
|
|
|
|
function readJsonFile(filePath) {
|
|
try {
|
|
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
return JSON.parse(fileContent);
|
|
} catch (error) {
|
|
console.error(`Error reading or parsing ${filePath}:`, error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
console.log('Checking lockfile...');
|
|
|
|
const lockfile = readJsonFile(lockfilePath);
|
|
if (lockfile === null) {
|
|
process.exit(1);
|
|
}
|
|
const packages = lockfile.packages || {};
|
|
const invalidPackages = [];
|
|
|
|
for (const [location, details] of Object.entries(packages)) {
|
|
// 1. Skip the root package itself.
|
|
if (location === '') {
|
|
continue;
|
|
}
|
|
|
|
// 2. Skip local workspace packages.
|
|
// They are identifiable in two ways:
|
|
// a) As a symlink within node_modules.
|
|
// b) As the source package definition, whose path is not in node_modules.
|
|
if (details.link === true || !location.includes('node_modules')) {
|
|
continue;
|
|
}
|
|
|
|
// 3. Any remaining package should be a third-party dependency.
|
|
// 1) Registry package with both "resolved" and "integrity" fields is valid.
|
|
if (details.resolved && details.integrity) {
|
|
continue;
|
|
}
|
|
// 2) Git and file dependencies only need a "resolved" field.
|
|
const isGitOrFileDep =
|
|
details.resolved?.startsWith('git') ||
|
|
details.resolved?.startsWith('file:');
|
|
if (isGitOrFileDep) {
|
|
continue;
|
|
}
|
|
|
|
// Mark the left dependency as invalid.
|
|
invalidPackages.push(location);
|
|
}
|
|
|
|
if (invalidPackages.length > 0) {
|
|
console.error(
|
|
'\nError: The following dependencies in package-lock.json are missing the "resolved" or "integrity" field:',
|
|
);
|
|
invalidPackages.forEach((pkg) => console.error(`- ${pkg}`));
|
|
process.exitCode = 1;
|
|
} else {
|
|
console.log('Lockfile check passed.');
|
|
}
|
|
|
|
// Check that gaxios v7+ with stream corruption bug is NOT resolved in any workspace node_modules.
|
|
// gaxios v7.x (versions < 7.1.6) has a bug where Array.toString() joins stream chunks with
|
|
// commas, corrupting error response JSON at TCP chunk boundaries.
|
|
// See: https://github.com/google-gemini/gemini-cli/pull/21884
|
|
function isCorruptedGaxios(version) {
|
|
if (!version) return false;
|
|
const match = version.match(/^7\.(\d+)\.(\d+)/);
|
|
if (match) {
|
|
const minor = parseInt(match[1], 10);
|
|
const patch = parseInt(match[2], 10);
|
|
if (minor < 1 || (minor === 1 && patch < 6)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const gaxiosViolations = [];
|
|
for (const [location, details] of Object.entries(packages)) {
|
|
if (
|
|
location.match(/(^|\/)node_modules\/gaxios$/) &&
|
|
!location.includes('@google/genai/node_modules') &&
|
|
isCorruptedGaxios(details.version)
|
|
) {
|
|
gaxiosViolations.push(`${location} (v${details.version})`);
|
|
}
|
|
}
|
|
|
|
if (gaxiosViolations.length > 0) {
|
|
console.error(
|
|
'\nError: gaxios versions with stream corruption bug (v7.x < 7.1.6) detected in workspace node_modules.',
|
|
);
|
|
console.error('See: https://github.com/google-gemini/gemini-cli/pull/21884');
|
|
gaxiosViolations.forEach((v) => console.error(`- ${v}`));
|
|
console.error(
|
|
'\nPlease ensure gaxios resolves to a version containing the fix (>= 7.1.6).',
|
|
);
|
|
process.exitCode = 1;
|
|
}
|
|
|
|
if (!process.exitCode) {
|
|
process.exitCode = 0;
|
|
}
|