Skip to content

Audit Upstream Updates #20

Audit Upstream Updates

Audit Upstream Updates #20

Workflow file for this run

name: Audit Upstream Updates
on:
workflow_dispatch:
schedule:
- cron: "0 9 * * 1" # Every Monday at 9 AM
permissions:
contents: read
id-token: write
issues: write
jobs:
audit-updates:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: false
- name: Run phase-1 upstream audit (bash only)
id: audit
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
./tools/audit_upstream.sh | tee audit_table.md
{
echo "# Weekly upstream audit"
echo
cat audit_table.md
} >> "$GITHUB_STEP_SUMMARY"
items=$(wc -l < audit_upstream_items.ndjson | awk '{print $1}')
echo "items=${items:-0}" >> "$GITHUB_OUTPUT"
# Ensure the upstream-update label exists so phase-2 doesn't spend
# turns creating it.
gh label create upstream-update \
--color A0DCFB --description "Pinned submodule is behind upstream" \
2>/dev/null || true
- name: Classify changes and file issues (Claude)
if: steps.audit.outputs.items != '0'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
audit_upstream_items.ndjson in the repo root contains one JSON
object per submodule that is behind upstream. Each object has:
path, owner, repo, branch, pinned, upstream, behind, pinned_date,
upstream_date, days_stale, existing_issue, existing_state.
`existing_issue` is the number of an already-filed
"Upstream update available: <path>" issue (or empty string if
none). `existing_state` is "OPEN" or "CLOSED" when present.
For each item:
1. Fetch the commit list via
`gh api repos/{owner}/{repo}/compare/{pinned}...{upstream} --jq '.commits[] | "\(.sha[0:7]) \(.commit.message | split("\n")[0])"'`
2. Classify the diff as:
- minor : docs, CI, tests, whitespace, cosmetic only
- moderate: bug fixes, small features, dep bumps
- major : architecture/API/RTL-affecting changes, new deps
3. Decide what to do based on severity AND existing_issue:
- MINOR + no existing_issue → do nothing.
- MINOR + existing OPEN issue → `gh issue comment <n>` once
noting the change is now classified minor; do not edit
the body or close the issue (humans triage state).
- MODERATE/MAJOR + no existing_issue → `gh issue create`
with title "Upstream update available: <path>" and label
`upstream-update`.
- MODERATE/MAJOR + existing_issue (any state) →
`gh issue edit <existing_issue> --body-file <file>` with
refreshed contents. Do NOT reopen a CLOSED issue and do
NOT change its state — humans control that.
4. The body (for create or edit) contains:
- pinned → upstream SHAs and dates
- commits behind, days stale
- severity classification with justification
- short bulleted summary of what changed
- recommendation (update now / defer / ignore)
- "Last refreshed: <UTC timestamp>" footer
Never open more than one issue per submodule path. Keep per-item
work bounded: a few gh api calls each. Do not clone repos,
regenerate RTL, open PRs, or modify any files in the repo.
claude_args: '--max-turns 60 --allowedTools Bash --allowedTools Read'
- name: Upload audit artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: upstream-audit
path: |
audit_table.md
audit_upstream_items.ndjson
if-no-files-found: ignore