From d051c0fd0fdac2078e35144f27bfcea415bd503e Mon Sep 17 00:00:00 2001 From: Brandon Keiji Date: Sat, 26 Apr 2025 00:30:50 +0000 Subject: [PATCH] feat: prototype publish sandbox script with npm package (#182) --- .gcp/dogfood.yaml | 2 +- .gcp/publish-dry-run.yaml | 2 +- package-lock.json | 3 +- package.json | 4 ++- packages/cli/Dockerfile | 27 ++++++++++++++++++ packages/cli/bin/sandbox.sh | 54 ++++++++++++++++++++++++++++++++++++ packages/cli/package.json | 11 +++++--- packages/server/package.json | 2 +- 8 files changed, 96 insertions(+), 9 deletions(-) create mode 100644 packages/cli/Dockerfile create mode 100755 packages/cli/bin/sandbox.sh diff --git a/.gcp/dogfood.yaml b/.gcp/dogfood.yaml index 8e74a581..5fd3fbdd 100644 --- a/.gcp/dogfood.yaml +++ b/.gcp/dogfood.yaml @@ -24,7 +24,7 @@ steps: # Authenticate with our registry - name: 'node:bookworm' entrypoint: 'npm' - args: ['run', 'auth'] + args: ['run', 'auth:npm'] # Publish packages from workspaces with 'dogfood' tag # we awkwardly need to install rsync beforehand. TODO: use a dedicated dev container diff --git a/.gcp/publish-dry-run.yaml b/.gcp/publish-dry-run.yaml index 75e6b603..7149c4de 100644 --- a/.gcp/publish-dry-run.yaml +++ b/.gcp/publish-dry-run.yaml @@ -24,7 +24,7 @@ steps: # Authenticate with our registry - name: 'node:bookworm' entrypoint: 'npm' - args: ['run', 'auth'] + args: ['run', 'auth:npm'] # Dry run publish to make sure that's not broken # we awkwardly need to install rsync beforehand. TODO: use a dedicated dev container diff --git a/package-lock.json b/package-lock.json index 89067c30..6d4500db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6835,7 +6835,8 @@ "yargs": "^17.7.2" }, "bin": { - "gemini-code": "dist/index.js" + "gemini-code": "dist/index.js", + "gemini-code-sandbox": "bin/sandbox.sh" }, "devDependencies": { "@types/diff": "^7.0.2", diff --git a/package.json b/package.json index 99379921..10ba1cca 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,9 @@ "typecheck": "tsc --noEmit --jsx react", "format": "prettier --write .", "preflight": "npm run format --workspaces --if-present && npm run lint --workspaces --if-present && npm run test --workspaces --if-present", - "auth": "npx google-artifactregistry-auth", + "auth:npm": "npx google-artifactregistry-auth", + "auth:docker": "gcloud auth configure-docker us-west1-docker.pkg.dev", + "auth": "npm run auth:npm && npm run auth:docker", "prerelease:dev": "npm run prerelease:version --workspaces && npm run prerelease:deps --workspaces" }, "devDependencies": { diff --git a/packages/cli/Dockerfile b/packages/cli/Dockerfile new file mode 100644 index 00000000..9cf4b1b9 --- /dev/null +++ b/packages/cli/Dockerfile @@ -0,0 +1,27 @@ +FROM docker.io/library/node:20-slim + +ENV GEMINI_CODE_SANDBOX=docker +ENV SANDBOX=sandbox + +# install minimal set of packages, then clean up +RUN apt-get update && apt-get install -y --no-install-recommends \ + man-db \ + curl \ + dnsutils \ + less \ + jq \ + bc \ + gh \ + git \ + unzip \ + rsync \ + ripgrep \ + procps \ + psmisc \ + lsof \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN --mount=type=secret,id=npmrc,dst=/root/.npmrc npm install -g @gemini-code/cli@head --verbose + +ENTRYPOINT 'gemini-code' \ No newline at end of file diff --git a/packages/cli/bin/sandbox.sh b/packages/cli/bin/sandbox.sh new file mode 100755 index 00000000..20dc608c --- /dev/null +++ b/packages/cli/bin/sandbox.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +REGISTRY="us-west1-docker.pkg.dev/gemini-code-dev/gemini-code-containers" # TODO: swap this to public registry before launch +IMAGE="gemini-code" +TAG="0.1.0-fakeversion" # TODO: make this more configurable +PROJECT=$(basename "$PWD") +WORKDIR=/sandbox/$PROJECT + +# use interactive tty mode and auto-remove container on exit +run_args=(-it --rm) + +# mount current directory as $WORKDIR inside container +run_args+=(-v "$PWD:$WORKDIR") + +# name container after image, plus numeric suffix to avoid conflicts +INDEX=0 +while docker ps -a --format "{{.Names}}" | grep -q "$IMAGE-$INDEX"; do + INDEX=$((INDEX + 1)) +done +run_args+=(--name "$IMAGE-$INDEX" --hostname "$IMAGE-$INDEX") + +# copy GEMINI_API_KEY +if [ -n "${GEMINI_API_KEY:-}" ]; then run_args+=(--env GEMINI_API_KEY="$GEMINI_API_KEY"); fi + +# copy GEMINI_CODE_MODEL +if [ -n "${GEMINI_CODE_MODEL:-}" ]; then run_args+=(--env GEMINI_CODE_MODEL="$GEMINI_CODE_MODEL"); fi + +# copy SHELL_TOOL to optionally enable shell tool +if [ -n "${SHELL_TOOL:-}" ]; then run_args+=(--env SHELL_TOOL="$SHELL_TOOL"); fi + +# copy TERM and COLORTERM to try to maintain terminal setup +if [ -n "${TERM:-}" ]; then run_args+=(--env TERM="$TERM"); fi +if [ -n "${COLORTERM:-}" ]; then run_args+=(--env COLORTERM="$COLORTERM"); fi + +# set SANDBOX environment variable as container name +# this is the preferred mechanism to detect if inside container/sandbox +run_args+=(--env "SANDBOX=$IMAGE:$TAG-$INDEX") + +node_args=("$CLI_PATH" "$@") + +docker run "${run_args[@]}" --init --workdir "$WORKDIR" "$REGISTRY/$IMAGE:$TAG" node "${node_args[@]}" \ No newline at end of file diff --git a/packages/cli/package.json b/packages/cli/package.json index c506bb65..ae534ebf 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,11 +1,12 @@ { "name": "@gemini-code/cli", - "version": "0.1.0", + "version": "0.1.0-dev-62cc889.0", "description": "Gemini Code CLI", "type": "module", "main": "dist/index.js", "bin": { - "gemini-code": "dist/index.js" + "gemini-code": "dist/index.js", + "gemini-code-sandbox": "bin/sandbox.sh" }, "scripts": { "build": "../../scripts/build_package.sh", @@ -17,13 +18,15 @@ "test": "vitest run", "prerelease:version": "node ../../scripts/bind_package_version.js", "prerelease:deps": "node ../../scripts/bind_package_dependencies.js", - "prepack": "npm run build" + "prerelease:sandbox": "DOCKER_BUILDKIT=1 docker build --no-cache --secret id=npmrc,src=$HOME/.npmrc -t 'us-west1-docker.pkg.dev/gemini-code-dev/gemini-code-containers/gemini-code:0.1.0-fakeversion' .", + "prepack": "npm run build", + "xpostpublish": "docker push 'us-west1-docker.pkg.dev/gemini-code-dev/gemini-code-containers/gemini-code:0.1.0-fakeversion'" }, "files": [ "dist" ], "dependencies": { - "@gemini-code/server": "*", + "@gemini-code/server": "0.1.0-dev-62cc889.0", "@google/genai": "^0.8.0", "diff": "^7.0.0", "dotenv": "^16.4.7", diff --git a/packages/server/package.json b/packages/server/package.json index 1b0e31c8..2bbc90ee 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@gemini-code/server", - "version": "0.1.0", + "version": "0.1.0-dev-62cc889.0", "description": "Gemini Code Server", "type": "module", "main": "dist/index.js",