PR Failure Chack-Agent Dispatch #82
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: PR Failure Chack-Agent Dispatch | |
| on: | |
| workflow_run: | |
| workflows: ["PR-tests"] | |
| types: [completed] | |
| jobs: | |
| resolve_pr_context: | |
| if: > | |
| ${{ github.event.workflow_run.conclusion == 'failure' && | |
| !startsWith(github.event.workflow_run.head_commit.message || '', 'Fix CI failures for PR #') }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: read | |
| issues: read | |
| outputs: | |
| number: ${{ steps.pr_context.outputs.number }} | |
| author: ${{ steps.pr_context.outputs.author }} | |
| head_repo: ${{ steps.pr_context.outputs.head_repo }} | |
| head_branch: ${{ steps.pr_context.outputs.head_branch }} | |
| should_run: ${{ steps.pr_context.outputs.should_run }} | |
| steps: | |
| - name: Resolve PR context | |
| id: pr_context | |
| env: | |
| PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }} | |
| HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| if [ -z "$PR_NUMBER" ] && [ -n "$HEAD_BRANCH" ]; then | |
| PR_NUMBER="$(gh pr list --state open --head "$HEAD_BRANCH" --json number --jq '.[0].number')" | |
| fi | |
| if [ -z "$PR_NUMBER" ]; then | |
| echo "No pull request found for workflow_run; skipping." | |
| { | |
| echo "number=" | |
| echo "author=" | |
| echo "head_repo=" | |
| echo "head_branch=${HEAD_BRANCH}" | |
| echo "should_run=false" | |
| } >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| pr_author=$(gh api -H "Accept: application/vnd.github+json" \ | |
| /repos/${{ github.repository }}/pulls/${PR_NUMBER} \ | |
| --jq '.user.login') | |
| pr_head_repo=$(gh api -H "Accept: application/vnd.github+json" \ | |
| /repos/${{ github.repository }}/pulls/${PR_NUMBER} \ | |
| --jq '.head.repo.full_name') | |
| pr_head_branch=$(gh api -H "Accept: application/vnd.github+json" \ | |
| /repos/${{ github.repository }}/pulls/${PR_NUMBER} \ | |
| --jq '.head.ref') | |
| pr_labels=$(gh api -H "Accept: application/vnd.github+json" \ | |
| /repos/${{ github.repository }}/issues/${PR_NUMBER} \ | |
| --jq '.labels[].name') | |
| if echo "$pr_labels" | grep -q "^chack-agent-fix-attempted$"; then | |
| echo "chack-agent fix already attempted for PR #${PR_NUMBER}; skipping." | |
| should_run=false | |
| else | |
| should_run=true | |
| fi | |
| { | |
| echo "number=${PR_NUMBER}" | |
| echo "author=${pr_author}" | |
| echo "head_repo=${pr_head_repo}" | |
| echo "head_branch=${pr_head_branch}" | |
| echo "should_run=${should_run}" | |
| } >> "$GITHUB_OUTPUT" | |
| chack_agent_on_failure: | |
| needs: resolve_pr_context | |
| if: ${{ needs.resolve_pr_context.outputs.author == 'carlospolop' && needs.resolve_pr_context.outputs.should_run == 'true' }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| actions: write | |
| env: | |
| CHACK_LOGS_HTTP_URL: ${{ secrets.CHACK_LOGS_HTTP_URL }} | |
| steps: | |
| - name: Comment on PR with failure info | |
| uses: actions/github-script@v7 | |
| env: | |
| PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }} | |
| RUN_URL: ${{ github.event.workflow_run.html_url }} | |
| WORKFLOW_NAME: ${{ github.event.workflow_run.name }} | |
| with: | |
| github-token: ${{ github.token }} | |
| script: | | |
| const prNumber = Number(process.env.PR_NUMBER); | |
| const body = `PR #${prNumber} had a failing workflow "${process.env.WORKFLOW_NAME}".\n\nRun: ${process.env.RUN_URL}\n\nLaunching Chack Agent to attempt a fix.`; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body, | |
| }); | |
| - name: Mark fix attempt | |
| env: | |
| PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }} | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| gh api -X POST -H "Accept: application/vnd.github+json" \ | |
| /repos/${{ github.repository }}/issues/${PR_NUMBER}/labels \ | |
| -f labels[]=chack-agent-fix-attempted | |
| - name: Checkout PR head | |
| uses: actions/checkout@v5 | |
| with: | |
| repository: ${{ needs.resolve_pr_context.outputs.head_repo }} | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| fetch-depth: 0 | |
| persist-credentials: true | |
| token: ${{ secrets.CODEX_FIXER_TOKEN || github.token }} | |
| - name: Configure git author | |
| run: | | |
| git config user.name "chack-agent" | |
| git config user.email "chack-agent@users.noreply.github.com" | |
| - name: Fetch failure summary | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| RUN_ID: ${{ github.event.workflow_run.id }} | |
| run: | | |
| gh api -H "Accept: application/vnd.github+json" \ | |
| /repos/${{ github.repository }}/actions/runs/$RUN_ID/jobs \ | |
| --paginate > /tmp/jobs.json | |
| python3 - <<'PY' | |
| import json | |
| data = json.load(open('/tmp/jobs.json')) | |
| lines = [] | |
| for job in data.get('jobs', []): | |
| if job.get('conclusion') == 'failure': | |
| lines.append(f"Job: {job.get('name')} (id {job.get('id')})") | |
| lines.append(f"URL: {job.get('html_url')}") | |
| for step in job.get('steps', []): | |
| if step.get('conclusion') == 'failure': | |
| lines.append(f" Step: {step.get('name')}") | |
| lines.append("") | |
| summary = "\n".join(lines).strip() or "No failing job details found." | |
| with open('chack_failure_summary.txt', 'w') as handle: | |
| handle.write(summary) | |
| PY | |
| - name: Create Chack Agent prompt | |
| env: | |
| PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }} | |
| RUN_URL: ${{ github.event.workflow_run.html_url }} | |
| HEAD_BRANCH: ${{ needs.resolve_pr_context.outputs.head_branch }} | |
| run: | | |
| { | |
| echo "You are fixing CI failures for PR #${PR_NUMBER} in ${{ github.repository }}." | |
| echo "The failing workflow run is: ${RUN_URL}" | |
| echo "The PR branch is: ${HEAD_BRANCH}" | |
| echo "" | |
| echo "Failure summary:" | |
| cat chack_failure_summary.txt | |
| echo "" | |
| echo "Please identify the cause, apply a easy, simple and minimal fix, and update files accordingly." | |
| echo "Do not edit or create any .md or .txt files and do not modify build_lists/regexes.yaml." | |
| echo "Run any fast checks you can locally (no network)." | |
| echo "Leave the repo in a state ready to commit as when you finish, it'll be automatically committed and pushed." | |
| } > chack_prompt.txt | |
| - name: Set up Node.js for Codex | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: "20" | |
| - name: Install Codex CLI | |
| run: | | |
| npm install -g @openai/codex | |
| codex --version | |
| - name: Run Chack Agent | |
| id: run_chack | |
| # Pin the action so dependency changes on its default branch cannot break PR repair. | |
| uses: carlospolop/chack-agent@9fd38a0657ae7060cc9bb07329c0bde71d7ba0d9 | |
| with: | |
| provider: codex | |
| model_primary: BEST_QUALITY | |
| main_action: peass-ng-pr-failure | |
| max_turns: 125 | |
| sub_action: PR Failure Chack-Agent Dispatch | |
| system_prompt: | | |
| You are Chack Agent, an elite CI-fix engineer. | |
| Diagnose the failing workflow, propose the minimal safe fix, and implement it. | |
| Never edit any .md or .txt files. Don't create job or summary files of you actions. | |
| Never create or modify build_lists/regexes.yaml. | |
| Run only fast, local checks (no network). Leave the repo ready to commit. | |
| prompt_file: chack_prompt.txt | |
| tools_config_json: "{\"exec_enabled\": true}" | |
| session_config_json: "{\"long_term_memory_enabled\": false}" | |
| agent_config_json: "{\"self_critique_enabled\": false, \"require_task_steps_manager_init_first\": true}" | |
| codex_access_token: ${{ secrets.CODEX_ACCESS_TOKEN }} | |
| openai_api_key: ${{ secrets.OPENAI_API_KEY }} | |
| - name: Commit and push if changed | |
| env: | |
| TARGET_BRANCH: ${{ needs.resolve_pr_context.outputs.head_branch }} | |
| PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }} | |
| ORIGINAL_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| rm -f chack_failure_summary.txt chack_prompt.txt | |
| pushed=false | |
| if ! git diff --quiet; then | |
| git add -A | |
| # Keep all fixer changes, including .github/workflows, and rely on permissioned tokens to push safely. | |
| # Only temporary tool artifacts are filtered out. | |
| git reset -- chack_failure_summary.txt chack_prompt.txt | |
| # Never commit generated or regenerated regex list files from this workflow. | |
| git reset -- build_lists/regexes.yaml || true | |
| # Never allow the agent to commit generated linpeas artifacts. | |
| git reset -- linpeas.sh linpeas_fat.sh || true | |
| while IFS= read -r forbidden_file; do | |
| git reset -- "$forbidden_file" || true | |
| done < <(git diff --name-only --cached | grep -E '(^|/)(linpeas\.sh|linpeas_fat\.sh)$' || true) | |
| while IFS= read -r file; do | |
| case "$file" in | |
| *.txt|*.md) | |
| git reset -- "$file" | |
| ;; | |
| esac | |
| done < <(git diff --name-only --cached) | |
| if git diff --cached --name-only | grep -Eq '(^|/)(linpeas\.sh|linpeas_fat\.sh)$'; then | |
| echo "Forbidden generated linpeas files are still staged; skipping push." | |
| echo "pushed=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if ! git diff --cached --quiet; then | |
| git commit -m "Fix CI failures for PR #${PR_NUMBER}" | |
| fi | |
| fi | |
| after_head="$(git rev-parse HEAD)" | |
| if [ "$after_head" = "$ORIGINAL_HEAD_SHA" ]; then | |
| echo "No commit produced by Chack Agent for PR #${PR_NUMBER}." | |
| echo "pushed=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if ! git push origin HEAD:${TARGET_BRANCH}; then | |
| echo "Push failed (likely token workflow permission limits); leaving run successful without push." | |
| echo "pushed=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| pushed=true | |
| if [ "$pushed" = "true" ]; then | |
| gh workflow run PR-tests.yml --ref "${TARGET_BRANCH}" | |
| fi | |
| - name: Comment with Chack Agent result | |
| if: ${{ steps.run_chack.outputs.final-message != '' }} | |
| uses: actions/github-script@v7 | |
| env: | |
| PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }} | |
| CHACK_MESSAGE: ${{ steps.run_chack.outputs.final-message }} | |
| with: | |
| github-token: ${{ github.token }} | |
| script: | | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: Number(process.env.PR_NUMBER), | |
| body: process.env.CHACK_MESSAGE, | |
| }); |