mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-06-02 15:13:15 -07:00
chore(scripts): make Windows preflight resilient by removing native linter dependencies and fixing EPERM locks
This commit is contained in:
Generated
+2497
-839
File diff suppressed because it is too large
Load Diff
+5
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@google/gemini-cli",
|
||||
"version": "0.35.0-nightly.20260311.657f19c1f",
|
||||
"version": "0.34.0-nightly.20260304.28af4e127",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
@@ -14,7 +14,7 @@
|
||||
"url": "git+https://github.com/google-gemini/gemini-cli.git"
|
||||
},
|
||||
"config": {
|
||||
"sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.35.0-nightly.20260311.657f19c1f"
|
||||
"sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.34.0-nightly.20260304.28af4e127"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "cross-env NODE_ENV=development node scripts/start.js",
|
||||
@@ -88,6 +88,7 @@
|
||||
"devDependencies": {
|
||||
"@agentclientprotocol/sdk": "^0.12.0",
|
||||
"@octokit/rest": "^22.0.0",
|
||||
"@tktco/node-actionlint": "^1.6.0",
|
||||
"@types/marked": "^5.0.2",
|
||||
"@types/mime-types": "^3.0.1",
|
||||
"@types/minimatch": "^5.1.2",
|
||||
@@ -126,11 +127,13 @@
|
||||
"react-devtools-core": "^6.1.2",
|
||||
"react-dom": "^19.2.0",
|
||||
"semver": "^7.7.2",
|
||||
"shellcheck": "^4.1.0",
|
||||
"strip-ansi": "^7.1.2",
|
||||
"ts-prune": "^0.10.3",
|
||||
"tsx": "^4.20.3",
|
||||
"typescript-eslint": "^8.30.1",
|
||||
"vitest": "^3.2.4",
|
||||
"yaml-lint": "^1.7.0",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
+7
-10
@@ -24,15 +24,15 @@ import { fileURLToPath } from 'node:url';
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const root = join(__dirname, '..');
|
||||
|
||||
// remove npm install/build artifacts
|
||||
rmSync(join(root, 'node_modules'), { recursive: true, force: true });
|
||||
rmSync(join(root, 'bundle'), { recursive: true, force: true });
|
||||
rmSync(join(root, 'packages/cli/src/generated/'), {
|
||||
const RMRF_OPTIONS = {
|
||||
recursive: true,
|
||||
force: true,
|
||||
});
|
||||
const RMRF_OPTIONS = { recursive: true, force: true };
|
||||
maxRetries: 10,
|
||||
retryDelay: 100,
|
||||
};
|
||||
rmSync(join(root, 'node_modules'), RMRF_OPTIONS);
|
||||
rmSync(join(root, 'bundle'), RMRF_OPTIONS);
|
||||
rmSync(join(root, 'packages/cli/src/generated/'), RMRF_OPTIONS);
|
||||
// Dynamically clean dist directories in all workspaces
|
||||
const rootPackageJson = JSON.parse(
|
||||
readFileSync(join(root, 'package.json'), 'utf-8'),
|
||||
@@ -57,10 +57,7 @@ for (const workspace of rootPackageJson.workspaces) {
|
||||
}
|
||||
|
||||
// Clean up vscode-ide-companion package
|
||||
rmSync(join(root, 'packages/vscode-ide-companion/node_modules'), {
|
||||
recursive: true,
|
||||
force: true,
|
||||
});
|
||||
rmSync(join(root, 'packages/vscode-ide-companion/node_modules'), RMRF_OPTIONS);
|
||||
|
||||
const vscodeCompanionDir = join(root, 'packages/vscode-ide-companion');
|
||||
try {
|
||||
|
||||
+13
-143
@@ -7,128 +7,15 @@
|
||||
*/
|
||||
|
||||
import { execSync } from 'node:child_process';
|
||||
import {
|
||||
mkdirSync,
|
||||
rmSync,
|
||||
readFileSync,
|
||||
existsSync,
|
||||
lstatSync,
|
||||
} from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const ACTIONLINT_VERSION = '1.7.7';
|
||||
const SHELLCHECK_VERSION = '0.11.0';
|
||||
const YAMLLINT_VERSION = '1.35.1';
|
||||
|
||||
const TEMP_DIR =
|
||||
process.env.GEMINI_LINT_TEMP_DIR || join(tmpdir(), 'gemini-cli-linters');
|
||||
|
||||
function getPlatformArch() {
|
||||
const platform = process.platform;
|
||||
const arch = process.arch;
|
||||
if (platform === 'linux' && arch === 'x64') {
|
||||
return {
|
||||
actionlint: 'linux_amd64',
|
||||
shellcheck: 'linux.x86_64',
|
||||
};
|
||||
}
|
||||
if (platform === 'darwin' && arch === 'x64') {
|
||||
return {
|
||||
actionlint: 'darwin_amd64',
|
||||
shellcheck: 'darwin.x86_64',
|
||||
};
|
||||
}
|
||||
if (platform === 'darwin' && arch === 'arm64') {
|
||||
return {
|
||||
actionlint: 'darwin_arm64',
|
||||
shellcheck: 'darwin.aarch64',
|
||||
};
|
||||
}
|
||||
if (platform === 'win32' && arch === 'x64') {
|
||||
return {
|
||||
actionlint: 'windows_amd64',
|
||||
// shellcheck is not used for Windows since it uses the .zip release
|
||||
// which has a consistent name across architectures
|
||||
};
|
||||
}
|
||||
throw new Error(`Unsupported platform/architecture: ${platform}/${arch}`);
|
||||
}
|
||||
|
||||
const platformArch = getPlatformArch();
|
||||
|
||||
const PYTHON_VENV_PATH = join(TEMP_DIR, 'python_venv');
|
||||
|
||||
const pythonVenvPythonPath = join(
|
||||
PYTHON_VENV_PATH,
|
||||
process.platform === 'win32' ? 'Scripts' : 'bin',
|
||||
process.platform === 'win32' ? 'python.exe' : 'python',
|
||||
);
|
||||
|
||||
const isWindows = process.platform === 'win32';
|
||||
|
||||
const actionlintCheck = isWindows
|
||||
? `where actionlint 2>nul`
|
||||
: 'command -v actionlint';
|
||||
|
||||
const actionlintInstaller = isWindows
|
||||
? `powershell -Command "` +
|
||||
`New-Item -ItemType Directory -Force -Path '${TEMP_DIR}/actionlint' | Out-Null; ` +
|
||||
`Invoke-WebRequest -Uri 'https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_${platformArch.actionlint}.zip' -OutFile '${TEMP_DIR}/.actionlint.zip'; ` +
|
||||
`Add-Type -AssemblyName System.IO.Compression.FileSystem; ` +
|
||||
`[System.IO.Compression.ZipFile]::ExtractToDirectory('${TEMP_DIR}/.actionlint.zip', '${TEMP_DIR}/actionlint')"`
|
||||
: `
|
||||
mkdir -p "${TEMP_DIR}/actionlint"
|
||||
curl -sSLo "${TEMP_DIR}/.actionlint.tgz" "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_${platformArch.actionlint}.tar.gz"
|
||||
tar -xzf "${TEMP_DIR}/.actionlint.tgz" -C "${TEMP_DIR}/actionlint"
|
||||
`;
|
||||
|
||||
const shellcheckCheck = isWindows
|
||||
? `where shellcheck 2>nul`
|
||||
: 'command -v shellcheck';
|
||||
|
||||
const shellcheckInstaller = isWindows
|
||||
? `powershell -Command "` +
|
||||
`Invoke-WebRequest -Uri 'https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.zip' -OutFile '${TEMP_DIR}/.shellcheck.zip'; ` +
|
||||
`Add-Type -AssemblyName System.IO.Compression.FileSystem; ` +
|
||||
`[System.IO.Compression.ZipFile]::ExtractToDirectory('${TEMP_DIR}/.shellcheck.zip', '${TEMP_DIR}/shellcheck')"`
|
||||
: `
|
||||
mkdir -p "${TEMP_DIR}/shellcheck"
|
||||
curl -sSLo "${TEMP_DIR}/.shellcheck.txz" "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.${platformArch.shellcheck}.tar.xz"
|
||||
tar -xf "${TEMP_DIR}/.shellcheck.txz" -C "${TEMP_DIR}/shellcheck" --strip-components=1
|
||||
`;
|
||||
|
||||
const yamllintCheck = isWindows
|
||||
? `if exist "${PYTHON_VENV_PATH}\\Scripts\\yamllint.exe" (exit 0) else (exit 1)`
|
||||
: `test -x "${PYTHON_VENV_PATH}/bin/yamllint"`;
|
||||
|
||||
const yamllintInstaller = isWindows
|
||||
? `python -m venv "${PYTHON_VENV_PATH}" && ` +
|
||||
`"${pythonVenvPythonPath}" -m pip install --upgrade pip && ` +
|
||||
`"${pythonVenvPythonPath}" -m pip install "yamllint==${YAMLLINT_VERSION}" --index-url https://pypi.org/simple`
|
||||
: `
|
||||
python3 -m venv "${PYTHON_VENV_PATH}" && \
|
||||
"${pythonVenvPythonPath}" -m pip install --upgrade pip && \
|
||||
"${pythonVenvPythonPath}" -m pip install "yamllint==${YAMLLINT_VERSION}" --index-url https://pypi.org/simple
|
||||
`;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* check: string;
|
||||
* installer: string;
|
||||
* run: string;
|
||||
* }}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {{[linterName: string]: Linter}}
|
||||
*/
|
||||
const LINTERS = {
|
||||
actionlint: {
|
||||
check: actionlintCheck,
|
||||
installer: actionlintInstaller,
|
||||
check: isWindows ? 'where npx node-actionlint 2>nul' : 'command -v npx node-actionlint',
|
||||
installer: 'npm install --save-dev @tktco/node-actionlint',
|
||||
run: `
|
||||
actionlint \
|
||||
npx node-actionlint \
|
||||
-color \
|
||||
-ignore 'SC2002:' \
|
||||
-ignore 'SC2016:' \
|
||||
@@ -137,12 +24,12 @@ const LINTERS = {
|
||||
`,
|
||||
},
|
||||
shellcheck: {
|
||||
check: shellcheckCheck,
|
||||
installer: shellcheckInstaller,
|
||||
check: isWindows ? 'where npx shellcheck 2>nul' : 'command -v npx shellcheck',
|
||||
installer: 'npm install --save-dev shellcheck',
|
||||
run: `
|
||||
git ls-files | grep -E '^([^.]+|.*\\.(sh|zsh|bash))' | xargs file --mime-type \
|
||||
| grep "text/x-shellscript" | awk '{ print substr($1, 1, length($1)-1) }' \
|
||||
| xargs shellcheck \
|
||||
| xargs npx shellcheck \
|
||||
--check-sourced \
|
||||
--enable=all \
|
||||
--exclude=SC2002,SC2129,SC2310 \
|
||||
@@ -152,30 +39,17 @@ const LINTERS = {
|
||||
`,
|
||||
},
|
||||
yamllint: {
|
||||
check: yamllintCheck,
|
||||
installer: yamllintInstaller,
|
||||
run: "git ls-files | grep -E '\\.(yaml|yml)' | xargs yamllint --format github",
|
||||
check: isWindows ? 'where npx yaml-lint 2>nul' : 'command -v npx yaml-lint',
|
||||
installer: 'npm install --save-dev yaml-lint',
|
||||
run: isWindows
|
||||
? `powershell -Command "Get-ChildItem -Recurse -Include *.yaml,*.yml | ForEach-Object { npx yaml-lint $_.FullName }"`
|
||||
: "git ls-files | grep -E '\\.(yaml|yml)' | xargs npx yaml-lint",
|
||||
},
|
||||
};
|
||||
|
||||
function runCommand(command, stdio = 'inherit') {
|
||||
try {
|
||||
const env = { ...process.env };
|
||||
const nodeBin = join(process.cwd(), 'node_modules', '.bin');
|
||||
const sep = isWindows ? ';' : ':';
|
||||
const pythonBin = isWindows
|
||||
? join(PYTHON_VENV_PATH, 'Scripts')
|
||||
: join(PYTHON_VENV_PATH, 'bin');
|
||||
// Windows sometimes uses 'Path' instead of 'PATH'
|
||||
const pathKey = 'Path' in env ? 'Path' : 'PATH';
|
||||
env[pathKey] = [
|
||||
nodeBin,
|
||||
join(TEMP_DIR, 'actionlint'),
|
||||
join(TEMP_DIR, 'shellcheck'),
|
||||
pythonBin,
|
||||
env[pathKey],
|
||||
].join(sep);
|
||||
execSync(command, { stdio, env, shell: true });
|
||||
execSync(command, { stdio, env: process.env, shell: true });
|
||||
return true;
|
||||
} catch (_e) {
|
||||
return false;
|
||||
@@ -184,11 +58,7 @@ function runCommand(command, stdio = 'inherit') {
|
||||
|
||||
export function setupLinters() {
|
||||
console.log('Setting up linters...');
|
||||
if (!process.env.GEMINI_LINT_TEMP_DIR) {
|
||||
rmSync(TEMP_DIR, { recursive: true, force: true });
|
||||
}
|
||||
mkdirSync(TEMP_DIR, { recursive: true });
|
||||
|
||||
|
||||
for (const linter in LINTERS) {
|
||||
const { check, installer } = LINTERS[linter];
|
||||
if (!runCommand(check, 'ignore')) {
|
||||
|
||||
Reference in New Issue
Block a user