mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-08-14 17:12:30 +02:00
Bumps [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) from 1.0.181 to 1.0.183.
- [Release notes](https://github.com/anthropics/claude-code-action/releases)
- [Commits](44423bdec7...be7b93b190)
---
updated-dependencies:
- dependency-name: anthropics/claude-code-action
dependency-version: 1.0.183
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
199 lines
9.1 KiB
YAML
199 lines
9.1 KiB
YAML
---
|
|
# Destination: .github/workflows/daily_ai_fix.yaml
|
|
#
|
|
# Tier 2 of the AI triage system. One Opus 5 run at xhigh over the whole
|
|
# batch of `ai-triage` issues, grouped by add-on, so it can spot the cross-issue
|
|
# patterns a per-issue run never sees ("these four reports are all the same base
|
|
# image bump"). Runs daily rather than weekly, so batches (default limit 8) stay
|
|
# small and any one day's failure doesn't block a week's worth of issues.
|
|
#
|
|
# This is the Opus step — root-cause diagnosis and, for anything not clearly a
|
|
# small confident fix, the written plan. Per issue it produces one of:
|
|
# * high certainty + small change -> a READY-for-review PR (ai:fixed)
|
|
# * medium certainty, or too large -> a full plan comment, no PR (ai:plan-pending)
|
|
# Alex then adds `ai:approved` and on_issue_approved.yaml (tier 3) executes
|
|
# the plan. This is the "create the full plan, ask for approval only when
|
|
# not sure" path — cheap to gate, immediate once approved.
|
|
# * fault is upstream / no fix -> analysis only (ai:upstream / ai:needs-human)
|
|
#
|
|
# Full tier map:
|
|
# Tier 1 on_issues_ai_triage.yaml Sonnet-low classify on issue open
|
|
# Tier 2 daily_ai_fix.yaml (this) Opus 5-xhigh daily fix/plan sweep
|
|
# Tier 3 on_issue_approved.yaml Opus 5-high execute an approved plan
|
|
# @claude on_claude_mention.yml Sonnet-low maintainer-only interactive
|
|
# PR on_pr_coderabbit.yml Sonnet-low one-shot CodeRabbit follow-up
|
|
# Kill switch: set repo variable AI_DISABLED=true to pause every AI workflow.
|
|
#
|
|
# Auth:
|
|
# Claude Pro/Max subscription via the CR_PAT GitHub Environment, which
|
|
# holds the CLAUDE_CODE_OAUTH_TOKEN secret (generate with `claude setup-token`).
|
|
# AI_PR_TOKEN — GitHub App token or PAT (repo scope). NOT GITHUB_TOKEN:
|
|
# pull requests created with GITHUB_TOKEN do not trigger
|
|
# other workflows, so your PR Check Build would never run.
|
|
|
|
name: AI fix sweep
|
|
|
|
on:
|
|
schedule:
|
|
- cron: "0 3 * * *"
|
|
workflow_dispatch:
|
|
inputs:
|
|
issue:
|
|
description: "Single issue number (blank = all ai-triage issues)"
|
|
required: false
|
|
limit:
|
|
description: "Max issues in the batch"
|
|
required: false
|
|
default: "8"
|
|
|
|
permissions:
|
|
contents: write
|
|
issues: write
|
|
pull-requests: write
|
|
|
|
concurrency:
|
|
group: ai-fix-sweep
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
sweep:
|
|
# Global kill switch: set repo variable AI_DISABLED=true to pause the sweep
|
|
# (and every other AI workflow) without editing any file.
|
|
if: ${{ vars.AI_DISABLED != 'true' }}
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 180
|
|
environment: CR_PAT
|
|
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
token: ${{ secrets.AI_PR_TOKEN }}
|
|
|
|
- name: Collect batch
|
|
id: batch
|
|
env:
|
|
GH_TOKEN: ${{ secrets.AI_PR_TOKEN }}
|
|
REPO: ${{ github.repository }}
|
|
# workflow_dispatch inputs land here instead of being interpolated
|
|
# directly into the script below — expanding "${{ }}" inline would
|
|
# splice attacker/typo-controlled text into the shell source itself
|
|
# rather than passing it as data.
|
|
ISSUE_INPUT: ${{ inputs.issue }}
|
|
LIMIT_INPUT: ${{ inputs.limit || '8' }}
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p /tmp/ai-fix
|
|
[[ "$LIMIT_INPUT" =~ ^[1-9][0-9]*$ ]] || { echo "::error::limit must be a positive integer, got '$LIMIT_INPUT'"; exit 1; }
|
|
if [ -n "$ISSUE_INPUT" ]; then
|
|
[[ "$ISSUE_INPUT" =~ ^[0-9]+$ ]] || { echo "::error::issue must be a number, got '$ISSUE_INPUT'"; exit 1; }
|
|
gh issue view "$ISSUE_INPUT" --repo "$REPO" \
|
|
--json number,title,body,labels,comments \
|
|
| jq '[.]' > /tmp/ai-fix/batch.json
|
|
else
|
|
gh issue list --repo "$REPO" --state open \
|
|
--label ai-triage --limit "$LIMIT_INPUT" \
|
|
--json number,title,body,labels,comments > /tmp/ai-fix/batch.json
|
|
fi
|
|
N=$(jq 'length' /tmp/ai-fix/batch.json)
|
|
echo "count=$N" >> "$GITHUB_OUTPUT"
|
|
echo "batch size: $N"
|
|
|
|
- name: Configure git
|
|
if: steps.batch.outputs.count != '0'
|
|
run: |
|
|
git config user.name "claude-ai-fix[bot]"
|
|
git config user.email "claude-ai-fix[bot]@users.noreply.github.com"
|
|
|
|
# Created up front so issue-fix.md's per-issue relabel never has to
|
|
# improvise a color or retry a "label does not exist" error — that's a
|
|
# wasted turn multiplied by every issue in the batch. Also covers
|
|
# ai:blocked, which the forbidden-paths guard applies later in this
|
|
# same job: with set -euo pipefail, `gh pr edit --add-label` on a
|
|
# label that doesn't exist yet fails and aborts that step's loop
|
|
# entirely, silently skipping every remaining PR behind it.
|
|
- name: Ensure control labels exist
|
|
if: steps.batch.outputs.count != '0'
|
|
env:
|
|
GH_TOKEN: ${{ secrets.AI_PR_TOKEN }}
|
|
REPO: ${{ github.repository }}
|
|
run: |
|
|
set -euo pipefail
|
|
for l in ai:fixed ai:plan-pending ai:approved ai:upstream ai:needs-human ai:blocked; do
|
|
gh label create "$l" --repo "$REPO" --color ededed --force >/dev/null 2>&1 || true
|
|
done
|
|
|
|
- name: Analyse and fix
|
|
if: steps.batch.outputs.count != '0'
|
|
uses: anthropics/claude-code-action@be7b93b1907a4abad570368f3c74b6fe3807510b # v1
|
|
with:
|
|
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
# Skip the OIDC -> Claude App token exchange. The scheduled path
|
|
# happens to pass it (github.actor is the maintainer), but
|
|
# workflow_dispatch by anyone else would 401. AI_PR_TOKEN, not
|
|
# GITHUB_TOKEN, so a PR Claude opens triggers CI.
|
|
github_token: ${{ secrets.AI_PR_TOKEN }}
|
|
# No track_progress here. It needs an issue or PR to hang its sticky
|
|
# comment on, and the action hard-fails validation without one; this
|
|
# workflow only ever runs on schedule/workflow_dispatch. Per-issue
|
|
# progress still gets reported — issue-fix.md has Claude comment on
|
|
# each issue directly via gh.
|
|
prompt: |
|
|
The batch of issues to work through is /tmp/ai-fix/batch.json.
|
|
Follow .github/prompts/issue-fix.md exactly. Do not deviate from
|
|
the path restrictions in that file under any circumstances.
|
|
claude_args: |
|
|
--model claude-opus-5
|
|
--effort xhigh
|
|
--max-turns 300
|
|
--allowedTools "Read,Write,Edit,Glob,Grep,Bash(git:*),Bash(gh:*),Bash(shellcheck:*),Bash(yamllint:*),Bash(docker build:*)"
|
|
env:
|
|
GH_TOKEN: ${{ secrets.AI_PR_TOKEN }}
|
|
|
|
# Belt and braces. issue-fix.md instructs Claude to drop the ai-triage
|
|
# label off every issue it finishes with (hard limit 6), so tomorrow's
|
|
# sweep never re-selects and re-spends a full read-and-fix pass on
|
|
# work that's already done. Enforce it here in case a turn or timeout
|
|
# budget runs out before the relabel step of the last issue or two.
|
|
- name: Guard against repeat processing
|
|
if: always() && steps.batch.outputs.count != '0'
|
|
env:
|
|
GH_TOKEN: ${{ secrets.AI_PR_TOKEN }}
|
|
REPO: ${{ github.repository }}
|
|
run: |
|
|
set -euo pipefail
|
|
mapfile -t ISSUES < <(jq -r '.[].number' /tmp/ai-fix/batch.json)
|
|
for n in "${ISSUES[@]}"; do
|
|
STILL=$(gh issue view "$n" --repo "$REPO" --json labels \
|
|
--jq '[.labels[].name] | index("ai-triage") != null' 2>/dev/null) || {
|
|
echo "::warning::could not re-check issue #$n (deleted or transferred?), skipping"
|
|
continue
|
|
}
|
|
if [ "$STILL" = "true" ]; then
|
|
echo "::warning::issue #$n still carries ai-triage after the sweep, forcing it out of tomorrow's batch"
|
|
gh issue edit "$n" --repo "$REPO" \
|
|
--remove-label ai-triage --add-label ai:needs-human
|
|
fi
|
|
done
|
|
|
|
# Belt and braces. The prompt forbids .github/ and .templates/; this
|
|
# enforces it over every open ai-fix/ PR (shared by tiers 2, 3 and the
|
|
# CodeRabbit follow-up, so the rule lives in exactly one place).
|
|
- name: Guard forbidden paths
|
|
if: always() && steps.batch.outputs.count != '0'
|
|
env:
|
|
GH_TOKEN: ${{ secrets.AI_PR_TOKEN }}
|
|
REPO: ${{ github.repository }}
|
|
run: |
|
|
set -euo pipefail
|
|
# Run the guard from the trusted default-branch copy, never the in-tree
|
|
# copy the model could have modified in this same job.
|
|
DEFAULT=$(gh api "repos/${REPO}" --jq '.default_branch' 2>/dev/null || echo master)
|
|
if git fetch --depth=1 origin "$DEFAULT" >/dev/null 2>&1 \
|
|
&& git cat-file -e "FETCH_HEAD:.github/scripts/ai_guard_paths.sh" 2>/dev/null; then
|
|
git show "FETCH_HEAD:.github/scripts/ai_guard_paths.sh" | bash
|
|
else
|
|
echo "::warning::trusted guard copy unavailable, using in-tree copy"
|
|
bash .github/scripts/ai_guard_paths.sh
|
|
fi
|