Agent CI Feedback #2296
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: Agent CI Feedback | |
| on: | |
| workflow_run: | |
| workflows: ["CI", "PR Validation"] | |
| types: [completed] | |
| permissions: | |
| pull-requests: write | |
| issues: write | |
| actions: read | |
| jobs: | |
| notify-agent: | |
| name: Notify Agent of CI Failure | |
| if: >- | |
| vars.AGENT_ENABLED == 'true' && | |
| github.event.workflow_run.conclusion == 'failure' && | |
| github.event.workflow_run.event == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Generate App token | |
| id: app-token | |
| uses: actions/create-github-app-token@v3 | |
| with: | |
| app-id: ${{ secrets.AGENT_APP_ID }} | |
| private-key: ${{ secrets.AGENT_APP_PRIVATE_KEY }} | |
| - name: Post CI failure feedback to agent PR | |
| uses: actions/github-script@v9 | |
| with: | |
| github-token: ${{ steps.app-token.outputs.token }} | |
| script: | | |
| const runId = context.payload.workflow_run.id; | |
| const workflowName = context.payload.workflow_run.name; | |
| // Get the PR associated with this workflow run | |
| const { data: { pull_requests: prs } } = await github.rest.actions.getWorkflowRun({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: runId | |
| }); | |
| if (!prs || prs.length === 0) { | |
| core.info('No PR associated with this workflow run'); | |
| return; | |
| } | |
| const prNumber = prs[0].number; | |
| // Get the PR to check if it's an agent PR | |
| const { data: pr } = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: prNumber | |
| }); | |
| if (!pr.head.ref.startsWith('agent/')) { | |
| core.info(`PR #${prNumber} is not an agent PR (branch: ${pr.head.ref})`); | |
| return; | |
| } | |
| // Count existing CI feedback rounds to prevent infinite loops | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber | |
| }); | |
| const ciFixRounds = comments.filter(c => | |
| c.body.includes('<!-- agent-ci-fix-round') | |
| ).length; | |
| if (ciFixRounds >= 2) { | |
| core.info(`PR #${prNumber} already has ${ciFixRounds} CI fix rounds, leaving for human review`); | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: `<!-- agent-ci-fix-round: ${ciFixRounds + 1} -->\n\nThe **${workflowName}** workflow has failed ${ciFixRounds + 1} times on this agent PR. Remaining CI issues require human review.\n\n[View failed run](${context.payload.workflow_run.html_url})` | |
| }); | |
| return; | |
| } | |
| // Get failed jobs for context | |
| const { data: { jobs } } = await github.rest.actions.listJobsForWorkflowRun({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: runId, | |
| filter: 'latest' | |
| }); | |
| const failedJobs = jobs | |
| .filter(j => j.conclusion === 'failure') | |
| .map(j => `- **${j.name}**: [view logs](${j.html_url})`) | |
| .join('\n'); | |
| const round = ciFixRounds + 1; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: `<!-- agent-ci-fix-round: ${round} -->\n\n@goudengine-agent The **${workflowName}** workflow failed on this PR (round ${round}/2). Please investigate and fix the failures.\n\n### Failed jobs\n${failedJobs || '_No individual job failures found — check the workflow run._'}\n\n[View full run](${context.payload.workflow_run.html_url})` | |
| }); | |
| core.info(`Posted CI failure feedback for PR #${prNumber} (round ${round})`); |