diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000..e79a88e890e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,17 @@ +# Git history - not needed in build context +.git + +# Root node_modules - reinstalled inside container via npm ci +node_modules + +# Package-level node_modules - reinstalled inside container +packages/*/node_modules + +# Development and IDE files +.github +.vscode +npm-debug.log* + +# Misc +.DS_Store +*.tmp diff --git a/Dockerfile b/Dockerfile index 44ba3439023..31d9c6d4460 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,44 @@ +# ---- Stage 1: Builder ---- +FROM docker.io/library/node:20-slim AS builder + +# Install git (needed by generate-git-commit-info.js script) +RUN apt-get update && apt-get install -y --no-install-recommends git \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +WORKDIR /build + +# Copy only package.json files first for better layer caching +# Dependencies only re-install when package files change, not source files +COPY package*.json ./ +COPY packages/cli/package*.json ./packages/cli/ +COPY packages/core/package*.json ./packages/core/ +COPY packages/vscode-ide-companion/package*.json ./packages/vscode-ide-companion/ +COPY packages/vscode-ide-companion/scripts/ ./packages/vscode-ide-companion/scripts/ +COPY packages/devtools/package*.json ./packages/devtools/ +COPY packages/sdk/package*.json ./packages/sdk/ +COPY packages/test-utils/package*.json ./packages/test-utils/ +COPY packages/a2a-server/package*.json ./packages/a2a-server/ + +# Use npm ci for consistent, reliable builds (respects package-lock.json) +RUN HUSKY=0 npm ci --ignore-scripts + +# Now copy the rest of the source (after install for better caching) +COPY packages/ ./packages/ +COPY tsconfig*.json ./ +COPY eslint.config.js ./ +COPY scripts/ ./scripts/ +COPY esbuild.config.js ./ + +# Pass git commit hash as build arg instead of copying entire .git directory +ARG GIT_COMMIT=unknown +ENV GIT_COMMIT=$GIT_COMMIT + +# Build and pack artifacts +RUN HUSKY=0 npm run build && \ + npm pack -w packages/core --pack-destination packages/core/dist/ && \ + npm pack -w packages/cli --pack-destination packages/cli/dist/ + +# ---- Stage 2: Runtime ---- FROM docker.io/library/node:20-slim ARG SANDBOX_NAME="gemini-cli-sandbox" @@ -50,4 +91,4 @@ RUN npm install -g /tmp/gemini-core.tgz \ && rm -f /tmp/gemini-{cli,core}.tgz # default entrypoint when none specified -CMD ["gemini"] +ENTRYPOINT ["/usr/local/share/npm-global/bin/gemini"] \ No newline at end of file diff --git a/scripts/generate-git-commit-info.js b/scripts/generate-git-commit-info.js index 049c39c249b..8aafbf54112 100644 --- a/scripts/generate-git-commit-info.js +++ b/scripts/generate-git-commit-info.js @@ -42,13 +42,19 @@ if (!existsSync(generatedCoreDir)) { } try { - const gitHash = execSync('git rev-parse --short HEAD', { - encoding: 'utf-8', - }).trim(); - if (gitHash) { - gitCommitInfo = gitHash; + // Check for GIT_COMMIT env var first (e.g. when building inside Docker + // without a .git directory available) + const envCommit = process.env.GIT_COMMIT; + if (envCommit && /^[0-9a-f]+$/i.test(envCommit)) { + gitCommitInfo = envCommit; + } else { + const gitHash = execSync('git rev-parse --short HEAD', { + encoding: 'utf-8', + }).trim(); + if (gitHash) { + gitCommitInfo = gitHash; + } } - const result = await readPackageUp(); cliVersion = result?.packageJson?.version ?? 'UNKNOWN'; } catch {