From 8479c086796e53205c34142038c65f885c2e3e76 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Wed, 4 Mar 2026 18:08:08 +0700 Subject: "Claude Code Review workflow" --- .github/workflows/claude-code-review.yml | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/workflows/claude-code-review.yml (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 000000000..b5e8cfd4d --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -0,0 +1,44 @@ +name: Claude Code Review + +on: + pull_request: + types: [opened, synchronize, ready_for_review, reopened] + # Optional: Only run on specific file changes + # paths: + # - "src/**/*.ts" + # - "src/**/*.tsx" + # - "src/**/*.js" + # - "src/**/*.jsx" + +jobs: + claude-review: + # Optional: Filter by PR author + # if: | + # github.event.pull_request.user.login == 'external-contributor' || + # github.event.pull_request.user.login == 'new-developer' || + # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' + + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code Review + id: claude-review + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' + plugins: 'code-review@claude-code-plugins' + prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' + # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md + # or https://code.claude.com/docs/en/cli-reference for available options + -- cgit v1.3.1 From f021d5c1e1de5c1b47fcbdd6d8fb1eea70eafe61 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 4 Mar 2026 18:13:51 +0700 Subject: fix trailing newline in workflow files to pass pre-commit Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/claude-code-review.yml | 1 - .github/workflows/claude.yml | 1 - CLAUDE.md | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) create mode 120000 CLAUDE.md (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index b5e8cfd4d..25f4ad18c 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -41,4 +41,3 @@ jobs: prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md # or https://code.claude.com/docs/en/cli-reference for available options - diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index d300267f1..9471a0591 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -47,4 +47,3 @@ jobs: # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md # or https://code.claude.com/docs/en/cli-reference for available options # claude_args: '--allowed-tools Bash(gh pr:*)' - diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 000000000..47dc3e3d8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file -- cgit v1.3.1 From ce8a77083dc00423b2c1a4c7657aa7290684dea6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 5 Mar 2026 20:59:26 +0700 Subject: ci: fix claude-code-review for fork PRs Switch pull_request to pull_request_target so secrets and OIDC tokens are available when reviewing PRs from forks. Also add pull-requests: write permission so the action can post review comments. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/claude-code-review.yml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 25f4ad18c..5ba2fe900 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -1,27 +1,15 @@ name: Claude Code Review on: - pull_request: + pull_request_target: types: [opened, synchronize, ready_for_review, reopened] - # Optional: Only run on specific file changes - # paths: - # - "src/**/*.ts" - # - "src/**/*.tsx" - # - "src/**/*.js" - # - "src/**/*.jsx" jobs: claude-review: - # Optional: Filter by PR author - # if: | - # github.event.pull_request.user.login == 'external-contributor' || - # github.event.pull_request.user.login == 'new-developer' || - # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' - runs-on: ubuntu-latest permissions: contents: read - pull-requests: read + pull-requests: write issues: read id-token: write -- cgit v1.3.1 From 97297fe08bf0357b447f9c735612ce5f03146a31 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 7 Mar 2026 11:12:48 +0700 Subject: update hil test: remove unused ctypes, add fallback for skip boards --- .github/workflows/build.yml | 9 ++++++++- .github/workflows/claude-code-review.yml | 1 + test/hil/hil_test.py | 5 +---- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9d8b90f5a..ab1d3611f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -291,7 +291,14 @@ jobs: - name: Test on actual hardware run: | - python3 test/hil/hil_test.py ${{ env.HIL_JSON }} $SKIP_BOARDS + python3 test/hil/hil_test.py ${{ env.HIL_JSON }} $SKIP_BOARDS || \ + (if [ -f "${{ env.HIL_JSON }}.skip" ]; then + SKIP_BOARDS=$(cat "${{ env.HIL_JSON }}.skip") + echo "Re-running with SKIP_BOARDS=$SKIP_BOARDS" + python3 test/hil/hil_test.py ${{ env.HIL_JSON }} $SKIP_BOARDS + else + exit 1 + fi) # --------------------------------------- # Hardware in the loop (HIL) diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 5ba2fe900..5d7efc115 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -6,6 +6,7 @@ on: jobs: claude-review: + if: false runs-on: ubuntu-latest permissions: contents: read diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index f0b24b3ff..7cffd2da8 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -47,7 +47,7 @@ from multiprocessing import Pool import fs import hashlib import ctypes -from pymtp import MTP, LIBMTP_MTPDevice, LIBMTP_RawDevice +from pymtp import MTP import string ENUM_TIMEOUT = 30 @@ -150,9 +150,6 @@ def read_disk_file(uid, lun, fname): def open_mtp_dev(uid): mtp = MTP() - # Set proper return type for LIBMTP_Open_Raw_Device (pymtp doesn't define it) - mtp.mtp.LIBMTP_Open_Raw_Device.restype = ctypes.POINTER(LIBMTP_MTPDevice) - mtp.mtp.LIBMTP_Open_Raw_Device.argtypes = [ctypes.POINTER(LIBMTP_RawDevice)] # MTP seems to take a while to enumerate timeout = 2 * ENUM_TIMEOUT while timeout > 0: -- cgit v1.3.1 From 2052111bac10fc3184b1dd9558fc1b9ab5c85ea4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Mar 2026 15:48:49 +0700 Subject: chore(workflows): update GitHub Actions dependencies and improve membrowse error handling update AGENTS.md with metrics compare --- .github/workflows/build_util.yml | 1 + .github/workflows/cifuzz.yml | 2 +- .github/workflows/claude-code-review.yml | 2 +- .github/workflows/claude.yml | 2 +- .github/workflows/membrowse-onboard.yml | 6 ++--- .github/workflows/metrics_comment.yml | 2 +- AGENTS.md | 45 ++++++++++++++++++++++++++++++++ 7 files changed, 53 insertions(+), 7 deletions(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/build_util.yml b/.github/workflows/build_util.yml index d03c9af81..c9b0d36d9 100644 --- a/.github/workflows/build_util.yml +++ b/.github/workflows/build_util.yml @@ -79,6 +79,7 @@ jobs: - name: Membrowse Upload if: inputs.toolchain != 'esp-idf' && inputs.upload-membrowse == true + continue-on-error: true env: MEMBROWSE_API_KEY: ${{ secrets.MEMBROWSE_API_KEY }} run: | diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index d7f1fc066..9b3756a72 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -29,7 +29,7 @@ jobs: fuzz-seconds: 400 - name: Upload Crash - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 5d7efc115..43144bb5e 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 1 diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 9471a0591..50f449949 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -26,7 +26,7 @@ jobs: actions: read # Required for Claude to read CI results on PRs steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 1 diff --git a/.github/workflows/membrowse-onboard.yml b/.github/workflows/membrowse-onboard.yml index aa7204ffa..4b9e54cff 100644 --- a/.github/workflows/membrowse-onboard.yml +++ b/.github/workflows/membrowse-onboard.yml @@ -17,7 +17,7 @@ jobs: toolchains: ${{ steps.load.outputs.toolchains }} steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Load target matrix id: load @@ -35,7 +35,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 submodules: recursive @@ -45,7 +45,7 @@ jobs: ${{ fromJson(needs.load-targets.outputs.toolchains)[matrix.toolchain].setup_cmd }} && python3 tools/get_deps.py ${{ matrix.get_deps || matrix.port }} - name: Setup ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@v1 with: key: ${{ matrix.port }}-${{ matrix.board }} diff --git a/.github/workflows/metrics_comment.yml b/.github/workflows/metrics_comment.yml index 7443f7367..5d250211f 100644 --- a/.github/workflows/metrics_comment.yml +++ b/.github/workflows/metrics_comment.yml @@ -17,7 +17,7 @@ jobs: pull-requests: write steps: - name: Download Artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: run-id: ${{ github.event.workflow_run.id }} github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/AGENTS.md b/AGENTS.md index bbbd7c36d..4e510b01e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -211,6 +211,51 @@ take 2-5 minutes. NEVER CANCEL. Set timeout to 20+ minutes. - Install requirements: `pip install -r docs/requirements.txt` - Build docs: `cd docs && sphinx-build -b html . _build` -- takes 2-3 seconds. NEVER CANCEL. Set timeout to 10+ minutes. +## Code Size Metrics + +Generate and compare code size metrics to evaluate the impact of changes. This is the most common workflow +when making code changes — use it to verify size impact before committing. + +**Quick single-board metrics (preferred for iterative development):** + +```bash +rm -rf cmake-build +python3 tools/build.py -b raspberry_pi_pico --target all --target tinyusb_metrics +python3 tools/metrics.py combine -j -m -f tinyusb/src cmake-build/cmake-build-*/metrics.json +``` + +This builds all examples for one board and produces `metrics.json` + `metrics.md`. Takes ~30 seconds. +NEVER CANCEL. Set timeout to 10+ minutes. + +**Comparing with master (before/after workflow):** + +1. On master: build and save baseline + ```bash + rm -rf cmake-build + python3 tools/build.py -b raspberry_pi_pico --target all --target tinyusb_metrics + python3 tools/metrics.py combine -j -m -f tinyusb/src cmake-build/cmake-build-*/metrics.json + mv metrics.json metrics_master.json + ``` +2. Switch to your branch: rebuild + ```bash + rm -rf cmake-build + python3 tools/build.py -b raspberry_pi_pico --target all --target tinyusb_metrics + python3 tools/metrics.py combine -j -m -f tinyusb/src cmake-build/cmake-build-*/metrics.json + ``` +3. Compare: `python3 tools/metrics.py compare -m -f tinyusb/src metrics_master.json metrics.json` + Produces `metrics_compare.md` showing size differences. + +**Full CI metrics (all arm-gcc families, for thorough validation):** + +```bash +rm -rf cmake-build +FAMILIES=$(python3 .github/workflows/ci_set_matrix.py | python3 -c "import sys,json; d=json.load(sys.stdin); print(' '.join(d.get('arm-gcc',[])))") +python3 tools/build.py --one-first --target all --target tinyusb_metrics $FAMILIES +python3 tools/metrics.py combine -j -m -f tinyusb/src cmake-build/cmake-build-*/metrics.json +``` + +Builds the first board of each family. Takes 2-4 minutes. NEVER CANCEL. Set timeout to 10+ minutes. + ## Code Quality and Validation - Format code: `clang-format -i path/to/file.c` (uses `.clang-format` config) -- cgit v1.3.1 From 87f9cc01cfd3134594d196210d28ee590c7a5fc3 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 1 Jun 2026 23:51:41 +0700 Subject: ci: re-enable Claude PR review and harden auth/permissions - claude-code-review.yml: re-enable (drop `if: false`); switch from pull_request_target to pull_request so fork PRs never receive the OAuth token (avoids prompt-injection token leak). Auto-review on open/synchronize/reopen/ready_for_review, skip drafts, sticky comment. - claude.yml: grant contents/pull-requests/issues write so @claude can reply and push fixes; @claude is the on-demand path for fork PRs. --- .github/workflows/claude-code-review.yml | 19 +++++++++++++++---- .github/workflows/claude.yml | 6 +++--- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 43144bb5e..2f055287c 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -1,18 +1,27 @@ name: Claude Code Review on: - pull_request_target: - types: [opened, synchronize, ready_for_review, reopened] + pull_request: + # opened/reopened/ready_for_review -> first auto review + # synchronize -> auto re-review on new pushes + # + # NOTE: pull_request (not _target) means fork PRs from non-write-access + # contributors get NO token, so they are not auto-reviewed -> use @claude + # on those. Same-repo branches (yours or write-access contributors) get + # full auto-review safely. + types: [opened, synchronize, reopened, ready_for_review] jobs: claude-review: - if: false + # Skip drafts; review real PRs only + if: github.event.pull_request.draft == false runs-on: ubuntu-latest permissions: contents: read pull-requests: write issues: read id-token: write + actions: read # Required for Claude to read CI results on PRs steps: - name: Checkout repository @@ -28,5 +37,7 @@ jobs: plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' plugins: 'code-review@claude-code-plugins' prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' + # Reuse one comment instead of posting a new one each push + use_sticky_comment: true + claude_args: '--max-turns 20' # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md - # or https://code.claude.com/docs/en/cli-reference for available options diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 50f449949..660edfb7b 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -19,9 +19,9 @@ jobs: (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) runs-on: ubuntu-latest permissions: - contents: read - pull-requests: read - issues: read + contents: write # allow Claude to push commits/branches when asked + pull-requests: write # allow Claude to comment on / update PRs + issues: write # allow Claude to comment on / update issues id-token: write actions: read # Required for Claude to read CI results on PRs steps: -- cgit v1.3.1 From 1ea04f7fe67bac927848e9dfd3ce2f607e7b93d7 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Jun 2026 00:16:54 +0700 Subject: ci: address codex/copilot review on claude workflows - claude.yml: gate @claude on author_association (OWNER/MEMBER/COLLABORATOR) so the write-scoped token and OAuth secret are never issued for an untrusted commenter on this public repo (defense-in-depth). - claude-code-review.yml: skip fork PRs in the job condition (head.repo.full_name == github.repository) since forks get no secrets and would only fail noisily; fix the misleading token comment; pass additional_permissions: actions: read so actions: read is effective. - hil SKILL.md: reword hostname guidance, use full test/hil/* paths, and show an explicit CONFIG= assignment so the local command is runnable. Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/skills/hil/SKILL.md | 14 ++++++++------ .github/workflows/claude-code-review.yml | 17 +++++++++++------ .github/workflows/claude.yml | 15 +++++++++++---- 3 files changed, 30 insertions(+), 16 deletions(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.claude/skills/hil/SKILL.md b/.claude/skills/hil/SKILL.md index c705c149c..22588eba3 100644 --- a/.claude/skills/hil/SKILL.md +++ b/.claude/skills/hil/SKILL.md @@ -5,12 +5,12 @@ description: Use when running TinyUSB Hardware-in-the-Loop (HIL) tests on physic # Hardware-in-the-Loop (HIL) Testing -Run TinyUSB HIL tests on real boards. **Run `hostname` first** — it sets the default config and whether remote mode is possible. +Run TinyUSB HIL tests on real boards. **Run `hostname` first** — it tells you which host you are on, which determines the default config and whether remote mode is possible. -| Host | Local boards | Remote (SSH → ci.lan)? | +| Host | Local config | Remote (SSH → ci.lan)? | |------|--------------|------------------------| -| `htpc` (dev PC) | `local.json` | yes (large pool, `tinyusb.json`) | -| `ci` (the rig) | `tinyusb.json` (large pool) | no — can't SSH to htpc, and boards are already local | +| `htpc` (dev PC) | `test/hil/local.json` | yes (large pool, `test/hil/tinyusb.json`) | +| `ci` (the rig) | `test/hil/tinyusb.json` (large pool) | no — can't SSH to htpc, and boards are already local | Default to **local**. Use **remote** only when on `htpc` and the user says `remote`/`ci.lan`. Never attempt remote on `ci`. @@ -27,10 +27,12 @@ If `local.json` is missing on `htpc`, ask the user to supply one (only fall back ## Local execution -Pick `$CONFIG` from `hostname`: `local.json` on `htpc`, `tinyusb.json` on `ci`. +Set `CONFIG` from `hostname` first, then run: ```bash -python3 test/hil/hil_test.py [-b BOARD_NAME] -B examples $CONFIG $EXTRA_ARGS +CONFIG=test/hil/local.json # on htpc +# CONFIG=test/hil/tinyusb.json # on ci +python3 test/hil/hil_test.py [-b BOARD_NAME] -B examples "$CONFIG" $EXTRA_ARGS ``` ## Remote execution (htpc → ci.lan only) diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 2f055287c..6c8bbb03d 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -5,16 +5,18 @@ on: # opened/reopened/ready_for_review -> first auto review # synchronize -> auto re-review on new pushes # - # NOTE: pull_request (not _target) means fork PRs from non-write-access - # contributors get NO token, so they are not auto-reviewed -> use @claude - # on those. Same-repo branches (yours or write-access contributors) get - # full auto-review safely. + # NOTE: pull_request (not _target) means fork PRs get a read-only GITHUB_TOKEN + # and NO repository secrets (CLAUDE_CODE_OAUTH_TOKEN), so they cannot be + # auto-reviewed. The job condition below skips them cleanly -> use @claude on + # those. Same-repo branches (yours or write-access contributors) auto-review. types: [opened, synchronize, reopened, ready_for_review] jobs: claude-review: - # Skip drafts; review real PRs only - if: github.event.pull_request.draft == false + # Skip drafts, and skip fork PRs (no secrets -> would only fail noisily) + if: > + github.event.pull_request.draft == false && + github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest permissions: contents: read @@ -34,6 +36,9 @@ jobs: uses: anthropics/claude-code-action@v1 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + # Pairs with the actions: read permission so Claude can read CI results + additional_permissions: | + actions: read plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' plugins: 'code-review@claude-code-plugins' prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 660edfb7b..dedecd349 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -12,11 +12,18 @@ on: jobs: claude: + # Only trusted actors (repo owner/member/collaborator) may summon @claude, so the + # write-scoped token and OAuth secret are never issued for an outside contributor's + # comment on this public repo. Defense-in-depth on top of the action's own check. if: | - (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || - (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude') && + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') && + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.review.author_association)) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')) && + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.issue.author_association)) runs-on: ubuntu-latest permissions: contents: write # allow Claude to push commits/branches when asked -- cgit v1.3.1 From 044cd06f87117afa541d8cc743fcc9ef2bdc8089 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Jun 2026 00:24:05 +0700 Subject: ci: address second codex/copilot review round - claude.yml: drop the issues "assigned" trigger; its author_association gate keys on the issue author, not the assigner, so a maintainer assigning an outside contributor's issue would be wrongly skipped. - claude-code-review.yml: issues: read -> write so use_sticky_comment can create/update its PR comment via the issues API. - hil SKILL.md: make local/remote command blocks copy-pasteable (drop [-b BOARD_NAME] notation for concrete examples) and fix timeout (600000 ms is 10 min; use 1200000 ms for the stated 20 min). Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/skills/hil/SKILL.md | 22 ++++++++++++++++------ .github/workflows/claude-code-review.yml | 2 +- .github/workflows/claude.yml | 5 ++++- 3 files changed, 21 insertions(+), 8 deletions(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.claude/skills/hil/SKILL.md b/.claude/skills/hil/SKILL.md index 22588eba3..a7a916907 100644 --- a/.claude/skills/hil/SKILL.md +++ b/.claude/skills/hil/SKILL.md @@ -27,27 +27,37 @@ If `local.json` is missing on `htpc`, ask the user to supply one (only fall back ## Local execution -Set `CONFIG` from `hostname` first, then run: +Set `CONFIG` from `hostname` first (`test/hil/local.json` on htpc, `test/hil/tinyusb.json` on ci): ```bash -CONFIG=test/hil/local.json # on htpc -# CONFIG=test/hil/tinyusb.json # on ci -python3 test/hil/hil_test.py [-b BOARD_NAME] -B examples "$CONFIG" $EXTRA_ARGS +CONFIG=test/hil/local.json # on ci use: CONFIG=test/hil/tinyusb.json + +# All boards in the config: +python3 test/hil/hil_test.py -B examples "$CONFIG" + +# A single board (replace stm32f723disco): +python3 test/hil/hil_test.py -b stm32f723disco -B examples "$CONFIG" ``` +Append pass-through flags (`-v`, `-r 1`, …) to either command as needed. + ## Remote execution (htpc → ci.lan only) `test/hil/hil_ci.sh` handles dir setup, scp of test scripts, rsync of firmware (`.elf`/`.bin`/`.hex`), and runs `hil_test.py` on `ci.lan` with `tinyusb.json`: ```bash -bash test/hil/hil_ci.sh [-b BOARD_NAME] [extra hil_test.py args...] +# All boards: +bash test/hil/hil_ci.sh + +# A single board, with pass-through flags: +bash test/hil/hil_ci.sh -b raspberry_pi_pico2 -t host/cdc_msc_hid -r 1 ``` Env overrides: `REMOTE`, `REMOTE_DIR`, `CONFIG`. Fails fast if the build dir/repo layout is missing. ## Timing -Runs take 2-5 min. Use a timeout ≥ 20 min (600000 ms). NEVER cancel early. +Runs take 2-5 min. Use a timeout ≥ 20 min (1200000 ms). NEVER cancel early. ## Reporting diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 6c8bbb03d..4a0e4639b 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -21,7 +21,7 @@ jobs: permissions: contents: read pull-requests: write - issues: read + issues: write # use_sticky_comment posts/updates a PR comment via the issues API id-token: write actions: read # Required for Claude to read CI results on PRs diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index dedecd349..bf7a401e4 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -6,7 +6,10 @@ on: pull_request_review_comment: types: [created] issues: - types: [opened, assigned] + # only "opened" — an issue's author_association gates the summon below; + # "assigned" would gate on the issue author, not the assigner, so a + # maintainer assigning an outsider's issue would be wrongly skipped. + types: [opened] pull_request_review: types: [submitted] -- cgit v1.3.1 From d585977d9275d70a75003529136dec2f3de9a875 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Jun 2026 09:05:46 +0700 Subject: ci: allow claude[bot] pushes in code review workflow Add allowed_bots: 'claude' so that when claude[bot] pushes commits the workflow skips gracefully instead of erroring. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/claude-code-review.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 4a0e4639b..97950e888 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -21,7 +21,7 @@ jobs: permissions: contents: read pull-requests: write - issues: write # use_sticky_comment posts/updates a PR comment via the issues API + issues: write # Claude posts the review comment via the issues API id-token: write actions: read # Required for Claude to read CI results on PRs @@ -36,13 +36,17 @@ jobs: uses: anthropics/claude-code-action@v1 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + # Allow claude[bot]'s own pushes to be handled gracefully (skip) instead + # of erroring out the workflow + allowed_bots: 'claude' # Pairs with the actions: read permission so Claude can read CI results additional_permissions: | actions: read plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' plugins: 'code-review@claude-code-plugins' prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' - # Reuse one comment instead of posting a new one each push - use_sticky_comment: true + # TEMPORARY: expose the full Claude transcript in the Actions log for + # debugging. Revert to remove once done. + show_full_output: true claude_args: '--max-turns 20' # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md -- cgit v1.3.1 From 9a3e32bf549c5fdf6ef7931a47b8b8e2e483d856 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Jun 2026 15:15:07 +0700 Subject: ci(claude): post sticky summary comment on code review The review workflow posted nothing when a review found no issues: with use_sticky_comment unset, the only output path was inline comments, so a clean review surfaced no comment at all on the PR. Enable use_sticky_comment so a single summary comment is posted/ updated every run, making "no issues found" results visible. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/claude-code-review.yml | 3 +++ 1 file changed, 3 insertions(+) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 97950e888..91859af9d 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -44,6 +44,9 @@ jobs: actions: read plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' plugins: 'code-review@claude-code-plugins' + # Post/update a single summary comment every run, so a clean review + # ("no issues found") is still visible instead of posting nothing. + use_sticky_comment: true prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' # TEMPORARY: expose the full Claude transcript in the Actions log for # debugging. Revert to remove once done. -- cgit v1.3.1 From 7c68545ab6bd0a2b7d4b59228d84d4c2085abae7 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Mon, 8 Jun 2026 09:42:08 +0700 Subject: ci: post auto-review findings to the PR (#3684) Add --comment so the auto-review is actually posted on the PR. --- .github/workflows/claude-code-review.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 91859af9d..71c1cb8ab 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -47,7 +47,9 @@ jobs: # Post/update a single summary comment every run, so a clean review # ("no issues found") is still visible instead of posting nothing. use_sticky_comment: true - prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' + # --comment makes the code-review command post its findings to the PR. + # Without it the command only prints the review to the Actions log. + prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }} --comment' # TEMPORARY: expose the full Claude transcript in the Actions log for # debugging. Revert to remove once done. show_full_output: true -- cgit v1.3.1 From c9cfd829f6a793b227f4e52df29337f2a8530ce7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Jun 2026 19:41:51 +0700 Subject: ci(claude-review): raise --max-turns 20 -> 50 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Claude Code Review action runs /code-review:code-review with a hard --max-turns cap. On large PRs (e.g. #3636 "add stm32c5 support", 29 files / +1689), the agent exhausts 20 turns exploring the diff before it can produce and post its review, so the SDK returns an error and the claude-review check fails red with: Reached maximum number of turns (20) Raise the cap to 50 so port-sized PRs complete and post their review. Cost scales with tokens, not the cap: a finished review pays the same whether the ceiling is 25 or 50 — the cap only bites when the agent would otherwise be force-stopped mid-run. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/claude-code-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 71c1cb8ab..94001dd8a 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -53,5 +53,5 @@ jobs: # TEMPORARY: expose the full Claude transcript in the Actions log for # debugging. Revert to remove once done. show_full_output: true - claude_args: '--max-turns 20' + claude_args: '--max-turns 50' # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md -- cgit v1.3.1 From b643e8108570b3a8d10dc446ca36954b90ac497a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Jun 2026 21:13:32 +0700 Subject: ci(claude-review): run auto review on Opus (claude-opus-4-8) The review action currently runs on the default Sonnet 4.6. On PR #3643 (musb EP0 race) it posted "No issues found" while an Opus pass on the same diff surfaced substantive questions (ISR-boundary RXRDY lifetime, regression scope of the DATA-state split). Pin the reviewer to claude-opus-4-8 for higher-signal reviews; subagents keep their cheaper default models. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/claude-code-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 94001dd8a..60cc4db4b 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -53,5 +53,5 @@ jobs: # TEMPORARY: expose the full Claude transcript in the Actions log for # debugging. Revert to remove once done. show_full_output: true - claude_args: '--max-turns 50' + claude_args: '--max-turns 50 --model claude-opus-4-8' # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md -- cgit v1.3.1 From e7b373ede2dc1ab7322d9687bc5ca87dd156e355 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 18 Jun 2026 19:37:12 +0700 Subject: ci(review): run Claude PR review at max effort Pass --effort max to the claude CLI in the auto-review workflow so PR reviews run at maximum reasoning effort. Switch claude_args to a multi-line block scalar for readability, keeping --max-turns 50 and --model claude-opus-4-8 unchanged. Co-Authored-By: Claude Fable 5 --- .github/workflows/claude-code-review.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to '.github/workflows/claude-code-review.yml') diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 60cc4db4b..59019616f 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -53,5 +53,8 @@ jobs: # TEMPORARY: expose the full Claude transcript in the Actions log for # debugging. Revert to remove once done. show_full_output: true - claude_args: '--max-turns 50 --model claude-opus-4-8' + claude_args: | + --max-turns 50 + --model claude-opus-4-8 + --effort max # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md -- cgit v1.3.1