feat(offload): address provisioning warnings and implement high-performance startup-script container

This commit is contained in:
mkorwel
2026-03-15 12:32:22 -07:00
parent b5c1b9f77b
commit edc8bfdfe4
4 changed files with 65 additions and 25 deletions

View File

@@ -1,7 +1,7 @@
/**
* Universal Offload Cleanup (Local)
*
* Cleans up tmux sessions and workspace on the GCE worker.
* Surgical or full cleanup of sessions and worktrees on the GCE worker.
*/
import { spawnSync } from 'child_process';
import path from 'path';
@@ -22,7 +22,10 @@ async function confirm(question: string): Promise<boolean> {
});
}
export async function runCleanup() {
export async function runCleanup(args: string[]) {
const prNumber = args[0];
const action = args[1];
const settingsPath = path.join(REPO_ROOT, '.gemini/settings.json');
if (!fs.existsSync(settingsPath)) {
console.error('❌ Settings not found. Run "npm run offload:setup" first.');
@@ -37,32 +40,49 @@ export async function runCleanup() {
return 1;
}
const { projectId, zone } = config;
const targetVM = `gcli-offload-${process.env.USER || 'mattkorwel'}`;
const { remoteHost } = config;
console.log(`🧹 Starting cleanup for ${targetVM}...`);
if (prNumber && action) {
const sessionName = `offload-${prNumber}-${action}`;
const worktreePath = `~/dev/worktrees/${sessionName}`;
console.log(`🧹 Surgically removing session and worktree for ${prNumber}-${action}...`);
// Kill specific tmux session
spawnSync(`ssh ${remoteHost} "tmux kill-session -t ${sessionName} 2>/dev/null"`, { shell: true });
// Remove specific worktree
spawnSync(`ssh ${remoteHost} "cd ~/dev/main && git worktree remove -f ${worktreePath} 2>/dev/null"`, { shell: true });
spawnSync(`ssh ${remoteHost} "cd ~/dev/main && git worktree prune"`, { shell: true });
console.log(`✅ Cleaned up ${prNumber}-${action}.`);
return 0;
}
// --- Bulk Cleanup (Old Behavior) ---
console.log(`🧹 Starting BULK cleanup on ${remoteHost}...`);
// 1. Standard Cleanup
console.log(' - Killing remote tmux sessions...');
console.log(' - Killing ALL remote tmux sessions...');
spawnSync(`ssh ${remoteHost} "tmux kill-server"`, { shell: true });
console.log(' - Cleaning up Git Worktrees...');
console.log(' - Cleaning up ALL Git Worktrees...');
spawnSync(`ssh ${remoteHost} "cd ~/dev/main && git worktree prune"`, { shell: true });
spawnSync(`ssh ${remoteHost} "rm -rf ~/dev/worktrees/*"`, { shell: true });
console.log('✅ Remote environment cleared.');
// 2. Full Wipe Option
const shouldWipe = await confirm('\nWould you like to COMPLETELY wipe the remote workspace directory?');
const shouldWipe = await confirm('\nWould you like to COMPLETELY wipe the remote workspace (main clone)?');
if (shouldWipe) {
console.log(`🔥 Wiping ~/.offload/workspace...`);
spawnSync(`gcloud compute ssh ${targetVM} --project ${projectId} --zone ${zone} --command "rm -rf ~/.offload/workspace && mkdir -p ~/.offload/workspace"`, { stdio: 'inherit', shell: true });
console.log('✅ Remote workspace wiped.');
console.log(`🔥 Wiping ~/dev/main...`);
spawnSync(`ssh ${remoteHost} "rm -rf ~/dev/main && mkdir -p ~/dev/main"`, { stdio: 'inherit', shell: true });
console.log('✅ Remote hub wiped. You will need to run npm run offload:setup again.');
}
return 0;
}
if (import.meta.url === `file://${process.argv[1]}`) {
runCleanup().catch(console.error);
runCleanup(process.argv.slice(2)).catch(console.error);
}

View File

@@ -41,29 +41,47 @@ async function provisionWorker() {
return;
}
console.log(`🚀 Provisioning container-native offload worker: ${name}...`);
console.log(`🚀 Provisioning high-performance container worker: ${name}...`);
console.log(` - Image: ${imageUri}`);
console.log(` - Disk: 200GB (High Performance)`);
// Use a startup script to run the container. This is the modern replacement
// for the deprecated create-with-container agent.
const startupScript = `#!/bin/bash
# Install Docker
apt-get update && apt-get install -y docker.io
# Authenticate to Artifact Registry
# (The VM Service Account must have Artifact Registry Reader permissions)
gcloud auth configure-docker us-docker.pkg.dev --quiet
# Pull and Run the maintainer container
docker pull ${imageUri}
docker run -d --name gemini-sandbox --restart always \\
-v /home/$(whoami)/dev:/home/node/dev:rw \\
-v /home/$(whoami)/.gemini:/home/node/.gemini:rw \\
-v /home/$(whoami)/.offload:/home/node/.offload:rw \\
${imageUri} /bin/bash -c "while true; do sleep 1000; done"
`;
const result = spawnSync('gcloud', [
'compute', 'instances', 'create-with-container', name,
'compute', 'instances', 'create', name,
'--project', PROJECT_ID,
'--zone', zone,
'--machine-type', 'n2-standard-8',
'--container-image', imageUri,
'--container-name', 'gemini-sandbox',
'--container-restart-policy', 'always',
'--container-mount-host-path', 'host-path=/home/$(whoami)/dev,mount-path=/home/node/dev,mode=rw',
'--container-mount-host-path', 'host-path=/home/$(whoami)/.gemini,mount-path=/home/node/.gemini,mode=rw',
'--container-mount-host-path', 'host-path=/home/$(whoami)/.offload,mount-path=/home/node/.offload,mode=rw',
'--boot-disk-size', '50GB',
'--image-family', 'ubuntu-2204-lts',
'--image-project', 'ubuntu-os-cloud',
'--boot-disk-size', '200GB',
'--boot-disk-type', 'pd-balanced',
'--metadata', `startup-script=${startupScript}`,
'--labels', `owner=${USER.replace(/[^a-z0-9_-]/g, '_')},type=offload-worker`,
'--tags', `gcli-offload-${USER}`,
'--scopes', 'https://www.googleapis.com/auth/cloud-platform'
], { stdio: 'inherit', shell: true });
if (result.status === 0) {
console.log(`\n✅ Container worker ${name} is being provisioned.`);
console.log(`👉 Access is managed via 'gcloud compute ssh --container'.`);
console.log(`\n✅ Worker ${name} is being provisioned.`);
console.log(`👉 Container 'gemini-sandbox' will start automatically once booted.`);
}
}

View File

@@ -55,9 +55,10 @@ function getStatus() {
console.log(`${pr.padEnd(10)} | ${action.padEnd(10)} | ${state.padEnd(12)} | ${id.padEnd(25)}`);
if (state === '🏃 RUNNING') {
console.log(` ─ Attach: npm run offload:attach ${pr} ${action} [--local]`);
console.log(` ─ Logs: npm run offload:logs ${pr} ${action}`);
console.log(` ─ Attach: npm run offload:attach ${pr} ${action} [--local]`);
console.log(` ─ Logs: npm run offload:logs ${pr} ${action}`);
}
console.log(` └─ Remove: npm run offload:remove ${pr} ${action}`);
});
console.log(''.padEnd(100, '-'));
}

View File

@@ -71,6 +71,7 @@
"offload:status": "npm run offload:fleet status",
"offload:attach": "tsx .gemini/skills/offload/scripts/attach.ts",
"offload:logs": "tsx .gemini/skills/offload/scripts/logs.ts",
"offload:remove": "tsx .gemini/skills/offload/scripts/clean.ts",
"pre-commit": "node scripts/pre-commit.js"
},
"overrides": {