From 4d4cf0f2f95a002e0b5bf23b2e4f5a446a0612ac Mon Sep 17 00:00:00 2001 From: Tolik Malibroda <54813212+tolikmalibroda@users.noreply.github.com> Date: Thu, 5 Jun 2025 17:46:54 +0200 Subject: feat: Add multi-stage docker build support for custom sandbox.Dockerfile (#746) --- packages/cli/src/utils/sandbox.ts | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'packages') diff --git a/packages/cli/src/utils/sandbox.ts b/packages/cli/src/utils/sandbox.ts index e583f0ff..9fb3da69 100644 --- a/packages/cli/src/utils/sandbox.ts +++ b/packages/cli/src/utils/sandbox.ts @@ -73,7 +73,9 @@ async function shouldUseCurrentUserInSandbox(): Promise { return false; // Default to false if no other condition is met } -async function getSandboxImageName(): Promise { +async function getSandboxImageName( + isCustomProjectSandbox: boolean, +): Promise { const packageJsonResult = await readPackageUp(); const packageJsonConfig = packageJsonResult?.packageJson.config as | { sandboxImageUri?: string } @@ -81,7 +83,9 @@ async function getSandboxImageName(): Promise { return ( process.env.GEMINI_SANDBOX_IMAGE ?? packageJsonConfig?.sandboxImageUri ?? - LOCAL_DEV_SANDBOX_IMAGE_NAME + (isCustomProjectSandbox + ? LOCAL_DEV_SANDBOX_IMAGE_NAME + '-' + path.basename(path.resolve()) + : LOCAL_DEV_SANDBOX_IMAGE_NAME) ); } @@ -272,15 +276,23 @@ export async function start_sandbox(sandbox: string) { // determine full path for gemini-cli to distinguish linked vs installed setting const gcPath = execSync(`realpath $(which gemini)`).toString().trim(); - const image = await getSandboxImageName(); + const projectSandboxDockerfile = path.join( + SETTINGS_DIRECTORY_NAME, + 'sandbox.Dockerfile', + ); + const isCustomProjectSandbox = fs.existsSync(projectSandboxDockerfile); + + const image = await getSandboxImageName(isCustomProjectSandbox); const workdir = process.cwd(); - // if BUILD_SANDBOX is set, then call scripts/build_sandbox.sh under gemini-cli repo + // if BUILD_SANDBOX is set or project-specific sandbox.Dockerfile provided, + // then call scripts/build_sandbox.sh under gemini-cli repo + // // note this can only be done with binary linked from gemini-cli repo - if (process.env.BUILD_SANDBOX) { + if (process.env.BUILD_SANDBOX || isCustomProjectSandbox) { if (!gcPath.includes('gemini-cli/packages/')) { console.error( - 'ERROR: cannot BUILD_SANDBOX using installed gemini binary; ' + + 'ERROR: cannot build sandbox using installed gemini binary; ' + 'run `npm link ./packages/cli` under gemini-cli repo to switch to linked binary.', ); process.exit(1); @@ -293,9 +305,9 @@ export async function start_sandbox(sandbox: string) { SETTINGS_DIRECTORY_NAME, 'sandbox.Dockerfile', ); - if (fs.existsSync(projectSandboxDockerfile)) { + if (isCustomProjectSandbox) { console.error(`using ${projectSandboxDockerfile} for sandbox`); - buildArgs += `-f ${path.resolve(projectSandboxDockerfile)}`; + buildArgs += `-s -f ${path.resolve(projectSandboxDockerfile)} -i ${image}`; } spawnSync(`cd ${gcRoot} && scripts/build_sandbox.sh ${buildArgs}`, { stdio: 'inherit', -- cgit v1.2.3