Skip to content

Commit ede0991

Browse files
gennethYuna Seol
authored andcommitted
feat(release): ship esbuild bundle in npm package
The npm registry publish path ships unbundled dist/ plus full node_modules/ (44,835 files), causing ~1-2 minute cold starts on Windows due to Defender real-time scanning. The GitHub registry path already ships a single-file bundle with zero dependencies. Apply the same bundle transformation to the npm publish path: - Add scripts/prepare-npm-release.js that rewrites the CLI package.json to ship bundle/ instead of dist/, removes all dependencies, and adds optionalDependencies for native modules (node-pty, keytar) so platform-specific features keep working. - Add a "Prepare bundled CLI for npm release" step in the publish action, conditioned on non-GitHub registry URLs. Result: npm package drops from 44,835 files to ~129 files (6.8 MB). Closes #19169
1 parent 9c2fd5a commit ede0991

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

.github/actions/publish-release/action.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ runs:
181181
--workspace="${{ inputs.a2a-package-name }}" \
182182
--save-exact
183183
184+
- name: '📦 Prepare bundled CLI for npm release'
185+
if: "inputs.npm-registry-url != 'https://npm.pkg.github.com/'"
186+
working-directory: '${{ inputs.working-directory }}'
187+
shell: 'bash'
188+
run: |
189+
node ${{ github.workspace }}/scripts/prepare-npm-release.js
190+
184191
- name: 'Get CLI Token'
185192
uses: './.github/actions/npm-auth-token'
186193
id: 'cli-token'

scripts/prepare-npm-release.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* @license
3+
* Copyright 2025 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import fs from 'node:fs';
8+
import path from 'node:path';
9+
10+
const rootDir = process.cwd();
11+
12+
function readJson(filePath) {
13+
return JSON.parse(fs.readFileSync(path.resolve(rootDir, filePath), 'utf-8'));
14+
}
15+
16+
function writeJson(filePath, data) {
17+
fs.writeFileSync(
18+
path.resolve(rootDir, filePath),
19+
JSON.stringify(data, null, 2),
20+
);
21+
}
22+
23+
// Copy bundle directory into packages/cli
24+
const sourceBundleDir = path.resolve(rootDir, 'bundle');
25+
const destBundleDir = path.resolve(rootDir, 'packages/cli/bundle');
26+
27+
if (fs.existsSync(sourceBundleDir)) {
28+
fs.rmSync(destBundleDir, { recursive: true, force: true });
29+
fs.cpSync(sourceBundleDir, destBundleDir, { recursive: true });
30+
console.log('Copied bundle/ directory to packages/cli/');
31+
} else {
32+
console.error(
33+
'Error: bundle/ directory not found at project root. Please run `npm run bundle` first.',
34+
);
35+
process.exit(1);
36+
}
37+
38+
// Read native module versions from root package.json
39+
const rootPkg = readJson('package.json');
40+
const rootOptional = rootPkg.optionalDependencies || {};
41+
42+
const nativeModules = [
43+
'@lydell/node-pty',
44+
'@lydell/node-pty-darwin-arm64',
45+
'@lydell/node-pty-darwin-x64',
46+
'@lydell/node-pty-linux-x64',
47+
'@lydell/node-pty-win32-arm64',
48+
'@lydell/node-pty-win32-x64',
49+
'keytar',
50+
'node-pty',
51+
];
52+
53+
const optionalDependencies = {};
54+
for (const mod of nativeModules) {
55+
if (rootOptional[mod]) {
56+
optionalDependencies[mod] = rootOptional[mod];
57+
}
58+
}
59+
60+
// Update @google/gemini-cli package.json for bundled npm release
61+
const cliPkgPath = 'packages/cli/package.json';
62+
const cliPkg = readJson(cliPkgPath);
63+
64+
cliPkg.files = ['bundle/'];
65+
cliPkg.bin = {
66+
gemini: 'bundle/gemini.js',
67+
};
68+
69+
delete cliPkg.dependencies;
70+
delete cliPkg.devDependencies;
71+
delete cliPkg.scripts;
72+
delete cliPkg.main;
73+
delete cliPkg.config;
74+
75+
cliPkg.optionalDependencies = optionalDependencies;
76+
77+
writeJson(cliPkgPath, cliPkg);
78+
79+
console.log('Updated packages/cli/package.json for bundled npm release.');
80+
console.log(
81+
'optionalDependencies:',
82+
JSON.stringify(optionalDependencies, null, 2),
83+
);
84+
console.log('Successfully prepared packages for npm release.');

0 commit comments

Comments
 (0)