From 667ca6d2416992e62f2830485c764cfd24258e73 Mon Sep 17 00:00:00 2001 From: Shreya Keshive Date: Fri, 3 Oct 2025 11:41:32 -0400 Subject: [PATCH] feat(ci): add ability to publish packages to private github registry for testing (#10348) --- .github/actions/publish-release/action.yml | 73 +++++++++++++++++----- .github/workflows/release-manual.yml | 13 +++- scripts/prepare-github-release.js | 63 +++++++++++++++++++ 3 files changed, 133 insertions(+), 16 deletions(-) create mode 100644 scripts/prepare-github-release.js diff --git a/.github/actions/publish-release/action.yml b/.github/actions/publish-release/action.yml index 479ea4ac90..cb82415a3a 100644 --- a/.github/actions/publish-release/action.yml +++ b/.github/actions/publish-release/action.yml @@ -48,7 +48,10 @@ inputs: gemini_api_key: description: 'The API key for running integration tests.' required: true - + registry: + description: 'The registry to publish to.' + required: false + default: 'npm-wombat' runs: using: 'composite' steps: @@ -103,14 +106,37 @@ runs: npm run build:packages npm run prepare:package - - name: 'Configure npm for publishing' + - name: '🎁 Bundle' + working-directory: '${{ inputs.working-directory }}' + shell: 'bash' + run: | + npm run bundle + + - name: '📦 Prepare for GitHub release' + if: "inputs.registry == 'github'" + working-directory: '${{ inputs.working-directory }}' + shell: 'bash' + run: | + node ${{ github.workspace }}/scripts/prepare-github-release.js + + - name: 'Configure npm for publishing to npm' + if: "inputs.registry != 'github'" uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' with: node-version-file: '${{ inputs.working-directory }}/.nvmrc' registry-url: 'https://wombat-dressing-room.appspot.com' scope: '@google' - - name: '📦 Publish @google/gemini-cli-core' + - name: 'Configure npm for publishing to GitHub' + if: "inputs.registry == 'github'" + uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' + with: + node-version-file: '${{ inputs.working-directory }}/.nvmrc' + registry-url: 'https://npm.pkg.github.com' + scope: '@google-gemini' + + - name: '📦 Publish @google/gemini-cli-core to npm' + if: "inputs.registry != 'github'" working-directory: '${{ inputs.working-directory }}' env: NODE_AUTH_TOKEN: '${{ inputs.wombat-token-core }}' @@ -122,16 +148,29 @@ runs: npm publish --workspace="@google/gemini-cli-core" --no-tag fi + - name: '📦 Publish @google-gemini/gemini-cli-core to GitHub' + if: "inputs.registry == 'github'" + working-directory: '${{ inputs.working-directory }}' + env: + NODE_AUTH_TOKEN: '${{ inputs.github-token }}' + shell: 'bash' + run: | + npm publish \ + --dry-run="${{ inputs.dry-run }}" \ + --workspace="@google-gemini/gemini-cli-core" \ + --no-tag + - name: '🔗 Install latest core package' working-directory: '${{ inputs.working-directory }}' - if: "${{ inputs.dry-run != 'true' }}" + if: "${{ inputs.dry-run != 'true' && inputs.registry != 'github' }}" shell: 'bash' run: | npm install "@google/gemini-cli-core@${{ inputs.release-version }}" \ --workspace="@google/gemini-cli" \ --save-exact - - name: '📦 Publish @google/gemini-cli' + - name: '📦 Publish @google/gemini-cli to npm' + if: "inputs.registry != 'github'" working-directory: '${{ inputs.working-directory }}' env: NODE_AUTH_TOKEN: '${{ inputs.wombat-token-cli }}' @@ -143,9 +182,21 @@ runs: npm publish --workspace="@google/gemini-cli" --no-tag fi + - name: '📦 Publish @google-gemini/gemini-cli to GitHub' + if: "inputs.registry == 'github'" + working-directory: '${{ inputs.working-directory }}' + env: + NODE_AUTH_TOKEN: '${{ inputs.github-token }}' + shell: 'bash' + run: | + npm publish \ + --dry-run="${{ inputs.dry-run }}" \ + --workspace="@google-gemini/gemini-cli" \ + --no-tag + - name: '🔬 Verify NPM release by version' uses: './.github/actions/verify-release' - if: "${{ inputs.dry-run != 'true' && inputs.force-skip-tests != 'true' }}" + if: "${{ inputs.dry-run != 'true' && inputs.force-skip-tests != 'true' && inputs.registry != 'github' }}" with: npm-package: '@google/gemini-cli@${{ inputs.release-version }}' expected-version: '${{ inputs.release-version }}' @@ -154,7 +205,7 @@ runs: - name: '🏷️ Tag release' uses: './.github/actions/tag-npm-release' - if: "${{ inputs.dry-run != 'true' }}" + if: "${{ inputs.dry-run != 'true' && inputs.registry != 'github' }}" with: channel: '${{ inputs.npm-tag }}' version: '${{ inputs.release-version }}' @@ -162,15 +213,9 @@ runs: wombat-token-core: '${{ inputs.wombat-token-core }}' wombat-token-cli: '${{ inputs.wombat-token-cli }}' - - name: '🎁 Bundle' - working-directory: '${{ inputs.working-directory }}' - shell: 'bash' - run: | - npm run bundle - - name: '🎉 Create GitHub Release' working-directory: '${{ inputs.working-directory }}' - if: "${{ inputs.dry-run != 'true' && inputs.skip-github-release != 'true' && inputs.npm-tag != 'dev' }}" + if: "${{ inputs.dry-run != 'true' && inputs.skip-github-release != 'true' && inputs.npm-tag != 'dev' && inputs.registry != 'github' }}" env: GITHUB_TOKEN: '${{ inputs.github-token }}' shell: 'bash' diff --git a/.github/workflows/release-manual.yml b/.github/workflows/release-manual.yml index 3d08610bb8..93b33c19ec 100644 --- a/.github/workflows/release-manual.yml +++ b/.github/workflows/release-manual.yml @@ -11,8 +11,16 @@ on: description: 'The branch, tag, or SHA to release from.' required: true type: 'string' + registry: + description: 'The registry to publish to.' + required: true + type: 'choice' + options: + - 'npm-wombat' + - 'github' + default: 'npm-wombat' npm_channel: - description: 'The npm channel to publish to.' + description: 'The npm channel to publish to (only used when registry is npm-wombat)' required: true type: 'choice' options: @@ -32,7 +40,7 @@ on: type: 'boolean' default: false skip_github_release: - description: 'Select to skip creating a GitHub release and create a npm release only.' + description: 'Select to skip creating a GitHub release (only used when registry is npm-wombat)' required: false type: 'boolean' default: false @@ -100,6 +108,7 @@ jobs: skip-github-release: '${{ github.event.inputs.skip_github_release }}' working-directory: './release' gemini_api_key: '${{ secrets.GEMINI_API_KEY }}' + registry: '${{ github.event.inputs.registry }}' - name: 'Create Issue on Failure' if: '${{ failure() && github.event.inputs.dry_run == false }}' diff --git a/scripts/prepare-github-release.js b/scripts/prepare-github-release.js new file mode 100644 index 0000000000..e30ca38a0f --- /dev/null +++ b/scripts/prepare-github-release.js @@ -0,0 +1,63 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import fs from 'node:fs'; +import path from 'node:path'; + +const rootDir = process.cwd(); + +function updatePackageJson(packagePath, updateFn) { + const packageJsonPath = path.resolve(rootDir, packagePath); + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + updateFn(packageJson); + fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); +} + +// Copy bundle directory into packages/cli +const sourceBundleDir = path.resolve(rootDir, 'bundle'); +const destBundleDir = path.resolve(rootDir, 'packages/cli/bundle'); + +if (fs.existsSync(sourceBundleDir)) { + fs.rmSync(destBundleDir, { recursive: true, force: true }); + fs.cpSync(sourceBundleDir, destBundleDir, { recursive: true }); + console.log('Copied bundle/ directory to packages/cli/'); +} else { + console.error( + 'Error: bundle/ directory not found at project root. Please run `npm run bundle` first.', + ); + process.exit(1); +} + +// Overwrite the .npmrc in the core package to point to the GitHub registry. +const coreNpmrcPath = path.resolve(rootDir, 'packages/core/.npmrc'); +fs.writeFileSync( + coreNpmrcPath, + '@google-gemini:registry=https://npm.pkg.github.com/', +); +console.log('Wrote .npmrc for @google-gemini scope to packages/core/'); + +// Update @google/gemini-cli +updatePackageJson('packages/cli/package.json', (pkg) => { + pkg.name = '@google-gemini/gemini-cli'; + pkg.files = ['bundle/']; + pkg.bin = { + gemini: 'bundle/gemini.js', + }; + + // Remove fields that are not relevant to the bundled package. + delete pkg.dependencies; + delete pkg.devDependencies; + delete pkg.scripts; + delete pkg.main; + delete pkg.config; // Deletes the sandboxImageUri +}); + +// Update @google/gemini-cli-core +updatePackageJson('packages/core/package.json', (pkg) => { + pkg.name = '@google-gemini/gemini-cli-core'; +}); + +console.log('Successfully prepared packages for GitHub release.');