mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-30 16:00:41 -07:00
chore: final cleanup of offload configuration paths and test assertions
This commit is contained in:
@@ -51,7 +51,7 @@ npm run offload:clean
|
||||
|
||||
## Technical details
|
||||
|
||||
This skill uses an isolated Gemini profile on the remote host (`~/.gemini-deep-review`) to ensure that verification tasks do not interfere with your primary configuration.
|
||||
This skill uses an isolated Gemini profile on the remote host (`~/.offload/gemini-cli-config`) to ensure that verification tasks do not interfere with your primary configuration.
|
||||
|
||||
### Directory structure
|
||||
- `scripts/orchestrator.ts`: Local orchestrator (syncs scripts and pops terminal).
|
||||
|
||||
@@ -32,6 +32,6 @@ Provide a structured assessment based on the physical proof and logs:
|
||||
* **Conclusion**: A clear next step for the maintainer.
|
||||
|
||||
## Best Practices
|
||||
* **Isolation First**: Always respect the user's isolation choices (`~/.gemini-deep-review`).
|
||||
* **Isolation First**: Always respect the user's isolation choices (`~/.offload/gemini-cli-config`).
|
||||
* **Be Behavioral**: Prioritize results from live execution (behavioral proofs) over static reading.
|
||||
* **Multi-tasking**: Remind the user they can continue chatting in the main window while the heavy offloaded task runs in the separate window.
|
||||
|
||||
@@ -13,7 +13,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const prNumber = process.argv[2];
|
||||
const branchName = process.argv[3];
|
||||
const policyPath = process.argv[4];
|
||||
const ISOLATED_CONFIG = process.env.GEMINI_CLI_HOME || path.join(process.env.HOME || '', '.gemini-deep-review');
|
||||
const ISOLATED_CONFIG = process.env.GEMINI_CLI_HOME || path.join(process.env.HOME || '', '.offload/gemini-cli-config');
|
||||
|
||||
async function main() {
|
||||
if (!prNumber || !branchName || !policyPath) {
|
||||
|
||||
@@ -51,9 +51,9 @@ export async function runOrchestrator(args: string[], env: NodeJS.ProcessEnv = p
|
||||
const sessionName = `offload-${prNumber}-${branchName.replace(/[^a-zA-Z0-9]/g, '-')}`;
|
||||
|
||||
// 2. Sync Configuration Mirror (Isolated Profiles)
|
||||
const ISOLATED_GEMINI = geminiSetup === 'isolated' ? '~/.gemini-deep-review' : '~/.gemini';
|
||||
const ISOLATED_GH = ghSetup === 'isolated' ? '~/.gh-deep-review' : '~/.config/gh';
|
||||
const remotePolicyPath = `${ISOLATED_GEMINI}/policies/deep-review-policy.toml`;
|
||||
const ISOLATED_GEMINI = geminiSetup === 'isolated' ? '~/.offload/gemini-cli-config' : '~/.gemini';
|
||||
const ISOLATED_GH = ghSetup === 'isolated' ? '~/.offload/gh-cli-config' : '~/.config/gh';
|
||||
const remotePolicyPath = `${ISOLATED_GEMINI}/policies/offload-policy.toml`;
|
||||
|
||||
console.log(`📡 Mirroring environment to ${remoteHost}...`);
|
||||
spawnSync('ssh', [remoteHost, `mkdir -p ${remoteWorkDir}/.gemini/skills/offload/scripts/ ${ISOLATED_GEMINI}/policies/`]);
|
||||
|
||||
@@ -48,8 +48,8 @@ export async function runSetup(env: NodeJS.ProcessEnv = process.env) {
|
||||
const ghChoice = await prompt('GitHub CLI Setup: Use [p]re-existing instance or [i]solated sandbox instance? (Isolated is recommended)', 'i');
|
||||
const ghSetup = ghChoice.toLowerCase() === 'p' ? 'preexisting' : 'isolated';
|
||||
|
||||
const ISOLATED_GEMINI_CONFIG = '~/.gemini-deep-review';
|
||||
const ISOLATED_GH_CONFIG = '~/.gh-deep-review';
|
||||
const ISOLATED_GEMINI_CONFIG = '~/.offload/gemini-cli-config';
|
||||
const ISOLATED_GH_CONFIG = '~/.offload/gh-cli-config';
|
||||
|
||||
console.log(`🔍 Checking state of ${remoteHost}...`);
|
||||
// Use a login shell to ensure the same PATH as the interactive user
|
||||
|
||||
@@ -65,37 +65,17 @@ describe('Offload Tooling Matrix', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Fix Loop', () => {
|
||||
it('should iterate until CI passes', async () => {
|
||||
let checkAttempts = 0;
|
||||
vi.mocked(spawnSync).mockImplementation((cmd: any, args: any) => {
|
||||
// Correctly check command AND args
|
||||
const isCheck = (typeof cmd === 'string' && cmd.includes('pr checks')) ||
|
||||
(Array.isArray(args) && args.includes('checks'));
|
||||
|
||||
if (isCheck) {
|
||||
checkAttempts++;
|
||||
return { status: 0, stdout: Buffer.from(checkAttempts === 1 ? 'fail' : 'success') } as any;
|
||||
}
|
||||
return { status: 0, stdout: Buffer.from('test-branch\n') } as any;
|
||||
});
|
||||
|
||||
vi.useFakeTimers();
|
||||
describe('Fix Playbook', () => {
|
||||
it('should launch the agentic fix-pr skill', async () => {
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
|
||||
const workerPromise = runWorker(['123', 'test-branch', '/path/policy', 'fix']);
|
||||
await runWorker(['123', 'test-branch', '/path/policy', 'fix']);
|
||||
|
||||
// Multi-stage timer flush to get through TaskRunner cycles and the polling loop
|
||||
for(let i=0; i<10; i++) {
|
||||
await vi.advanceTimersByTimeAsync(2000);
|
||||
}
|
||||
|
||||
await vi.advanceTimersByTimeAsync(40000); // 1st fail
|
||||
for(let i=0; i<10; i++) { await vi.advanceTimersByTimeAsync(2000); }
|
||||
await vi.advanceTimersByTimeAsync(40000); // 2nd pass
|
||||
|
||||
await workerPromise;
|
||||
expect(checkAttempts).toBe(2);
|
||||
vi.useRealTimers();
|
||||
const spawnSyncCalls = vi.mocked(spawnSync).mock.calls;
|
||||
const fixCall = spawnSyncCalls.find(call =>
|
||||
JSON.stringify(call).includes("activate the 'fix-pr' skill")
|
||||
);
|
||||
expect(fixCall).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -78,9 +78,32 @@ describe('Offload Orchestration', () => {
|
||||
await runOrchestrator(['123'], {});
|
||||
const spawnCalls = vi.mocked(spawnSync).mock.calls;
|
||||
const sshCall = spawnCalls.find(call => typeof call[0] === 'string' && call[0].includes('tmux new-session'));
|
||||
// Match the new 'offload-123-test-branch' format
|
||||
expect(sshCall![0]).toContain('offload-123-test-branch');
|
||||
});
|
||||
|
||||
it('should use isolated config path when geminiSetup is isolated', async () => {
|
||||
const isolatedSettings = {
|
||||
...mockSettings,
|
||||
maintainer: {
|
||||
...mockSettings.maintainer,
|
||||
deepReview: {
|
||||
...mockSettings.maintainer.deepReview,
|
||||
geminiSetup: 'isolated'
|
||||
}
|
||||
}
|
||||
};
|
||||
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify(isolatedSettings));
|
||||
|
||||
await runOrchestrator(['123'], {});
|
||||
|
||||
const spawnCalls = vi.mocked(spawnSync).mock.calls;
|
||||
const sshCall = spawnCalls.find(call => {
|
||||
const cmdStr = typeof call[0] === 'string' ? call[0] : '';
|
||||
return cmdStr.includes('GEMINI_CLI_HOME=~/.offload/gemini-cli-config');
|
||||
});
|
||||
|
||||
expect(sshCall).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setup.ts', () => {
|
||||
@@ -99,6 +122,8 @@ describe('Offload Orchestration', () => {
|
||||
const remoteCmd = args[1];
|
||||
if (remoteCmd.includes('[ -d ~/test-dir/.git ]')) return { status: 0 } as any;
|
||||
if (remoteCmd.includes('command -v')) return { status: 0 } as any;
|
||||
if (remoteCmd.includes('gh auth status')) return { status: 0 } as any;
|
||||
if (remoteCmd.includes('google_accounts.json')) return { status: 0 } as any;
|
||||
}
|
||||
return { status: 0, stdout: Buffer.from(''), stderr: Buffer.from('') } as any;
|
||||
});
|
||||
@@ -122,15 +147,15 @@ describe('Offload Orchestration', () => {
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
await runWorker(['123', 'test-branch', '/test-policy.toml', 'review']);
|
||||
const spawnCalls = vi.mocked(spawn).mock.calls;
|
||||
expect(spawnCalls.some(c => c[0].includes('/review-frontend'))).toBe(true);
|
||||
expect(spawnCalls.some(c => c[0].includes("activate the 'review-pr' skill"))).toBe(true);
|
||||
});
|
||||
|
||||
it('should launch the fix playbook when requested', async () => {
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
await runWorker(['123', 'test-branch', '/test-policy.toml', 'fix']);
|
||||
const spawnCalls = vi.mocked(spawn).mock.calls;
|
||||
// Match the updated prompt string in fix.ts
|
||||
expect(spawnCalls.some(c => c[0].toLowerCase().includes('analyze current failures'))).toBe(true);
|
||||
// runFixPlaybook uses spawnSync
|
||||
const spawnSyncCalls = vi.mocked(spawnSync).mock.calls;
|
||||
expect(spawnSyncCalls.some(c => JSON.stringify(c).includes("activate the 'fix-pr' skill"))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user