mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-08-08 16:11:58 -07:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0fecabc368 | |||
| 7a42aa11d4 | |||
| 8826432034 | |||
| 6701f061a3 | |||
| ab84509eed | |||
| e98178ebcf | |||
| bd549fabd6 | |||
| d2e96b6c0a | |||
| b89f64341e | |||
| 3fa8a7e9fd | |||
| 1666218952 | |||
| 8c3f6ad220 | |||
| 69cb84d43e | |||
| 555105ddcb | |||
| 884d5a4aa2 | |||
| 4432c188e0 | |||
| 03cfcfca0b | |||
| 48a04d2d2d | |||
| 6b7a1150b5 | |||
| 7c81b1837e | |||
| 6502f99619 | |||
| aecfa04862 | |||
| 5d1d0d569f | |||
| 0c21f374f3 | |||
| 3e3d71297a | |||
| 82f2bd9b44 | |||
| cac05a838d | |||
| 4ee0820117 | |||
| 070b74bb83 | |||
| 973573ef49 | |||
| 6f4c9a5317 | |||
| 247ac33265 | |||
| c9a3d28d99 | |||
| 6831c79c0a | |||
| 14707b6d5e | |||
| a4b05d8346 | |||
| 256ccd8d23 | |||
| dea79901a5 | |||
| 0d55843c4a | |||
| 7b83236ab2 | |||
| 30770bf362 | |||
| d83ecc4585 | |||
| 1da17999c7 | |||
| 2797039239 | |||
| e03dc0d603 | |||
| 642adf350f | |||
| 6058c1be45 | |||
| f0541c35ac | |||
| b255e904fd | |||
| be08763cfa | |||
| dc2aa1ead7 | |||
| ce0bed07c6 | |||
| b6887db096 | |||
| a9834cc6c3 | |||
| 8a1d905fd6 | |||
| a35e4436a0 | |||
| f09e38ee0e | |||
| 8c9494eb70 | |||
| ec7f503d13 | |||
| b21a5a0c3c | |||
| 2f179d1886 | |||
| 430e9c68d7 | |||
| 2513dd929d | |||
| 9856a67b4c | |||
| 706a48629f | |||
| 17b3b264e6 | |||
| 20a2430d89 | |||
| a7395df23a | |||
| b4f6191704 | |||
| 2dde05deb0 | |||
| 6a6c344f49 | |||
| 4faa59fb72 | |||
| 208e9e24bf | |||
| 5b2ad83372 | |||
| 5e2d2ecf76 | |||
| 5fa0e5520f | |||
| 1a5742efec | |||
| 56f1ffe14f | |||
| 118e3176e8 | |||
| e03570f99e | |||
| 33fc71b22e | |||
| f6727cc14f | |||
| 2e0bf57e63 | |||
| 27fceb9679 | |||
| a6c9eaabf6 | |||
| dc3072c597 | |||
| 4a0b341575 | |||
| f0ccf3e52d | |||
| cc5ce59dca | |||
| 1eba9123de | |||
| 7226817a6b | |||
| 111c598ed9 | |||
| d66884a38b | |||
| 4155f7404b | |||
| 6038f48241 | |||
| af5b5d5ccc | |||
| 2530610a59 | |||
| 69f9bfb67b | |||
| 4955b470db | |||
| ff3398f297 | |||
| 8383974276 | |||
| 7bfa1de1b3 | |||
| a28ff41a75 | |||
| 46b1c59a47 | |||
| beed1515c2 | |||
| 5e58f5ea3c | |||
| 9fadff531a | |||
| 57789e2e34 | |||
| 989352f557 |
@@ -0,0 +1,47 @@
|
||||
# .github/actions/publish-bundle/action.yml
|
||||
name: 'Publish Bundle'
|
||||
description: 'Builds, versions, and publishes the bundled CLI package.'
|
||||
inputs:
|
||||
version:
|
||||
description: 'The version to publish the package with.'
|
||||
required: true
|
||||
tag:
|
||||
description: 'The npm dist-tag to publish the package with.'
|
||||
required: true
|
||||
github-token:
|
||||
description: 'GitHub token for authentication.'
|
||||
required: true
|
||||
package-scope:
|
||||
description: 'The npm scope to publish the package to.'
|
||||
required: false
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: 'Setup NPMRC'
|
||||
uses: './.github/actions/setup-npmrc'
|
||||
with:
|
||||
github-token: '${{ inputs.github-token }}'
|
||||
|
||||
- name: 'Bundle'
|
||||
shell: 'bash'
|
||||
run: 'npm run bundle'
|
||||
|
||||
- name: 'Prepare Package for Publishing'
|
||||
if: "${{ inputs.package-scope != '' }}"
|
||||
shell: 'bash'
|
||||
env:
|
||||
PACKAGE_SCOPE: '${{ inputs.package-scope }}'
|
||||
run: 'node scripts/prepare-package.js --scope=${{ env.PACKAGE_SCOPE }}'
|
||||
|
||||
- name: 'Set Version'
|
||||
shell: 'bash'
|
||||
env:
|
||||
PACKAGE_VERSION: '${{ inputs.version }}'
|
||||
run: 'npm version --no-git-tag-version "${{ env.PACKAGE_VERSION }}"'
|
||||
|
||||
- name: 'Publish to GitHub Packages'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ inputs.github-token }}'
|
||||
NPM_TAG: '${{ inputs.tag }}'
|
||||
shell: 'bash'
|
||||
run: 'npm publish --tag="${{ env.NPM_TAG }}"'
|
||||
@@ -0,0 +1,274 @@
|
||||
name: 'Publish Release (DEPRECATED)'
|
||||
description: 'Builds, prepares, and publishes the gemini-cli packages to npm and creates a GitHub release.'
|
||||
|
||||
inputs:
|
||||
release-version:
|
||||
description: 'The version to release (e.g., 0.1.11).'
|
||||
required: true
|
||||
npm-tag:
|
||||
description: 'The npm tag to publish with (e.g., latest, preview, nightly).'
|
||||
required: true
|
||||
wombat-token-core:
|
||||
description: 'The npm token for the cli-core package.'
|
||||
required: true
|
||||
wombat-token-cli:
|
||||
description: 'The npm token for the cli package.'
|
||||
required: true
|
||||
wombat-token-a2a-server:
|
||||
description: 'The npm token for the a2a package.'
|
||||
required: true
|
||||
github-token:
|
||||
description: 'The GitHub token for creating the release.'
|
||||
required: true
|
||||
dry-run:
|
||||
description: 'Whether to run in dry-run mode.'
|
||||
type: 'string'
|
||||
required: true
|
||||
release-tag:
|
||||
description: 'The release tag for the release (e.g., v0.1.11).'
|
||||
required: true
|
||||
previous-tag:
|
||||
description: 'The previous tag to use for generating release notes.'
|
||||
required: true
|
||||
skip-github-release:
|
||||
description: 'Whether to skip creating a GitHub release.'
|
||||
type: 'boolean'
|
||||
required: false
|
||||
default: false
|
||||
working-directory:
|
||||
description: 'The working directory to run the steps in.'
|
||||
required: false
|
||||
default: '.'
|
||||
force-skip-tests:
|
||||
description: 'Skip tests and validation'
|
||||
required: false
|
||||
default: false
|
||||
skip-branch-cleanup:
|
||||
description: 'Whether to skip cleaning up the release branch.'
|
||||
type: 'boolean'
|
||||
required: false
|
||||
default: false
|
||||
gemini_api_key:
|
||||
description: 'The API key for running integration tests.'
|
||||
required: true
|
||||
npm-registry-publish-url:
|
||||
description: 'npm registry publish url'
|
||||
required: true
|
||||
npm-registry-url:
|
||||
description: 'npm registry url'
|
||||
required: true
|
||||
npm-registry-scope:
|
||||
description: 'npm registry scope'
|
||||
required: true
|
||||
cli-package-name:
|
||||
description: 'The name of the cli package.'
|
||||
required: true
|
||||
core-package-name:
|
||||
description: 'The name of the core package.'
|
||||
required: true
|
||||
a2a-package-name:
|
||||
description: 'The name of the a2a package.'
|
||||
required: true
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: '📝 Print Inputs'
|
||||
shell: 'bash'
|
||||
env:
|
||||
JSON_INPUTS: '${{ toJSON(inputs) }}'
|
||||
run: 'echo "$JSON_INPUTS"'
|
||||
|
||||
- name: '👤 Configure Git User'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
git config user.name "gemini-cli-robot"
|
||||
git config user.email "gemini-cli-robot@google.com"
|
||||
|
||||
- name: '🌿 Create and switch to a release branch'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
id: 'release_branch'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
BRANCH_NAME="release/${{ inputs.release-tag }}"
|
||||
git switch -c "${BRANCH_NAME}"
|
||||
echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: '⬆️ Update package versions'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm run release:version "${{ inputs.release-version }}"
|
||||
|
||||
- name: '💾 Commit and Conditionally Push package versions'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
shell: 'bash'
|
||||
env:
|
||||
BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
|
||||
DRY_RUN: '${{ inputs.dry-run }}'
|
||||
RELEASE_TAG: '${{ inputs.release-tag }}'
|
||||
run: |-
|
||||
set -e
|
||||
git add package.json package-lock.json packages/*/package.json
|
||||
git commit -m "chore(release): ${RELEASE_TAG}"
|
||||
if [[ "${DRY_RUN}" == "false" ]]; then
|
||||
echo "Pushing release branch to remote..."
|
||||
git push --set-upstream origin "${BRANCH_NAME}" --follow-tags
|
||||
else
|
||||
echo "Dry run enabled. Skipping push."
|
||||
fi
|
||||
|
||||
- name: '🛠️ Build and Prepare Packages'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm run build:packages
|
||||
npm run prepare:package
|
||||
|
||||
- name: '🎁 Bundle'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm run bundle
|
||||
|
||||
# TODO: Refactor this github specific publishing script to be generalized based upon inputs.
|
||||
- name: '📦 Prepare for GitHub release'
|
||||
if: "inputs.npm-registry-url == 'https://npm.pkg.github.com/'"
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
node ${{ github.workspace }}/scripts/prepare-github-release.js
|
||||
|
||||
- name: 'Configure npm for publishing to npm'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020'
|
||||
with:
|
||||
node-version-file: '${{ inputs.working-directory }}/.nvmrc'
|
||||
registry-url: '${{inputs.npm-registry-publish-url}}'
|
||||
scope: '${{inputs.npm-registry-scope}}'
|
||||
|
||||
- name: 'Get core Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
id: 'core-token'
|
||||
with:
|
||||
package-name: '${{ inputs.core-package-name }}'
|
||||
github-token: '${{ inputs.github-token }}'
|
||||
wombat-token-core: '${{ inputs.wombat-token-core }}'
|
||||
wombat-token-cli: '${{ inputs.wombat-token-cli }}'
|
||||
wombat-token-a2a-server: '${{ inputs.wombat-token-a2a-server }}'
|
||||
|
||||
- name: '📦 Publish CORE to NPM'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.core-token.outputs.auth-token }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm publish \
|
||||
--dry-run="${{ inputs.dry-run }}" \
|
||||
--workspace="${{ inputs.core-package-name }}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${{ inputs.core-package-name }} false --silent
|
||||
|
||||
- name: '🔗 Install latest core package'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
if: "${{ inputs.dry-run != 'true' }}"
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm install "${{ inputs.core-package-name }}@${{ inputs.release-version }}" \
|
||||
--workspace="${{ inputs.cli-package-name }}" \
|
||||
--workspace="${{ inputs.a2a-package-name }}" \
|
||||
--save-exact
|
||||
|
||||
- name: 'Get CLI Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
id: 'cli-token'
|
||||
with:
|
||||
package-name: '${{ inputs.cli-package-name }}'
|
||||
github-token: '${{ inputs.github-token }}'
|
||||
wombat-token-core: '${{ inputs.wombat-token-core }}'
|
||||
wombat-token-cli: '${{ inputs.wombat-token-cli }}'
|
||||
wombat-token-a2a-server: '${{ inputs.wombat-token-a2a-server }}'
|
||||
|
||||
- name: '📦 Publish CLI'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.cli-token.outputs.auth-token }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm publish \
|
||||
--dry-run="${{ inputs.dry-run }}" \
|
||||
--workspace="${{ inputs.cli-package-name }}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${{ inputs.cli-package-name }} false --silent
|
||||
|
||||
- name: 'Get a2a-server Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
id: 'a2a-token'
|
||||
with:
|
||||
package-name: '${{ inputs.a2a-package-name }}'
|
||||
github-token: '${{ inputs.github-token }}'
|
||||
wombat-token-core: '${{ inputs.wombat-token-core }}'
|
||||
wombat-token-cli: '${{ inputs.wombat-token-cli }}'
|
||||
wombat-token-a2a-server: '${{ inputs.wombat-token-a2a-server }}'
|
||||
|
||||
- name: '📦 Publish a2a'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.a2a-token.outputs.auth-token }}'
|
||||
shell: 'bash'
|
||||
# Tag staging for initial release
|
||||
run: |
|
||||
npm publish \
|
||||
--dry-run="${{ inputs.dry-run }}" \
|
||||
--workspace="${{ inputs.a2a-package-name }}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${{ inputs.a2a-package-name }} false --silent
|
||||
|
||||
- name: '🔬 Verify NPM release by version'
|
||||
uses: './.github/actions/verify-release'
|
||||
if: "${{ inputs.dry-run != 'true' && inputs.force-skip-tests != 'true' }}"
|
||||
with:
|
||||
npm-package: '${{ inputs.cli-package-name }}@${{ inputs.release-version }}'
|
||||
expected-version: '${{ inputs.release-version }}'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
gemini_api_key: '${{ inputs.gemini_api_key }}'
|
||||
github-token: '${{ inputs.github-token }}'
|
||||
npm-registry-url: '${{ inputs.npm-registry-url }}'
|
||||
npm-registry-scope: '${{ inputs.npm-registry-scope }}'
|
||||
|
||||
- name: '🏷️ Tag release'
|
||||
uses: './.github/actions/tag-npm-release'
|
||||
with:
|
||||
channel: '${{ inputs.npm-tag }}'
|
||||
version: '${{ inputs.release-version }}'
|
||||
dry-run: '${{ inputs.dry-run }}'
|
||||
github-token: '${{ inputs.github-token }}'
|
||||
wombat-token-core: '${{ inputs.wombat-token-core }}'
|
||||
wombat-token-cli: '${{ inputs.wombat-token-cli }}'
|
||||
wombat-token-a2a-server: '${{ inputs.wombat-token-a2a-server }}'
|
||||
cli-package-name: '${{ inputs.cli-package-name }}'
|
||||
core-package-name: '${{ inputs.core-package-name }}'
|
||||
a2a-package-name: '${{ inputs.a2a-package-name }}'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
|
||||
- name: '🎉 Create GitHub Release'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
if: "${{ inputs.dry-run != 'true' && inputs.skip-github-release != 'true' && inputs.npm-tag != 'dev' && inputs.npm-registry-url != 'https://npm.pkg.github.com/' }}"
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ inputs.github-token }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
gh release create "${{ inputs.release-tag }}" \
|
||||
bundle/gemini.js \
|
||||
--target "${{ steps.release_branch.outputs.BRANCH_NAME }}" \
|
||||
--title "Release ${{ inputs.release-tag }}" \
|
||||
--notes-start-tag "${{ inputs.previous-tag }}" \
|
||||
--generate-notes
|
||||
|
||||
- name: '🧹 Clean up release branch'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
if: "${{ inputs.dry-run != 'true' && inputs.skip-branch-cleanup != 'true' }}"
|
||||
continue-on-error: true
|
||||
shell: 'bash'
|
||||
run: |
|
||||
echo "Cleaning up release branch ${{ steps.release_branch.outputs.BRANCH_NAME }}..."
|
||||
git push origin --delete "${{ steps.release_branch.outputs.BRANCH_NAME }}"
|
||||
@@ -46,7 +46,7 @@ runs:
|
||||
uses: 'docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1' # ratchet:docker/login-action@v3
|
||||
with:
|
||||
registry: 'ghcr.io'
|
||||
username: '${{ inputs.github-actor }}'
|
||||
username: '${{ github.repository_owner }}'
|
||||
password: '${{ inputs.github-secret }}'
|
||||
- name: 'Get branch name'
|
||||
id: 'branch_name'
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
name: 'Build and push sandbox docker'
|
||||
description: 'Pushes sandbox docker image to container registry'
|
||||
|
||||
inputs:
|
||||
github-actor:
|
||||
description: 'Github actor'
|
||||
required: true
|
||||
github-secret:
|
||||
description: 'Github secret'
|
||||
required: true
|
||||
dockerhub-username:
|
||||
description: 'Dockerhub username'
|
||||
required: true
|
||||
dockerhub-token:
|
||||
description: 'Dockerhub PAT w/ R+W'
|
||||
required: true
|
||||
github-sha:
|
||||
description: 'Github Commit SHA Hash'
|
||||
required: true
|
||||
github-ref-name:
|
||||
description: 'Github ref name'
|
||||
required: true
|
||||
dry-run:
|
||||
description: 'Whether this is a dry run.'
|
||||
required: true
|
||||
type: 'boolean'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: '📝 Print Inputs'
|
||||
shell: 'bash'
|
||||
env:
|
||||
JSON_INPUTS: '${{ toJSON(inputs) }}'
|
||||
run: 'echo "$JSON_INPUTS"'
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@v4'
|
||||
with:
|
||||
ref: '${{ inputs.github-sha }}'
|
||||
fetch-depth: 0
|
||||
- name: 'Install Dependencies'
|
||||
shell: 'bash'
|
||||
run: 'npm install'
|
||||
- name: 'npm build'
|
||||
shell: 'bash'
|
||||
run: 'npm run build'
|
||||
- name: 'Set up Docker Buildx'
|
||||
uses: 'docker/setup-buildx-action@v3'
|
||||
- name: 'Log in to GitHub Container Registry'
|
||||
uses: 'docker/login-action@v3'
|
||||
with:
|
||||
registry: 'docker.io'
|
||||
username: '${{ inputs.dockerhub-username }}'
|
||||
password: '${{ inputs.dockerhub-token }}'
|
||||
- name: 'determine image tag'
|
||||
id: 'image_tag'
|
||||
shell: 'bash'
|
||||
run: |-
|
||||
SHELL_TAG_NAME="${{ inputs.github-ref-name }}"
|
||||
FINAL_TAG="${{ inputs.github-sha }}"
|
||||
if [[ "$SHELL_TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then
|
||||
echo "Release detected."
|
||||
FINAL_TAG="${SHELL_TAG_NAME#v}"
|
||||
else
|
||||
echo "Development release detected. Using commit SHA as tag."
|
||||
fi
|
||||
echo "Determined image tag: $FINAL_TAG"
|
||||
echo "FINAL_TAG=$FINAL_TAG" >> $GITHUB_OUTPUT
|
||||
- name: 'build'
|
||||
id: 'docker_build'
|
||||
shell: 'bash'
|
||||
env:
|
||||
GEMINI_SANDBOX_IMAGE_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
|
||||
GEMINI_SANDBOX: 'docker'
|
||||
run: |-
|
||||
npm run build:sandbox -- \
|
||||
--image google/gemini-cli-sandbox:${{ steps.image_tag.outputs.FINAL_TAG }} \
|
||||
--output-file final_image_uri.txt
|
||||
echo "uri=$(cat final_image_uri.txt)" >> $GITHUB_OUTPUT
|
||||
- name: 'publish'
|
||||
shell: 'bash'
|
||||
if: "${{ inputs.dry-run != 'true' }}"
|
||||
run: |-
|
||||
docker push "${{ steps.docker_build.outputs.uri }}"
|
||||
- name: 'Create issue on failure'
|
||||
if: |-
|
||||
${{ failure() }}
|
||||
shell: 'bash'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ inputs.github-secret }}'
|
||||
DETAILS_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||
run: |-
|
||||
gh issue create \
|
||||
--title "Docker build failed" \
|
||||
--body "The docker build failed. See the full run for details: ${DETAILS_URL}" \
|
||||
--label "kind/bug,release-failure"
|
||||
@@ -0,0 +1,124 @@
|
||||
# .github/workflows/build-and-publish.yml
|
||||
name: 'Build and Publish Bundle'
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cli-package-name:
|
||||
description: 'The name of the CLI package.'
|
||||
required: true
|
||||
type: 'string'
|
||||
npm-registry-scope:
|
||||
description: 'NPM registry scope'
|
||||
required: true
|
||||
type: 'string'
|
||||
npm-registry-url:
|
||||
description: 'NPM registry URL'
|
||||
required: true
|
||||
type: 'string'
|
||||
outputs:
|
||||
version:
|
||||
description: 'The version of the published package'
|
||||
value: '${{ jobs.publish-bundle.outputs.version }}'
|
||||
image-uri:
|
||||
description: 'The URI of the built sandbox image.'
|
||||
value: '${{ jobs.build-and-publish-sandbox.outputs.image-uri }}'
|
||||
|
||||
jobs:
|
||||
publish-bundle:
|
||||
name: 'Publish Bundle'
|
||||
runs-on: 'ubuntu-latest'
|
||||
outputs:
|
||||
version: '${{ steps.vars.outputs.version }}'
|
||||
permissions:
|
||||
contents: 'read'
|
||||
packages: 'write'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
ref: '${{ github.event.inputs.branch_ref || github.ref }}'
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4.4.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install Dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Calculate Version and Tag'
|
||||
id: 'vars'
|
||||
run: |
|
||||
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
||||
NEW_VERSION="${CURRENT_VERSION}-ci.${{ github.run_number }}.${{ github.sha }}"
|
||||
echo "version=${NEW_VERSION}" >> "$GITHUB_OUTPUT"
|
||||
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||
echo "tag=pr-${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "tag=ci" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- name: 'Publish Bundle'
|
||||
uses: './.github/actions/publish-bundle'
|
||||
with:
|
||||
version: '${{ steps.vars.outputs.version }}'
|
||||
tag: '${{ steps.vars.outputs.tag }}'
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
package-scope: '${{ inputs.npm-registry-scope }}'
|
||||
|
||||
build-and-publish-sandbox:
|
||||
name: 'Build and Publish Sandbox'
|
||||
runs-on: 'ubuntu-latest'
|
||||
needs: 'publish-bundle'
|
||||
outputs:
|
||||
image-uri: '${{ steps.docker_build.outputs.uri }}'
|
||||
permissions:
|
||||
contents: 'read'
|
||||
packages: 'write'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
ref: '${{ github.event.inputs.branch_ref || github.ref }}'
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4.4.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Setup NPMRC'
|
||||
uses: './.github/actions/setup-npmrc'
|
||||
with:
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
|
||||
- name: 'Log in to GitHub Container Registry'
|
||||
uses: 'docker/login-action@v3'
|
||||
with:
|
||||
registry: 'ghcr.io'
|
||||
username: '${{ github.repository_owner }}'
|
||||
password: '${{ secrets.GITHUB_TOKEN }}'
|
||||
|
||||
- name: 'Set up Docker Buildx'
|
||||
uses: 'docker/setup-buildx-action@v3'
|
||||
|
||||
- name: 'Build and Push Sandbox Image'
|
||||
id: 'docker_build'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
IMAGE_TAG="ghcr.io/${{ github.repository }}/sandbox:${{ needs.publish-bundle.outputs.version }}"
|
||||
docker build . \
|
||||
--file Dockerfile \
|
||||
--tag "${IMAGE_TAG}" \
|
||||
--build-arg CLI_VERSION=${{ needs.publish-bundle.outputs.version }} \
|
||||
--build-arg NPM_REGISTRY_SCOPE=${{ inputs.npm-registry-scope }} \
|
||||
--build-arg NPM_REGISTRY_URL=${{ inputs.npm-registry-url }} \
|
||||
--build-arg CLI_PACKAGE_NAME=${{ inputs.cli-package-name }} \
|
||||
--secret id=GITHUB_TOKEN
|
||||
docker push "${IMAGE_TAG}"
|
||||
echo "uri=${IMAGE_TAG}" >> "$GITHUB_OUTPUT"
|
||||
@@ -0,0 +1,50 @@
|
||||
# .github/workflows/bundle-size.yml
|
||||
name: 'Bundle Size Check'
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
version:
|
||||
description: 'The version of the published package'
|
||||
required: true
|
||||
type: 'string'
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
pull-requests: 'write'
|
||||
packages: 'read'
|
||||
|
||||
jobs:
|
||||
bundle-size:
|
||||
name: 'Check Bundle Size'
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
ref: '${{ github.event.inputs.branch_ref || github.ref }}'
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Setup NPMRC'
|
||||
uses: './.github/actions/setup-npmrc'
|
||||
with:
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
env:
|
||||
VERSION: '${{ inputs.version }}'
|
||||
run: 'npm install @google-gemini/gemini-cli@${{ env.VERSION }}'
|
||||
|
||||
- name: 'Check Bundle Size'
|
||||
uses: 'preactjs/compressed-size-action@946a292cd35bd1088e0d7eb92b69d1a8d5b5d76a'
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
pattern: './bundle/**/*.{js,sb}'
|
||||
minimum-change-threshold: '1000'
|
||||
compression: 'none'
|
||||
clean-script: 'clean'
|
||||
+17
-189
@@ -1,121 +1,27 @@
|
||||
name: 'Testing: CI'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'release/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'release/**'
|
||||
merge_group:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch_ref:
|
||||
description: 'Branch to run on'
|
||||
required: true
|
||||
default: 'main'
|
||||
type: 'string'
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}'
|
||||
cancel-in-progress: |-
|
||||
${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/heads/release/') }}
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
checks: 'write'
|
||||
contents: 'read'
|
||||
statuses: 'write'
|
||||
packages: 'read'
|
||||
pull-requests: 'write'
|
||||
actions: 'read'
|
||||
security-events: 'write'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: 'bash'
|
||||
|
||||
jobs:
|
||||
merge_queue_skipper:
|
||||
permissions: 'read-all'
|
||||
name: 'Merge Queue Skipper'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
outputs:
|
||||
skip: '${{ steps.merge-queue-ci-skipper.outputs.skip-check }}'
|
||||
steps:
|
||||
- id: 'merge-queue-ci-skipper'
|
||||
uses: 'cariad-tech/merge-queue-ci-skipper@1032489e59437862c90a08a2c92809c903883772' # ratchet:cariad-tech/merge-queue-ci-skipper@main
|
||||
with:
|
||||
secret: '${{ secrets.GITHUB_TOKEN }}'
|
||||
|
||||
lint:
|
||||
name: 'Lint'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
ref: '${{ github.event.inputs.branch_ref || github.ref }}'
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4.4.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Validate NOTICES.txt'
|
||||
run: 'git diff --exit-code packages/vscode-ide-companion/NOTICES.txt'
|
||||
|
||||
- name: 'Check lockfile'
|
||||
run: 'npm run check:lockfile'
|
||||
|
||||
- name: 'Install linters'
|
||||
run: 'node scripts/lint.js --setup'
|
||||
|
||||
- name: 'Run ESLint'
|
||||
run: 'node scripts/lint.js --eslint'
|
||||
|
||||
- name: 'Run actionlint'
|
||||
run: 'node scripts/lint.js --actionlint'
|
||||
|
||||
- name: 'Run shellcheck'
|
||||
run: 'node scripts/lint.js --shellcheck'
|
||||
|
||||
- name: 'Run yamllint'
|
||||
run: 'node scripts/lint.js --yamllint'
|
||||
|
||||
- name: 'Run Prettier'
|
||||
run: 'node scripts/lint.js --prettier'
|
||||
|
||||
- name: 'Run sensitive keyword linter'
|
||||
run: 'node scripts/lint.js --sensitive-keywords'
|
||||
|
||||
link_checker:
|
||||
name: 'Link Checker'
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
- name: 'Link Checker'
|
||||
uses: 'lycheeverse/lychee-action@885c65f3dc543b57c898c8099f4e08c8afd178a2' # ratchet: lycheeverse/lychee-action@v2.6.1
|
||||
with:
|
||||
args: '--verbose ./**/*.md'
|
||||
fail: true
|
||||
test_linux:
|
||||
name: 'Test (Linux)'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs:
|
||||
- 'lint'
|
||||
- 'merge_queue_skipper'
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
permissions:
|
||||
contents: 'read'
|
||||
checks: 'write'
|
||||
pull-requests: 'write'
|
||||
runs-on: 'ubuntu-latest'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version:
|
||||
- '20.x'
|
||||
@@ -131,10 +37,7 @@ jobs:
|
||||
node-version: '${{ matrix.node-version }}'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
|
||||
- name: 'Install dependencies for testing'
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Run tests and generate reports'
|
||||
@@ -142,12 +45,6 @@ jobs:
|
||||
NO_COLOR: true
|
||||
run: 'npm run test:ci'
|
||||
|
||||
- name: 'Bundle'
|
||||
run: 'npm run bundle'
|
||||
|
||||
- name: 'Smoke test bundle'
|
||||
run: 'node ./bundle/gemini.js --version'
|
||||
|
||||
- name: 'Wait for file system sync'
|
||||
run: 'sleep 2'
|
||||
|
||||
@@ -172,16 +69,9 @@ jobs:
|
||||
test_mac:
|
||||
name: 'Test (Mac)'
|
||||
runs-on: '${{ matrix.os }}'
|
||||
needs:
|
||||
- 'lint'
|
||||
- 'merge_queue_skipper'
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
permissions:
|
||||
contents: 'read'
|
||||
checks: 'write'
|
||||
pull-requests: 'write'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- 'macos-latest'
|
||||
@@ -199,10 +89,7 @@ jobs:
|
||||
node-version: '${{ matrix.node-version }}'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
|
||||
- name: 'Install dependencies for testing'
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Run tests and generate reports'
|
||||
@@ -210,12 +97,6 @@ jobs:
|
||||
NO_COLOR: true
|
||||
run: 'npm run test:ci -- --coverage.enabled=false'
|
||||
|
||||
- name: 'Bundle'
|
||||
run: 'npm run bundle'
|
||||
|
||||
- name: 'Smoke test bundle'
|
||||
run: 'node ./bundle/gemini.js --version'
|
||||
|
||||
- name: 'Wait for file system sync'
|
||||
run: 'sleep 2'
|
||||
|
||||
@@ -247,13 +128,7 @@ jobs:
|
||||
|
||||
codeql:
|
||||
name: 'CodeQL'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
permissions:
|
||||
actions: 'read'
|
||||
contents: 'read'
|
||||
security-events: 'write'
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
@@ -268,37 +143,12 @@ jobs:
|
||||
- name: 'Perform CodeQL Analysis'
|
||||
uses: 'github/codeql-action/analyze@df559355d593797519d70b90fc8edd5db049e7a2' # ratchet:github/codeql-action/analyze@v3
|
||||
|
||||
# Check for changes in bundle size.
|
||||
bundle_size:
|
||||
name: 'Check Bundle Size'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "${{github.event_name == 'pull_request' && needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
permissions:
|
||||
contents: 'read' # For checkout
|
||||
pull-requests: 'write' # For commenting
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
ref: '${{ github.event.inputs.branch_ref || github.ref }}'
|
||||
fetch-depth: 1
|
||||
|
||||
- uses: 'preactjs/compressed-size-action@946a292cd35bd1088e0d7eb92b69d1a8d5b5d76a'
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
pattern: './bundle/**/*.{js,sb}'
|
||||
minimum-change-threshold: '1000'
|
||||
compression: 'none'
|
||||
clean-script: 'clean'
|
||||
|
||||
test_windows:
|
||||
name: 'Slow Test - Win'
|
||||
runs-on: 'gemini-cli-windows-16-core'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
runs-on: 'windows-latest'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
@@ -334,14 +184,6 @@ jobs:
|
||||
run: 'npm ci'
|
||||
shell: 'pwsh'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
shell: 'pwsh'
|
||||
env:
|
||||
NODE_OPTIONS: '--max-old-space-size=32768 --max-semi-space-size=256'
|
||||
UV_THREADPOOL_SIZE: '32'
|
||||
NODE_ENV: 'production'
|
||||
|
||||
- name: 'Run tests and generate reports'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
@@ -352,34 +194,20 @@ jobs:
|
||||
run: 'npm run test:ci -- --coverage.enabled=false'
|
||||
shell: 'pwsh'
|
||||
|
||||
- name: 'Bundle'
|
||||
run: 'npm run bundle'
|
||||
shell: 'pwsh'
|
||||
|
||||
- name: 'Smoke test bundle'
|
||||
run: 'node ./bundle/gemini.js --version'
|
||||
shell: 'pwsh'
|
||||
|
||||
ci:
|
||||
name: 'CI'
|
||||
if: 'always()'
|
||||
needs:
|
||||
- 'lint'
|
||||
- 'link_checker'
|
||||
- 'test_linux'
|
||||
- 'test_mac'
|
||||
- 'codeql'
|
||||
- 'bundle_size'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Check all job results'
|
||||
run: |
|
||||
if [[ (${{ needs.lint.result }} != 'success' && ${{ needs.lint.result }} != 'skipped') || \
|
||||
(${{ needs.link_checker.result }} != 'success' && ${{ needs.link_checker.result }} != 'skipped') || \
|
||||
(${{ needs.test_linux.result }} != 'success' && ${{ needs.test_linux.result }} != 'skipped') || \
|
||||
if [[ (${{ needs.test_linux.result }} != 'success' && ${{ needs.test_linux.result }} != 'skipped') || \
|
||||
(${{ needs.test_mac.result }} != 'success' && ${{ needs.test_mac.result }} != 'skipped') || \
|
||||
(${{ needs.codeql.result }} != 'success' && ${{ needs.codeql.result }} != 'skipped') || \
|
||||
(${{ needs.bundle_size.result }} != 'success' && ${{ needs.bundle_size.result }} != 'skipped') ]]; then
|
||||
(${{ needs.codeql.result }} != 'success' && ${{ needs.codeql.result }} != 'skipped') ]]; then
|
||||
echo "One or more CI jobs failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+67
-77
@@ -1,56 +1,32 @@
|
||||
name: 'Testing: E2E'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
# This will run for PRs from the base repository, providing secrets.
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'release/**'
|
||||
# This will run for PRs from forks when a label is added.
|
||||
pull_request_target:
|
||||
types: ['labeled']
|
||||
merge_group:
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
branch_ref:
|
||||
description: 'Branch to run on'
|
||||
version:
|
||||
description: 'The version of the published package'
|
||||
required: true
|
||||
default: 'main'
|
||||
type: 'string'
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}'
|
||||
cancel-in-progress: |-
|
||||
${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/heads/release/') }}
|
||||
cli-package-name:
|
||||
description: 'The name of the CLI package to install'
|
||||
required: true
|
||||
type: 'string'
|
||||
image-uri:
|
||||
description: 'The URI of the built sandbox image.'
|
||||
required: true
|
||||
type: 'string'
|
||||
secrets:
|
||||
GEMINI_API_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
merge_queue_skipper:
|
||||
name: 'Merge Queue Skipper'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
permissions: 'read-all'
|
||||
outputs:
|
||||
skip: '${{ steps.merge-queue-e2e-skipper.outputs.skip-check }}'
|
||||
steps:
|
||||
- id: 'merge-queue-e2e-skipper'
|
||||
uses: 'cariad-tech/merge-queue-ci-skipper@1032489e59437862c90a08a2c92809c903883772' # ratchet:cariad-tech/merge-queue-ci-skipper@main
|
||||
with:
|
||||
secret: '${{ secrets.GITHUB_TOKEN }}'
|
||||
continue-on-error: true
|
||||
|
||||
e2e_linux:
|
||||
name: 'E2E Test (Linux) - ${{ matrix.sandbox }}'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: |
|
||||
(needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip == 'false') &&
|
||||
(github.event_name == 'push' ||
|
||||
github.event_name == 'push' ||
|
||||
github.event_name == 'merge_group' ||
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(github.event.pull_request.head.repo.full_name == github.repository) ||
|
||||
(github.event.label.name == 'maintainer:e2e:ok'))
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
github.event.pull_request.head.repo.full_name == github.repository ||
|
||||
github.event.label.name == 'maintainer:e2e:ok'
|
||||
runs-on: 'ubuntu-latest'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -59,7 +35,6 @@ jobs:
|
||||
- 'sandbox:docker'
|
||||
node-version:
|
||||
- '20.x'
|
||||
|
||||
steps:
|
||||
- name: 'Checkout (fork)'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
@@ -74,26 +49,34 @@ jobs:
|
||||
with:
|
||||
ref: '${{ github.event.inputs.branch_ref || github.ref }}'
|
||||
|
||||
- name: 'Set up Node.js ${{ matrix.node-version }}'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
|
||||
- name: 'Setup NPMRC'
|
||||
uses: './.github/actions/setup-npmrc'
|
||||
with:
|
||||
node-version: '${{ matrix.node-version }}'
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
|
||||
- name: 'Log in to GitHub Container Registry'
|
||||
uses: 'docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1' # ratchet:docker/login-action@v3
|
||||
with:
|
||||
registry: 'ghcr.io'
|
||||
username: '${{ github.repository_owner }}'
|
||||
password: '${{ secrets.GITHUB_TOKEN }}'
|
||||
|
||||
- name: 'Pull sandbox image'
|
||||
run: 'docker pull ${{ inputs.image-uri }}'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
|
||||
- name: 'Set up Docker'
|
||||
if: "matrix.sandbox == 'sandbox:docker'"
|
||||
uses: 'docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435' # ratchet:docker/setup-buildx-action@v3
|
||||
env:
|
||||
CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
VERSION: '${{ inputs.version }}'
|
||||
run: 'npm install ${{ env.CLI_PACKAGE_NAME }}@${{ env.VERSION }}'
|
||||
|
||||
- name: 'Run E2E tests'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
KEEP_OUTPUT: 'true'
|
||||
VERBOSE: 'true'
|
||||
INTEGRATION_TEST_USE_INSTALLED_GEMINI: 'true'
|
||||
GEMINI_SANDBOX_IMAGE: '${{ inputs.image-uri }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
if [[ "${{ matrix.sandbox }}" == "sandbox:docker" ]]; then
|
||||
@@ -104,14 +87,12 @@ jobs:
|
||||
|
||||
e2e_mac:
|
||||
name: 'E2E Test (macOS)'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: |
|
||||
(needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip == 'false') &&
|
||||
(github.event_name == 'push' ||
|
||||
github.event_name == 'push' ||
|
||||
github.event_name == 'merge_group' ||
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(github.event.pull_request.head.repo.full_name == github.repository) ||
|
||||
(github.event.label.name == 'maintainer:e2e:ok'))
|
||||
github.event.pull_request.head.repo.full_name == github.repository ||
|
||||
github.event.label.name == 'maintainer:e2e:ok'
|
||||
runs-on: 'macos-latest'
|
||||
steps:
|
||||
- name: 'Checkout (fork)'
|
||||
@@ -132,11 +113,16 @@ jobs:
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
- name: 'Setup NPMRC'
|
||||
uses: './.github/actions/setup-npmrc'
|
||||
with:
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
- name: 'Install dependencies'
|
||||
env:
|
||||
CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
VERSION: '${{ inputs.version }}'
|
||||
run: 'npm install ${{ env.CLI_PACKAGE_NAME }}@${{ env.VERSION }}'
|
||||
|
||||
- name: 'Fix rollup optional dependencies on macOS'
|
||||
if: "runner.os == 'macOS'"
|
||||
@@ -149,19 +135,18 @@ jobs:
|
||||
KEEP_OUTPUT: 'true'
|
||||
SANDBOX: 'sandbox:none'
|
||||
VERBOSE: 'true'
|
||||
INTEGRATION_TEST_USE_INSTALLED_GEMINI: 'true'
|
||||
run: 'npm run test:integration:sandbox:none'
|
||||
|
||||
e2e_windows:
|
||||
name: 'Slow E2E - Win'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: |
|
||||
(needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip == 'false') &&
|
||||
(github.event_name == 'push' ||
|
||||
github.event_name == 'push' ||
|
||||
github.event_name == 'merge_group' ||
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(github.event.pull_request.head.repo.full_name == github.repository) ||
|
||||
(github.event.label.name == 'maintainer:e2e:ok'))
|
||||
runs-on: 'gemini-cli-windows-16-core'
|
||||
github.event.pull_request.head.repo.full_name == github.repository ||
|
||||
github.event.label.name == 'maintainer:e2e:ok'
|
||||
runs-on: 'windows-latest'
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
@@ -202,12 +187,16 @@ jobs:
|
||||
npm config set registry https://registry.npmjs.org/
|
||||
shell: 'pwsh'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
shell: 'pwsh'
|
||||
- name: 'Setup NPMRC'
|
||||
uses: './.github/actions/setup-npmrc'
|
||||
with:
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
- name: 'Install dependencies'
|
||||
env:
|
||||
CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
VERSION: '${{ inputs.version }}'
|
||||
run: 'npm install ${{ env.CLI_PACKAGE_NAME }}@${{ env.VERSION }}'
|
||||
shell: 'pwsh'
|
||||
|
||||
- name: 'Run E2E tests'
|
||||
@@ -219,6 +208,7 @@ jobs:
|
||||
NODE_OPTIONS: '--max-old-space-size=32768 --max-semi-space-size=256'
|
||||
UV_THREADPOOL_SIZE: '32'
|
||||
NODE_ENV: 'test'
|
||||
INTEGRATION_TEST_USE_INSTALLED_GEMINI: 'true'
|
||||
shell: 'pwsh'
|
||||
run: 'npm run test:integration:sandbox:none'
|
||||
|
||||
@@ -229,13 +219,13 @@ jobs:
|
||||
github.event_name == 'push' ||
|
||||
github.event_name == 'merge_group' ||
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(github.event.pull_request.head.repo.full_name == github.repository) ||
|
||||
(github.event.label.name == 'maintainer:e2e:ok')
|
||||
github.event.pull_request.head.repo.full_name == github.repository ||
|
||||
github.event.label.name == 'maintainer:e2e:ok'
|
||||
)
|
||||
needs:
|
||||
- 'e2e_linux'
|
||||
- 'e2e_mac'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Check E2E test results'
|
||||
run: |
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# .github/workflows/lint.yml
|
||||
name: 'Linting'
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: 'Lint All'
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci --only=dev'
|
||||
|
||||
- name: 'Run linting'
|
||||
run: 'npm run lint:all'
|
||||
@@ -0,0 +1,91 @@
|
||||
# .github/workflows/pr-checks.yml
|
||||
name: 'Checks'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'release/**'
|
||||
merge_group:
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
CLI_PACKAGE_NAME: '@google/gemini-cli'
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
packages: 'write'
|
||||
pull-requests: 'write'
|
||||
security-events: 'write'
|
||||
checks: 'write'
|
||||
statuses: 'write'
|
||||
actions: 'read'
|
||||
attestations: 'read'
|
||||
deployments: 'read'
|
||||
discussions: 'read'
|
||||
issues: 'read'
|
||||
pages: 'read'
|
||||
repository-projects: 'read'
|
||||
id-token: 'write'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: 'Lint'
|
||||
uses: './.github/workflows/lint.yml'
|
||||
|
||||
get-vars:
|
||||
name: 'Get Environment Variables'
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment: 'dev'
|
||||
outputs:
|
||||
cli-package-name: '${{ steps.get-vars.outputs.cli-package-name }}'
|
||||
npm-registry-scope: '${{ steps.get-vars.outputs.npm-registry-scope }}'
|
||||
npm-registry-url: '${{ steps.get-vars.outputs.npm-registry-url }}'
|
||||
steps:
|
||||
- id: 'get-vars'
|
||||
env:
|
||||
CLI_PACKAGE_NAME: '${{ vars.CLI_PACKAGE_NAME }}'
|
||||
NPM_REGISTRY_SCOPE: '${{ vars.NPM_REGISTRY_SCOPE }}'
|
||||
NPM_REGISTRY_URL: '${{ vars.NPM_REGISTRY_URL }}'
|
||||
run: |
|
||||
echo "cli-package-name=${CLI_PACKAGE_NAME}" >> "$GITHUB_OUTPUT"
|
||||
echo "npm-registry-scope=${NPM_REGISTRY_SCOPE}" >> "$GITHUB_OUTPUT"
|
||||
echo "npm-registry-url=${NPM_REGISTRY_URL}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build-and-publish:
|
||||
name: 'Build and Publish CI Bundle'
|
||||
needs: ['lint', 'get-vars']
|
||||
uses: './.github/workflows/build-and-publish.yml'
|
||||
with:
|
||||
cli-package-name: '${{ needs.get-vars.outputs.cli-package-name }}'
|
||||
npm-registry-scope: '${{ needs.get-vars.outputs.npm-registry-scope }}'
|
||||
npm-registry-url: '${{ needs.get-vars.outputs.npm-registry-url }}'
|
||||
|
||||
ci:
|
||||
name: 'CI Checks'
|
||||
needs: 'lint'
|
||||
uses: './.github/workflows/ci.yml'
|
||||
|
||||
e2e:
|
||||
name: 'E2E Checks'
|
||||
needs: ['build-and-publish', 'get-vars']
|
||||
uses: './.github/workflows/e2e.yml'
|
||||
permissions:
|
||||
contents: 'read'
|
||||
packages: 'read'
|
||||
with:
|
||||
version: '${{ needs.build-and-publish.outputs.version }}'
|
||||
cli-package-name: '${{ needs.get-vars.outputs.cli-package-name }}'
|
||||
image-uri: '${{ needs.build-and-publish.outputs.image-uri }}'
|
||||
secrets:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
|
||||
bundle-size:
|
||||
name: 'Bundle Size Check'
|
||||
needs: 'build-and-publish'
|
||||
uses: './.github/workflows/bundle-size.yml'
|
||||
with:
|
||||
version: '${{ needs.build-and-publish.outputs.version }}'
|
||||
@@ -0,0 +1,144 @@
|
||||
name: 'Release: Manual (Bundled)'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'The version to release (e.g., v0.1.11). Must be a valid semver string with a "v" prefix.'
|
||||
required: true
|
||||
type: 'string'
|
||||
ref:
|
||||
description: 'The branch, tag, or SHA to release from.'
|
||||
required: true
|
||||
type: 'string'
|
||||
npm_channel:
|
||||
description: 'The npm channel to publish to'
|
||||
required: true
|
||||
type: 'choice'
|
||||
options:
|
||||
- 'dev'
|
||||
- 'preview'
|
||||
- 'nightly'
|
||||
- 'latest'
|
||||
default: 'latest'
|
||||
dry_run:
|
||||
description: 'Run a dry-run of the release process; no branches, npm packages or GitHub releases will be created.'
|
||||
required: true
|
||||
type: 'boolean'
|
||||
default: true
|
||||
force_skip_tests:
|
||||
description: 'Select to skip the "Run Tests" step in testing. Prod releases should run tests'
|
||||
required: false
|
||||
type: 'boolean'
|
||||
default: false
|
||||
skip_github_release:
|
||||
description: 'Select to skip creating a GitHub release (only used when environment is PROD)'
|
||||
required: false
|
||||
type: 'boolean'
|
||||
default: false
|
||||
environment:
|
||||
description: 'Environment'
|
||||
required: false
|
||||
type: 'choice'
|
||||
options:
|
||||
- 'prod'
|
||||
- 'dev'
|
||||
default: 'prod'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
permissions:
|
||||
contents: 'write'
|
||||
packages: 'write'
|
||||
issues: 'write'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Checkout Release Code'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8'
|
||||
with:
|
||||
ref: '${{ github.event.inputs.ref }}'
|
||||
path: 'release'
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Debug Inputs'
|
||||
shell: 'bash'
|
||||
env:
|
||||
JSON_INPUTS: '${{ toJSON(inputs) }}'
|
||||
run: 'echo "$JSON_INPUTS"'
|
||||
|
||||
- name: 'Setup Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020'
|
||||
with:
|
||||
node-version-file: './release/.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install Dependencies'
|
||||
working-directory: './release'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Prepare Release Info'
|
||||
id: 'release_info'
|
||||
working-directory: './release'
|
||||
env:
|
||||
INPUT_VERSION: '${{ github.event.inputs.version }}'
|
||||
run: |
|
||||
RELEASE_VERSION="${INPUT_VERSION}"
|
||||
echo "RELEASE_VERSION=${RELEASE_VERSION#v}" >> "${GITHUB_OUTPUT}"
|
||||
echo "PREVIOUS_TAG=$(git describe --tags --abbrev=0)" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: 'Run Tests'
|
||||
if: "${{github.event.inputs.force_skip_tests != 'true'}}"
|
||||
uses: './.github/actions/run-tests'
|
||||
with:
|
||||
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
|
||||
working-directory: './release'
|
||||
|
||||
- name: 'Publish Bundle'
|
||||
uses: './.github/actions/publish-bundle'
|
||||
with:
|
||||
version: '${{ steps.release_info.outputs.RELEASE_VERSION }}'
|
||||
tag: '${{ github.event.inputs.npm_channel }}'
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
package-scope: '${{ vars.NPM_REGISTRY_SCOPE }}'
|
||||
|
||||
- name: '🔬 Verify Bundled NPM release by version'
|
||||
if: '${{ github.event.inputs.dry_run == false && github.event.inputs.force_skip_tests == false }}'
|
||||
working-directory: './release'
|
||||
shell: 'bash'
|
||||
env:
|
||||
CLI_PACKAGE_NAME: '${{ vars.CLI_PACKAGE_NAME }}'
|
||||
RELEASE_VERSION: '${{ steps.release_info.outputs.RELEASE_VERSION }}'
|
||||
run: |
|
||||
npx -y "${CLI_PACKAGE_NAME}"@"${RELEASE_VERSION}" --version
|
||||
|
||||
- name: '🎉 Create GitHub Release'
|
||||
working-directory: './release'
|
||||
if: "${{ github.event.inputs.dry_run == false && github.event.inputs.skip_github_release == false && github.event.inputs.npm_channel != 'dev' && vars.NPM_REGISTRY_URL != 'https://npm.pkg.github.com/' }}"
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
RELEASE_TAG: '${{ github.event.inputs.version }}'
|
||||
PREVIOUS_TAG: '${{ steps.release_info.outputs.PREVIOUS_TAG }}'
|
||||
run: |
|
||||
gh release create "${RELEASE_TAG}" \
|
||||
bundle/gemini.js \
|
||||
--title "Release ${RELEASE_TAG}" \
|
||||
--notes-start-tag "${PREVIOUS_TAG}" \
|
||||
--generate-notes
|
||||
|
||||
- name: 'Create Issue on Failure'
|
||||
if: '${{ failure() && github.event.inputs.dry_run == false }}'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
RELEASE_TAG: '${{ github.event.inputs.version }}'
|
||||
DETAILS_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||
run: |
|
||||
gh issue create \
|
||||
--title 'Manual Release Failed for ${RELEASE_TAG} on $(date +'%Y-%m-%d')' \
|
||||
--body 'The manual release workflow failed. See the full run for details: ${DETAILS_URL}' \
|
||||
--label 'kind/bug,release-failure,priority/p0'
|
||||
@@ -1,4 +1,4 @@
|
||||
name: 'Release: Manual'
|
||||
name: 'Release: Manual (Depreciated)'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
working-directory: './release'
|
||||
|
||||
- name: 'Publish Release'
|
||||
uses: './.github/actions/publish-release'
|
||||
uses: './.github/actions/publish-release-deprecated'
|
||||
with:
|
||||
force-skip-tests: '${{ github.event.inputs.force_skip_tests }}'
|
||||
release-version: '${{ steps.release_info.outputs.RELEASE_VERSION }}'
|
||||
|
||||
@@ -227,7 +227,7 @@ jobs:
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Publish Release'
|
||||
uses: './.github/actions/publish-release'
|
||||
uses: './.github/actions/publish-release-deprecated'
|
||||
with:
|
||||
release-version: '${{ needs.calculate-versions.outputs.PREVIEW_VERSION }}'
|
||||
release-tag: 'v${{ needs.calculate-versions.outputs.PREVIEW_VERSION }}'
|
||||
@@ -293,7 +293,7 @@ jobs:
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Publish Release'
|
||||
uses: './.github/actions/publish-release'
|
||||
uses: './.github/actions/publish-release-deprecated'
|
||||
with:
|
||||
release-version: '${{ needs.calculate-versions.outputs.STABLE_VERSION }}'
|
||||
release-tag: 'v${{ needs.calculate-versions.outputs.STABLE_VERSION }}'
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
name: 'Release Sandbox'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: 'The branch, tag, or SHA to release from.'
|
||||
required: false
|
||||
type: 'string'
|
||||
default: 'main'
|
||||
dry-run:
|
||||
description: 'Whether this is a dry run.'
|
||||
required: false
|
||||
type: 'boolean'
|
||||
default: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
contents: 'read'
|
||||
packages: 'write'
|
||||
issues: 'write'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8'
|
||||
with:
|
||||
ref: '${{ github.event.inputs.ref || github.sha }}'
|
||||
fetch-depth: 0
|
||||
- name: 'Push'
|
||||
uses: './.github/actions/push-sandbox'
|
||||
with:
|
||||
dockerhub-username: '${{ secrets.DOCKER_SERVICE_ACCOUNT_NAME }}'
|
||||
dockerhub-token: '${{ secrets.DOCKER_SERVICE_ACCOUNT_KEY }}'
|
||||
github-actor: '${{ github.actor }}'
|
||||
github-secret: '${{ secrets.GITHUB_TOKEN }}'
|
||||
github-sha: '${{ github.sha }}'
|
||||
github-ref-name: '${{github.event.inputs.ref}}'
|
||||
dry-run: '${{ github.event.inputs.dry-run }}'
|
||||
- name: 'Create Issue on Failure'
|
||||
if: '${{ failure() && github.event.inputs.dry-run == false }}'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
DETAILS_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||
run: |
|
||||
gh issue create \
|
||||
--title 'Sandbox Release Failed on $(date +'%Y-%m-%d')' \
|
||||
--body 'The sandbox-release workflow failed. See the full run for details: ${DETAILS_URL}' \
|
||||
--label 'kind/bug,release-failure,priority/p0'
|
||||
@@ -55,4 +55,6 @@ gha-creds-*.json
|
||||
# Log files
|
||||
patch_output.log
|
||||
|
||||
# Local npm configuration
|
||||
.npmrc
|
||||
.genkit
|
||||
|
||||
+39
-1
@@ -304,7 +304,45 @@ npm run lint
|
||||
- **Imports:** Pay special attention to import paths. The project uses ESLint to
|
||||
enforce restrictions on relative imports between packages.
|
||||
|
||||
### Project structure
|
||||
### Setting Up Your NPM Environment
|
||||
|
||||
**Note:** The following instructions are intended for contributors who need to
|
||||
work with pre-release versions hosted on the private GitHub Packages registry.
|
||||
General contributors who only use the public `npmjs.org` registry may not need
|
||||
to perform this setup.
|
||||
|
||||
This project uses a hybrid registry model:
|
||||
|
||||
- Production packages (e.g., `@google/gemini-cli`) are published to `npmjs.org`.
|
||||
- Pre-release and development packages (e.g., `@google-gemini/gemini-cli`) are
|
||||
published to **GitHub Packages**.
|
||||
|
||||
To work with both registries, you need to configure your user-level `~/.npmrc`
|
||||
file to authenticate with GitHub Packages. We have a script to automate this.
|
||||
|
||||
#### Configure Your `~/.npmrc` File
|
||||
|
||||
Run the following command to automatically configure your `~/.npmrc` file:
|
||||
|
||||
```bash
|
||||
npm run setup-npmrc
|
||||
```
|
||||
|
||||
This command will:
|
||||
|
||||
1. Check that you have the [GitHub CLI (`gh`)](https://cli.github.com/)
|
||||
installed and that you are logged in.
|
||||
2. **Back up** your existing `~/.npmrc` to `~/.npmrc.bak` if a backup doesn't
|
||||
already exist.
|
||||
3. **Overwrite** your `~/.npmrc` with the correct configuration to pull
|
||||
packages from both `npmjs.org` and `npm.pkg.github.com` based on their
|
||||
scope.
|
||||
|
||||
After running this, you can install packages from both registries without any
|
||||
further configuration. If your GitHub token expires, you can simply run the
|
||||
command again to update it.
|
||||
|
||||
### Project Structure
|
||||
|
||||
- `packages/`: Contains the individual sub-packages of the project.
|
||||
- `a2a-server`: A2A server implementation for the Gemini CLI. (Experimental)
|
||||
|
||||
+34
-14
@@ -1,11 +1,38 @@
|
||||
# --- Builder Stage ---
|
||||
FROM docker.io/library/node:20-slim AS builder
|
||||
|
||||
ARG CLI_VERSION
|
||||
ARG NPM_REGISTRY_SCOPE
|
||||
ARG NPM_REGISTRY_URL
|
||||
ARG CLI_PACKAGE_NAME
|
||||
|
||||
# Set up npm global package folder
|
||||
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
|
||||
ENV PATH=$PATH:/usr/local/share/npm-global/bin
|
||||
|
||||
# Ensure the node user has permissions to write to the global npm directory
|
||||
RUN mkdir -p /usr/local/share/npm-global && chown -R node:node /usr/local/share/npm-global
|
||||
|
||||
# Configure npm to use GitHub Packages
|
||||
RUN --mount=type=secret,id=GITHUB_TOKEN \
|
||||
echo "${NPM_REGISTRY_SCOPE}:registry=${NPM_REGISTRY_URL}" > /home/node/.npmrc && \
|
||||
echo "//npm.pkg.github.com/:_authToken=$(cat /run/secrets/GITHUB_TOKEN)" >> /home/node/.npmrc && \
|
||||
chown -R node:node /home/node/.npmrc
|
||||
|
||||
# Switch to non-root user
|
||||
USER node
|
||||
|
||||
# Install the Gemini CLI package
|
||||
RUN npm install -g ${CLI_PACKAGE_NAME}@${CLI_VERSION} && \
|
||||
npm cache clean --force
|
||||
|
||||
# --- Final Stage ---
|
||||
FROM docker.io/library/node:20-slim
|
||||
|
||||
ARG SANDBOX_NAME="gemini-cli-sandbox"
|
||||
ARG CLI_VERSION_ARG
|
||||
ENV SANDBOX="$SANDBOX_NAME"
|
||||
ENV CLI_VERSION=$CLI_VERSION_ARG
|
||||
|
||||
# install minimal set of packages, then clean up
|
||||
# Install runtime dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python3 \
|
||||
make \
|
||||
@@ -29,22 +56,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# set up npm global package folder under /usr/local/share
|
||||
# give it to non-root user node, already set up in base image
|
||||
# Set up npm global package folder and user
|
||||
RUN mkdir -p /usr/local/share/npm-global \
|
||||
&& chown -R node:node /usr/local/share/npm-global
|
||||
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
|
||||
ENV PATH=$PATH:/usr/local/share/npm-global/bin
|
||||
|
||||
# switch to non-root user node
|
||||
USER node
|
||||
|
||||
# install gemini-cli and clean up
|
||||
COPY packages/cli/dist/google-gemini-cli-*.tgz /tmp/gemini-cli.tgz
|
||||
COPY packages/core/dist/google-gemini-cli-core-*.tgz /tmp/gemini-core.tgz
|
||||
RUN npm install -g /tmp/gemini-cli.tgz /tmp/gemini-core.tgz \
|
||||
&& npm cache clean --force \
|
||||
&& rm -f /tmp/gemini-{cli,core}.tgz
|
||||
# Copy installed package from the builder stage
|
||||
COPY --from=builder /usr/local/share/npm-global /usr/local/share/npm-global
|
||||
|
||||
# default entrypoint when none specified
|
||||
# Default entrypoint
|
||||
CMD ["gemini"]
|
||||
|
||||
@@ -8,6 +8,7 @@ import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
setupFiles: ['./vitest.setup.ts'],
|
||||
testTimeout: 300000, // 5 minutes
|
||||
globalSetup: './globalSetup.ts',
|
||||
reporters: ['default'],
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
// Mock the ClearcutLogger module to prevent E2E tests from failing due to a missing generated file.
|
||||
// The ClearcutLogger (which imports git-commit.js) is not needed for E2E test validation,
|
||||
// as tests rely on the OpenTelemetry logger which writes to telemetry.log.
|
||||
vi.mock(
|
||||
(await import('node:path')).resolve(
|
||||
process.cwd(),
|
||||
'packages/core/src/telemetry/clearcut-logger/clearcut-logger.js',
|
||||
),
|
||||
() => ({
|
||||
ClearcutLogger: {
|
||||
getInstance: vi.fn(() => ({
|
||||
logStartSessionEvent: vi.fn(),
|
||||
logNewPromptEvent: vi.fn(),
|
||||
logToolCallEvent: vi.fn(),
|
||||
logToolOutputTruncatedEvent: vi.fn(),
|
||||
logFileOperationEvent: vi.fn(),
|
||||
logApiRequestEvent: vi.fn(),
|
||||
logApiResponseEvent: vi.fn(),
|
||||
logApiErrorEvent: vi.fn(),
|
||||
logChatCompressionEvent: vi.fn(),
|
||||
logFlashFallbackEvent: vi.fn(),
|
||||
logRipgrepFallbackEvent: vi.fn(),
|
||||
logLoopDetectedEvent: vi.fn(),
|
||||
logLoopDetectionDisabledEvent: vi.fn(),
|
||||
logNextSpeakerCheck: vi.fn(),
|
||||
logSlashCommandEvent: vi.fn(),
|
||||
logMalformedJsonResponseEvent: vi.fn(),
|
||||
logIdeConnectionEvent: vi.fn(),
|
||||
logConversationFinishedEvent: vi.fn(),
|
||||
logKittySequenceOverflowEvent: vi.fn(),
|
||||
logInvalidChunkEvent: vi.fn(),
|
||||
logContentRetryEvent: vi.fn(),
|
||||
logContentRetryFailureEvent: vi.fn(),
|
||||
logModelRoutingEvent: vi.fn(),
|
||||
logExtensionInstallEvent: vi.fn(),
|
||||
logExtensionUninstallEvent: vi.fn(),
|
||||
logExtensionUpdateEvent: vi.fn(),
|
||||
logExtensionEnableEvent: vi.fn(),
|
||||
logExtensionDisableEvent: vi.fn(),
|
||||
logSmartEditStrategyEvent: vi.fn(),
|
||||
logSmartEditCorrectionEvent: vi.fn(),
|
||||
logAgentStartEvent: vi.fn(),
|
||||
logAgentFinishEvent: vi.fn(),
|
||||
logWebFetchFallbackAttemptEvent: vi.fn(),
|
||||
logEndSessionEvent: vi.fn(),
|
||||
})),
|
||||
clearInstance: vi.fn(),
|
||||
},
|
||||
}),
|
||||
);
|
||||
Generated
+25
@@ -5376,6 +5376,15 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
@@ -8655,6 +8664,13 @@
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/express/node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
@@ -16214,6 +16230,15 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
|
||||
+15
-7
@@ -8,7 +8,6 @@
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"private": "true",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/google-gemini/gemini-cli.git"
|
||||
@@ -34,18 +33,26 @@
|
||||
"build:packages": "npm run build --workspaces",
|
||||
"build:sandbox": "node scripts/build_sandbox.js",
|
||||
"bundle": "npm run generate && node esbuild.config.js && node scripts/copy_bundle_assets.js",
|
||||
"test": "npm run test --workspaces --if-present",
|
||||
"test:ci": "npm run test:ci --workspaces --if-present && npm run test:scripts",
|
||||
"test": "npm run test --workspaces --if-present --parallel",
|
||||
"test:ci": "npm run build && npm run test:ci --workspaces --if-present --parallel && npm run test:scripts",
|
||||
"test:scripts": "vitest run --config ./scripts/tests/vitest.config.ts",
|
||||
"test:e2e": "cross-env VERBOSE=true KEEP_OUTPUT=true npm run test:integration:sandbox:none",
|
||||
"test:integration:all": "npm run test:integration:sandbox:none && npm run test:integration:sandbox:docker && npm run test:integration:sandbox:podman",
|
||||
"test:integration:sandbox:none": "cross-env GEMINI_SANDBOX=false vitest run --root ./integration-tests",
|
||||
"test:integration:sandbox:docker": "cross-env GEMINI_SANDBOX=docker npm run build:sandbox && cross-env GEMINI_SANDBOX=docker vitest run --root ./integration-tests",
|
||||
"test:integration:sandbox:docker": "cross-env GEMINI_SANDBOX=docker vitest run --root ./integration-tests",
|
||||
"test:integration:sandbox:podman": "cross-env GEMINI_SANDBOX=podman vitest run --root ./integration-tests",
|
||||
"lint": "eslint . --ext .ts,.tsx && eslint integration-tests && eslint scripts",
|
||||
"lint": "node scripts/lint.js --eslint",
|
||||
"lint:eslint": "node scripts/lint.js --eslint",
|
||||
"lint:actionlint": "node scripts/lint.js --actionlint",
|
||||
"lint:shellcheck": "node scripts/lint.js --shellcheck",
|
||||
"lint:yamllint": "node scripts/lint.js --yamllint",
|
||||
"lint:prettier": "node scripts/lint.js --prettier",
|
||||
"lint:sensitive-keywords": "node scripts/lint.js --sensitive-keywords",
|
||||
"lint:tsconfig": "node scripts/lint.js --tsconfig",
|
||||
"lint:setup": "node scripts/lint.js --setup",
|
||||
"lint:fix": "eslint . --fix --ext .ts,.tsx && eslint integration-tests --fix && eslint scripts --fix && npm run format",
|
||||
"lint:ci": "npm run lint:all",
|
||||
"lint:all": "node scripts/lint.js",
|
||||
"lint:all": "npm run lint:setup && npm-run-all --parallel lint:eslint lint:actionlint lint:shellcheck lint:yamllint lint:prettier lint:sensitive-keywords lint:tsconfig",
|
||||
"format": "prettier --experimental-cli --write .",
|
||||
"typecheck": "npm run typecheck --workspaces --if-present",
|
||||
"preflight": "npm run clean && npm ci && npm run format && npm run lint:ci && npm run build && npm run typecheck && npm run test:ci",
|
||||
@@ -55,7 +62,8 @@
|
||||
"telemetry": "node scripts/telemetry.js",
|
||||
"check:lockfile": "node scripts/check-lockfile.js",
|
||||
"clean": "node scripts/clean.js",
|
||||
"pre-commit": "node scripts/pre-commit.js"
|
||||
"pre-commit": "node scripts/pre-commit.js",
|
||||
"setup-npmrc": "node scripts/configure-registry.js"
|
||||
},
|
||||
"overrides": {
|
||||
"wrap-ansi": "9.0.2",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"debug": "node --inspect-brk dist/index.js",
|
||||
"lint": "eslint . --ext .ts,.tsx",
|
||||
"format": "prettier --write .",
|
||||
"test": "vitest run",
|
||||
"test": "vitest run -- ",
|
||||
"test:ci": "vitest run",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview This script automates the configuration of the user's
|
||||
* global .npmrc file to work with this repository's development workflow.
|
||||
*
|
||||
* Rationale:
|
||||
* This project uses a hybrid registry setup:
|
||||
* - Production packages (`@google/gemini-cli`) are on the public npmjs.org registry.
|
||||
* - Pre-release packages (`@google-gemini/gemini-cli`) are on the GitHub Packages registry.
|
||||
*
|
||||
* This script provides a consistent, automated, and less error-prone way to
|
||||
* configure the necessary scopes and authentication for both registries. It
|
||||
* backs up the user's existing .npmrc, making it a safe, one-time setup.
|
||||
*/
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import os from 'node:os';
|
||||
import { execSync } from 'node:child_process';
|
||||
|
||||
const homedir = os.homedir();
|
||||
const npmrcPath = path.join(homedir, '.npmrc');
|
||||
const backupPath = path.join(homedir, '.npmrc.bak');
|
||||
|
||||
const GITHUB_REGISTRY_URL = 'https://npm.pkg.github.com/';
|
||||
const GITHUB_SCOPE = '@google-gemini';
|
||||
const PROD_SCOPE = '@google';
|
||||
const PROD_REGISTRY_URL = 'https://registry.npmjs.org/';
|
||||
|
||||
function checkGhCli() {
|
||||
try {
|
||||
execSync('gh --version', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (_e) {
|
||||
console.error(
|
||||
'Error: The GitHub CLI (`gh`) is not installed or not in your PATH.',
|
||||
);
|
||||
console.error('Please install it to continue: https://cli.github.com/');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getGhAuthStatus() {
|
||||
try {
|
||||
execSync('gh auth status', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (_e) {
|
||||
console.error('Error: You are not logged in to the GitHub CLI (`gh`).');
|
||||
console.error(
|
||||
"Please run `gh auth login` and ensure you grant the 'read:packages' and 'write:packages' scopes.",
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getGhAuthToken() {
|
||||
try {
|
||||
const token = execSync('gh auth token', {
|
||||
encoding: 'utf8',
|
||||
}).trim();
|
||||
if (!token) {
|
||||
throw new Error('No token returned from `gh auth token`');
|
||||
}
|
||||
return token;
|
||||
} catch (_e) {
|
||||
console.error('Error: Failed to retrieve GitHub auth token.');
|
||||
console.error(
|
||||
'Please ensure you are logged in (`gh auth status`) and have the correct permissions.',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function setupNpmrc() {
|
||||
console.log('Configuring your global ~/.npmrc for development...');
|
||||
|
||||
if (!checkGhCli() || !getGhAuthStatus()) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const token = getGhAuthToken();
|
||||
if (!token) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Back up the original .npmrc if it exists and a backup doesn't already.
|
||||
if (fs.existsSync(npmrcPath) && !fs.existsSync(backupPath)) {
|
||||
fs.copyFileSync(npmrcPath, backupPath);
|
||||
console.log(`Backed up your existing configuration to ${backupPath}`);
|
||||
}
|
||||
|
||||
const newContent = [
|
||||
`# Added by gemini-cli setup`,
|
||||
`# Configures scopes for both production and development registries`,
|
||||
``,
|
||||
`# Production packages from npmjs.org`,
|
||||
`${PROD_SCOPE}:registry=${PROD_REGISTRY_URL}`,
|
||||
``,
|
||||
`# Pre-release packages from GitHub Packages`,
|
||||
`${GITHUB_SCOPE}:registry=${GITHUB_REGISTRY_URL}`,
|
||||
`//${new URL(GITHUB_REGISTRY_URL).hostname}/:_authToken=${token}`,
|
||||
``,
|
||||
].join('\n');
|
||||
|
||||
fs.writeFileSync(npmrcPath, newContent);
|
||||
console.log(`✅ Successfully configured your ~/.npmrc file.`);
|
||||
console.log('You can now install both production and pre-release packages.');
|
||||
}
|
||||
|
||||
setupNpmrc();
|
||||
+5
-1
@@ -147,7 +147,11 @@ export function setupLinters() {
|
||||
|
||||
export function runESLint() {
|
||||
console.log('\nRunning ESLint...');
|
||||
if (!runCommand('npm run lint')) {
|
||||
if (
|
||||
!runCommand(
|
||||
'eslint . --ext .ts,.tsx && eslint integration-tests && eslint scripts',
|
||||
)
|
||||
) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/**
|
||||
* @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-a2a-server
|
||||
updatePackageJson('packages/a2a-server/package.json', (pkg) => {
|
||||
pkg.name = '@google-gemini/gemini-cli-a2a-server';
|
||||
});
|
||||
|
||||
// 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.');
|
||||
+45
-34
@@ -6,46 +6,57 @@
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
// ES module equivalent of __dirname
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const rootDir = process.cwd();
|
||||
|
||||
const rootDir = path.resolve(__dirname, '..');
|
||||
|
||||
function copyFiles(packageName, filesToCopy) {
|
||||
const packageDir = path.resolve(rootDir, 'packages', packageName);
|
||||
if (!fs.existsSync(packageDir)) {
|
||||
console.error(`Error: Package directory not found at ${packageDir}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Preparing package: ${packageName}`);
|
||||
for (const [source, dest] of Object.entries(filesToCopy)) {
|
||||
const sourcePath = path.resolve(rootDir, source);
|
||||
const destPath = path.resolve(packageDir, dest);
|
||||
try {
|
||||
fs.copyFileSync(sourcePath, destPath);
|
||||
console.log(`Copied ${source} to packages/${packageName}/`);
|
||||
} catch (err) {
|
||||
console.error(`Error copying ${source}:`, err);
|
||||
process.exit(1);
|
||||
}
|
||||
function getArg(name) {
|
||||
const arg = process.argv.find((arg) => arg.startsWith(name));
|
||||
if (!arg) {
|
||||
return null;
|
||||
}
|
||||
return arg.split('=')[1];
|
||||
}
|
||||
|
||||
// Prepare 'core' package
|
||||
copyFiles('core', {
|
||||
'README.md': 'README.md',
|
||||
LICENSE: 'LICENSE',
|
||||
'.npmrc': '.npmrc',
|
||||
function updatePackageJson(packagePath, updateFn) {
|
||||
const packageJsonPath = path.resolve(rootDir, packagePath);
|
||||
if (!fs.existsSync(packageJsonPath)) {
|
||||
console.error(`Error: package.json not found at ${packageJsonPath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
||||
updateFn(packageJson);
|
||||
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
||||
console.log(`Updated ${packagePath}`);
|
||||
}
|
||||
|
||||
const scope = getArg('--scope');
|
||||
if (!scope) {
|
||||
console.error('Error: --scope argument is required.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Preparing packages with scope: ${scope}...`);
|
||||
|
||||
// Update root package.json
|
||||
updatePackageJson('package.json', (pkg) => {
|
||||
pkg.name = `${scope}/gemini-cli`;
|
||||
});
|
||||
|
||||
// Prepare 'cli' package
|
||||
copyFiles('cli', {
|
||||
'README.md': 'README.md',
|
||||
LICENSE: 'LICENSE',
|
||||
// Update @google/gemini-cli-a2a-server
|
||||
updatePackageJson('packages/a2a-server/package.json', (pkg) => {
|
||||
pkg.name = `${scope}/gemini-cli-a2a-server`;
|
||||
});
|
||||
|
||||
console.log('Successfully prepared all packages.');
|
||||
// Update @google/gemini-cli-core
|
||||
updatePackageJson('packages/core/package.json', (pkg) => {
|
||||
pkg.name = `${scope}/gemini-cli-core`;
|
||||
});
|
||||
|
||||
// Update @google/gemini-cli
|
||||
updatePackageJson('packages/cli/package.json', (pkg) => {
|
||||
pkg.name = `${scope}/gemini-cli`;
|
||||
pkg.dependencies['@google/gemini-cli-core'] =
|
||||
`npm:${scope}/gemini-cli-core@^0.0.0`;
|
||||
});
|
||||
|
||||
console.log('Successfully prepared packages.');
|
||||
|
||||
Reference in New Issue
Block a user