mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 12:54:07 -07:00
feat: add 'fix-pr' skill for agentic iterative PR fixing
This commit is contained in:
@@ -0,0 +1,60 @@
|
|||||||
|
# Fix PR Skill
|
||||||
|
|
||||||
|
This skill enables the agent to autonomously and iteratively fix a Pull Request until it is mergeable and passes all quality checks. It is designed to be run in a dedicated, non-blocking environment (like an offloaded remote session).
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
|
||||||
|
The goal is to move a PR from its current state (failing tests, merge conflicts, or unaddressed comments) to a "Ready to Merge" state.
|
||||||
|
|
||||||
|
## Iterative Fix Loop
|
||||||
|
|
||||||
|
The agent must follow this loop until the PR is green and mergeable:
|
||||||
|
|
||||||
|
### 1. Synchronization & Merge Conflicts
|
||||||
|
- Fetch latest main: `git fetch origin main`.
|
||||||
|
- Attempt to merge: `git merge origin/main`.
|
||||||
|
- **If conflicts occur**:
|
||||||
|
- Use `git status` to identify conflicted files.
|
||||||
|
- Resolve the conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) based on the project's architectural direction.
|
||||||
|
- `git add` and `git commit` the resolution.
|
||||||
|
|
||||||
|
### 2. CI Failure Analysis
|
||||||
|
- Check current status: `gh pr checks`.
|
||||||
|
- **If CI is failing**:
|
||||||
|
- Download failing logs: `gh run view --log-failed`.
|
||||||
|
- Analyze the specific error (lint, typecheck, or test failure).
|
||||||
|
- Reproduce the failure locally (e.g., `npm run lint`, `npm test -- <path>`).
|
||||||
|
- Apply a targeted fix.
|
||||||
|
|
||||||
|
### 3. Comment Resolution
|
||||||
|
- Fetch all comments: Use `scripts/fetch-pr-info.js` or `gh pr view --json reviews,comments`.
|
||||||
|
- Analyze:
|
||||||
|
- **Line-level comments**: Fix the specific logic requested.
|
||||||
|
- **Review rejections**: Address the high-level architectural concerns.
|
||||||
|
- **General comments**: Respond or implement requested changes.
|
||||||
|
- For each fixed item, summarize the change in a commit message.
|
||||||
|
|
||||||
|
### 4. Verification & Push
|
||||||
|
- Verify the fix locally: `npm run build` and relevant tests.
|
||||||
|
- **If local verification fails**: Re-analyze and apply a new fix.
|
||||||
|
- **If local verification passes**:
|
||||||
|
- `git add .`
|
||||||
|
- `git commit -m "fix: address <issue/comment>"`
|
||||||
|
- `git push origin HEAD`
|
||||||
|
|
||||||
|
### 5. Wait for CI
|
||||||
|
- Run the blocker tool: `npx tsx .gemini/skills/fix-pr/scripts/wait-for-ci.ts`.
|
||||||
|
- **If CI passes**: Move to final check.
|
||||||
|
- **If CI fails**: Repeat the loop from step 2.
|
||||||
|
|
||||||
|
## Final Check
|
||||||
|
The PR is considered "Fix Complete" when:
|
||||||
|
1. `gh pr checks` returns success for all required jobs.
|
||||||
|
2. There are no outstanding merge conflicts with `main`.
|
||||||
|
3. All critical review comments have been addressed via code changes.
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
- **Reason about failures**: Don't just guess. Read the stack traces and log files.
|
||||||
|
- **Incremental commits**: Make small, focused commits for different fixes.
|
||||||
|
- **Verify before pushing**: Always run the build/test locally before pushing to CI to save time.
|
||||||
|
- **Be Autonomous**: In an offloaded session, you have full permission to iterate until successful.
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* CI Waiter Utility for Fix PR Skill
|
||||||
|
* Blocks until GitHub checks for the current branch are complete.
|
||||||
|
*/
|
||||||
|
import { spawnSync } from 'child_process';
|
||||||
|
|
||||||
|
async function wait(ms: number) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log('🔍 Waiting for GitHub Checks to complete...');
|
||||||
|
|
||||||
|
let attempts = 0;
|
||||||
|
const maxAttempts = 30; // 15 minutes total
|
||||||
|
|
||||||
|
while (attempts < maxAttempts) {
|
||||||
|
const checkStatus = spawnSync('gh', ['pr', 'checks'], { shell: true });
|
||||||
|
const output = checkStatus.stdout.toString();
|
||||||
|
|
||||||
|
if (output.includes('fail')) {
|
||||||
|
console.log('❌ CI Failed.');
|
||||||
|
process.exit(1);
|
||||||
|
} else if (output.includes('pending')) {
|
||||||
|
console.log(`⏳ CI still pending... (check ${attempts + 1}/${maxAttempts})`);
|
||||||
|
await wait(30000); // 30 seconds
|
||||||
|
} else if (output.trim() === '') {
|
||||||
|
console.log('⚠️ No checks found yet, waiting...');
|
||||||
|
await wait(10000);
|
||||||
|
} else {
|
||||||
|
console.log('✅ CI Passed!');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error('⏰ Timeout waiting for CI.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(console.error);
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { spawnSync } from 'child_process';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
export async function runFixPlaybook(prNumber: string, targetDir: string, policyPath: string, geminiBin: string) {
|
||||||
|
console.log(`🚀 Offload | FIX | PR #${prNumber}`);
|
||||||
|
console.log('Switching to agentic fix loop inside Gemini CLI...');
|
||||||
|
|
||||||
|
// Use the nightly gemini binary to activate the fix-pr skill and iterate
|
||||||
|
const result = spawnSync(geminiBin, [
|
||||||
|
'--policy', policyPath,
|
||||||
|
'--cwd', targetDir,
|
||||||
|
'-p', `Please activate the 'fix-pr' skill and use it to iteratively fix PR #${prNumber}.
|
||||||
|
Ensure you handle CI failures, merge conflicts, and unaddressed review comments
|
||||||
|
until the PR is fully passing and mergeable.`
|
||||||
|
], { stdio: 'inherit' });
|
||||||
|
|
||||||
|
return result.status || 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user