From 63ddbdb1a5a32d3c1747ad8a9a37fea4f77a02ef Mon Sep 17 00:00:00 2001 From: Sasa Junuzovic Date: Sun, 15 Mar 2026 13:00:28 -0700 Subject: [PATCH] fix: implementer aw label + responder resolve order + rescue git config - issue-implementer: added labels: ["aw"] to create-pull-request config so the label is guaranteed at config level, not agent discretion. Closes #96. - review-responder: added explicit instruction to reply and resolve threads BEFORE pushing code. Pushing invalidates thread IDs and makes them unresolvable. Refs #95. - pr-rescue: added git config for user.name/email. Rebase fails without committer identity on GitHub Actions runner. Closes #98. - docs: fixed dismiss_stale_reviews (false not true), --auto flag, added required_conversation_resolution to branch protection example. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/issue-implementer.lock.yml | 6 ++-- .github/workflows/issue-implementer.md | 1 + .github/workflows/pr-rescue.yml | 36 ++++++++++++++------ .github/workflows/review-responder.md | 4 ++- docs/agentic-workflows.md | 7 ++-- 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/.github/workflows/issue-implementer.lock.yml b/.github/workflows/issue-implementer.lock.yml index cbc1637..ca2e66f 100644 --- a/.github/workflows/issue-implementer.lock.yml +++ b/.github/workflows/issue-implementer.lock.yml @@ -22,7 +22,7 @@ # For more information: https://github.github.com/gh-aw/introduction/overview/ # # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"4fc53e677916c7a07bd3ab866fd52f1d8f45d833aec9d14a70f8645c5c84117a","compiler_version":"v0.58.1","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"0fdf002a9a9ba94e76b837c1c539dff8d4ad8c11e051c8f5de388321b3ba09ad","compiler_version":"v0.58.1","strict":true} name: "Issue Implementer" "on": @@ -326,7 +326,7 @@ jobs: cat > /opt/gh-aw/safeoutputs/tools.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_EOF' [ { - "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created.", + "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Labels [\"aw\"] will be automatically added.", "inputSchema": { "additionalProperties": false, "properties": { @@ -1216,7 +1216,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,github.com,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,static.crates.io,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"auto_merge\":true,\"draft\":false,\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"max\":1,\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"AGENTS.md\"],\"protected_files_policy\":\"fallback-to-issue\",\"protected_path_prefixes\":[\".github/\",\".agents/\"]},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\"]}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"auto_merge\":true,\"draft\":false,\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"labels\":[\"aw\"],\"max\":1,\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"AGENTS.md\"],\"protected_files_policy\":\"fallback-to-issue\",\"protected_path_prefixes\":[\".github/\",\".agents/\"]},\"missing_data\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{\"github-token\":\"${{ secrets.GH_AW_WRITE_TOKEN }}\",\"if_no_changes\":\"warn\",\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\"]}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} GITHUB_TOKEN: ${{ secrets.GH_AW_WRITE_TOKEN }} with: diff --git a/.github/workflows/issue-implementer.md b/.github/workflows/issue-implementer.md index f600391..c9a5850 100644 --- a/.github/workflows/issue-implementer.md +++ b/.github/workflows/issue-implementer.md @@ -33,6 +33,7 @@ safe-outputs: protected-files: fallback-to-issue auto-merge: true draft: false + labels: ["aw"] push-to-pull-request-branch: github-token: ${{ secrets.GH_AW_WRITE_TOKEN }} diff --git a/.github/workflows/pr-rescue.yml b/.github/workflows/pr-rescue.yml index f4d5d98..537ecce 100644 --- a/.github/workflows/pr-rescue.yml +++ b/.github/workflows/pr-rescue.yml @@ -16,7 +16,7 @@ permissions: concurrency: group: pr-rescue - cancel-in-progress: true + cancel-in-progress: false jobs: rescue: @@ -28,6 +28,11 @@ jobs: fetch-depth: 0 token: ${{ secrets.GH_AW_WRITE_TOKEN }} + - name: Configure git identity + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + - name: Find and rebase stuck agent PRs env: GH_TOKEN: ${{ secrets.GH_AW_WRITE_TOKEN }} @@ -50,11 +55,11 @@ jobs: while IFS=' ' read -r pr_number branch; do echo "::group::Processing PR #${pr_number} (branch: ${branch})" - # Check if PR is behind main + # Check if PR is specifically behind main (not blocked for other reasons) merge_state=$(gh pr view "$pr_number" --json mergeStateStatus --jq '.mergeStateStatus') echo "Merge state: ${merge_state}" - if [ "$merge_state" != "BEHIND" ] && [ "$merge_state" != "BLOCKED" ]; then + if [ "$merge_state" != "BEHIND" ]; then echo "PR #${pr_number} is not behind main (state: ${merge_state}). Skipping." echo "::endgroup::" continue @@ -70,17 +75,28 @@ jobs: echo "PR #${pr_number} is approved but behind main. Rebasing..." - git fetch origin "$branch" - git checkout "$branch" + if ! git fetch origin "$branch" 2>&1; then + echo "::warning::Failed to fetch branch for PR #${pr_number}. Branch may have been deleted. Skipping." + echo "::endgroup::" + continue + fi + + if ! git checkout "$branch" 2>&1; then + echo "::warning::Failed to checkout branch for PR #${pr_number}. Skipping." + echo "::endgroup::" + continue + fi if git rebase origin/main; then - echo "Rebase successful. Pushing..." - git push --force-with-lease origin "$branch" - echo "✅ PR #${pr_number} rebased. CI will rerun, approval survives, auto-merge will fire." - rescued=$((rescued + 1)) + if git push --force-with-lease origin "$branch" 2>&1; then + echo "✅ PR #${pr_number} rebased. CI will rerun, approval survives, auto-merge will fire." + rescued=$((rescued + 1)) + else + echo "::warning::Push failed for PR #${pr_number}. Branch may have been updated. Skipping." + fi else echo "::warning::Rebase failed for PR #${pr_number} — likely has conflicts. Skipping." - git rebase --abort + git rebase --abort 2>/dev/null || true fi git checkout main diff --git a/.github/workflows/review-responder.md b/.github/workflows/review-responder.md index d3a876e..3c43005 100644 --- a/.github/workflows/review-responder.md +++ b/.github/workflows/review-responder.md @@ -66,6 +66,8 @@ This workflow runs when a review is submitted on a pull request. 7. After addressing all comments, run the CI checks locally to make sure your fixes don't break anything: `uv sync && uv run ruff check --fix . && uv run ruff format . && uv run pyright && uv run pytest --cov --cov-fail-under=80 -v` -8. Push all changes in a single commit with message "fix: address review comments". +8. **IMPORTANT**: You MUST reply to threads and resolve them BEFORE pushing code. Pushing code invalidates thread IDs and makes them unresolvable. The correct order is: reply → resolve → push. + +9. Push all changes in a single commit with message "fix: address review comments". If a review comment requests a change that would be architecturally significant or you're unsure about, reply to the thread explaining your concern rather than making the change blindly. diff --git a/docs/agentic-workflows.md b/docs/agentic-workflows.md index 29cb85a..a2e2072 100644 --- a/docs/agentic-workflows.md +++ b/docs/agentic-workflows.md @@ -352,10 +352,11 @@ gh api repos/OWNER/REPO/branches/main/protection -X PUT --input - <<'EOF' "required_status_checks": { "strict": true, "contexts": ["check"] }, "enforce_admins": true, "required_pull_request_reviews": { - "dismiss_stale_reviews": true, + "dismiss_stale_reviews": false, "required_approving_review_count": 1 }, - "restrictions": null + "restrictions": null, + "required_conversation_resolution": true } EOF ``` @@ -381,7 +382,7 @@ gh api repos/OWNER/REPO/branches/main/protection/enforce_admins -X POST # 5. Re-enable auto-merge on those PRs for pr in ; do - gh pr merge --enable-auto --merge "$pr" + gh pr merge --auto --merge "$pr" done ```