Files
PEASS-ng/.github/workflows/ci-master-failure-chack-agent-pr.yml
Carlos Polop d44e5b5c5b f
2026-03-07 15:01:54 +01:00

287 lines
12 KiB
YAML

name: CI-master Failure Chack-Agent PR
on:
workflow_run:
workflows: ["CI-master_test"]
types: [completed]
jobs:
chack_agent_fix_master_failure:
if: >
${{ github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.head_branch == 'master' &&
!startsWith(github.event.workflow_run.head_commit.message, 'Fix CI-master failures for run #') }}
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
actions: read
env:
TARGET_BRANCH: master
FIX_BRANCH: chack-agent/ci-master-fix-${{ github.event.workflow_run.id }}
CHACK_LOGS_HTTP_URL: ${{ secrets.CHACK_LOGS_HTTP_URL }}
CAN_PUSH_WORKFLOWS: ${{ secrets.CHACK_AGENT_FIXER_TOKEN != '' }}
steps:
- name: Checkout failing commit
uses: actions/checkout@v5
with:
ref: ${{ github.event.workflow_run.head_sha }}
fetch-depth: 0
persist-credentials: true
token: ${{ secrets.CHACK_AGENT_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: Create fix branch
run: git checkout -b "$FIX_BRANCH"
- name: Fetch failure summary and failed-step logs
env:
GH_TOKEN: ${{ github.token }}
RUN_ID: ${{ github.event.workflow_run.id }}
run: |
failed_logs_file="$(pwd)/chack_failed_steps_logs.txt"
if gh run view "$RUN_ID" --repo "${{ github.repository }}" --log-failed > "$failed_logs_file"; then
if [ ! -s "$failed_logs_file" ]; then
echo "No failed step logs were returned by gh run view --log-failed." > "$failed_logs_file"
fi
else
echo "Failed to download failed step logs with gh run view --log-failed." > "$failed_logs_file"
fi
echo "FAILED_LOGS_PATH=$failed_logs_file" >> "$GITHUB_ENV"
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:
RUN_URL: ${{ github.event.workflow_run.html_url }}
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
run: |
{
echo "You are fixing a failing CI-master_test run in ${{ github.repository }}."
echo "The failing workflow run is: ${RUN_URL}"
echo "The failing commit SHA is: ${HEAD_SHA}"
echo "The target branch for the final PR is: ${TARGET_BRANCH}"
echo ""
echo "Failure summary:"
cat chack_failure_summary.txt
echo ""
echo "Failed-step logs file absolute path (local runner): ${FAILED_LOGS_PATH}"
echo "Read that file to inspect the exact failing logs."
echo ""
echo "Please identify the cause, apply an easy, simple and minimal fix, and update files accordingly."
echo "Workflow-file edits are allowed when required to fix the failing run."
echo "Do not edit or create any .md or .txt files or any summary file and do not modify build_lists/regexes.yaml. Don't create job or summary files of you actions."
echo "Run any fast checks you can locally (no network)."
echo "Leave the repo in a state ready to commit; changes will be committed and pushed automatically."
} > 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
uses: carlospolop/chack-agent@master
with:
provider: codex
model_primary: CHEAP_BUT_QUALITY
max_turns: 125
main_action: peass-ng-master-failure
sub_action: CI-master Failure Chack-Agent PR
system_prompt: |
Diagnose the failing gh actions workflow, propose the minimal and effective safe fix, and implement it.
Workflow-file edits are allowed when needed to fix the failure.
Never edit any .md or .txt files.
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}"
openai_api_key: ${{ secrets.OPENAI_API_KEY }}
- name: Commit and push fix branch if changed
id: push_fix
env:
ORIGINAL_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
run: |
rm -f chack_failure_summary.txt chack_prompt.txt chack_failed_steps_logs.txt
pushed=false
if ! git diff --quiet; then
git add -A
if [ "$CAN_PUSH_WORKFLOWS" != "true" ]; then
# Avoid workflow-file pushes with token scopes that cannot write workflows.
git reset -- .github/workflows || true
git checkout -- .github/workflows || true
git clean -fdx -- .github/workflows || true
fi
git reset -- chack_failure_summary.txt chack_prompt.txt chack_failed_steps_logs.txt
# Never include generated regex list updates in automated fixer commits.
git reset -- build_lists/regexes.yaml || true
while IFS= read -r file; do
case "$file" in
*.txt|*.md)
git reset -- "$file"
;;
esac
done < <(git diff --name-only --cached)
if [ "$CAN_PUSH_WORKFLOWS" != "true" ] && git diff --cached --name-only | grep -q '^.github/workflows/'; then
echo "Workflow-file changes are still staged; skipping push without workflows permission."
echo "pushed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if ! git diff --cached --quiet; then
git commit -m "Fix CI-master failures for run #${{ github.event.workflow_run.id }}"
fi
fi
after_head="$(git rev-parse HEAD)"
if [ "$after_head" = "$ORIGINAL_HEAD_SHA" ]; then
echo "No commit produced by Chack Agent."
echo "pushed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ "$CAN_PUSH_WORKFLOWS" = "true" ]; then
echo "Sanitizing Chack commit range, preserving workflow fixes."
git diff --binary "$ORIGINAL_HEAD_SHA"..HEAD -- \
. \
':(exclude)chack_failure_summary.txt' \
':(exclude)chack_prompt.txt' \
':(exclude)chack_failed_steps_logs.txt' \
':(exclude)build_lists/regexes.yaml' \
':(exclude)*.md' \
':(exclude)*.txt' \
':(exclude)**/*.txt' \
':(exclude)**/*.md' > /tmp/chack_sanitized.patch
else
echo "Sanitizing Chack commit range to non-workflow changes only."
git diff --binary "$ORIGINAL_HEAD_SHA"..HEAD -- \
. \
':(exclude).github/workflows/**' \
':(exclude)chack_failure_summary.txt' \
':(exclude)chack_prompt.txt' \
':(exclude)chack_failed_steps_logs.txt' \
':(exclude)build_lists/regexes.yaml' \
':(exclude)*.md' \
':(exclude)*.txt' \
':(exclude)**/*.txt' \
':(exclude)**/*.md' > /tmp/chack_sanitized.patch
if [ ! -s /tmp/chack_sanitized.patch ]; then
echo "Only workflow-file changes were produced; skipping push."
echo "pushed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
fi
git reset --hard "$ORIGINAL_HEAD_SHA"
git apply --index /tmp/chack_sanitized.patch
rm -f chack_failure_summary.txt chack_prompt.txt chack_failed_steps_logs.txt
git reset -- chack_failure_summary.txt chack_prompt.txt chack_failed_steps_logs.txt || true
if git diff --cached --quiet; then
echo "No sanitized changes left after filtering."
echo "pushed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
git commit -m "Fix CI-master failures for run #${{ github.event.workflow_run.id }}"
if ! git push origin HEAD:"$FIX_BRANCH"; then
echo "Push failed (likely token workflow permission limits); skipping PR creation."
echo "pushed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
pushed=true
if [ "$pushed" = "true" ]; then
echo "pushed=true" >> "$GITHUB_OUTPUT"
else
echo "pushed=false" >> "$GITHUB_OUTPUT"
fi
- name: Create PR to master
if: ${{ steps.push_fix.outputs.pushed == 'true' }}
id: create_pr
env:
GH_TOKEN: ${{ secrets.CHACK_AGENT_FIXER_TOKEN || github.token }}
RUN_URL: ${{ github.event.workflow_run.html_url }}
run: |
set +e
pr_output=$(gh pr create \
--title "Fix CI-master_test failure (run #${{ github.event.workflow_run.id }})" \
--body "Automated Chack Agent fix for failing CI-master_test run: ${RUN_URL}" \
--base "$TARGET_BRANCH" \
--head "$FIX_BRANCH" 2>&1)
rc=$?
set -e
if [ $rc -eq 0 ]; then
echo "url=$pr_output" >> "$GITHUB_OUTPUT"
echo "created=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "$pr_output"
if echo "$pr_output" | grep -qi "not permitted to create or approve pull requests"; then
echo "PR creation blocked by repository Actions policy. Fix branch was pushed: $FIX_BRANCH"
echo "url=" >> "$GITHUB_OUTPUT"
echo "created=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Unexpected PR creation error."
exit $rc
- name: Comment on created PR with Chack Agent result
if: ${{ steps.push_fix.outputs.pushed == 'true' && steps.create_pr.outputs.created == 'true' && steps.run_chack.outputs.final-message != '' }}
uses: actions/github-script@v7
env:
PR_URL: ${{ steps.create_pr.outputs.url }}
CHACK_MESSAGE: ${{ steps.run_chack.outputs.final-message }}
with:
github-token: ${{ github.token }}
script: |
const prUrl = process.env.PR_URL;
const match = prUrl.match(/\/pull\/(\d+)$/);
if (!match) {
core.info(`Could not parse PR number from URL: ${prUrl}`);
return;
}
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: Number(match[1]),
body: process.env.CHACK_MESSAGE,
});