diff options
| author | hathach <[email protected]> | 2026-03-05 13:00:45 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-03-05 13:00:45 +0700 |
| commit | 0427fcfd02e6d6b8939b54984f58c3711d806ddd (patch) | |
| tree | 5d86bb047dc306cf383fc7258074294d343c6ae2 /.github/workflows | |
| parent | 6e675da608b063e2ea7db1d700d788d6a247f9ec (diff) | |
| parent | ce8a073a31307d65e3337a2f69a5ea1b9b507ea5 (diff) | |
Merge branch 'master' into fork/armusin/threadx_osal
Diffstat (limited to '.github/workflows')
| -rw-r--r-- | .github/workflows/build.yml | 121 | ||||
| -rw-r--r-- | .github/workflows/build_util.yml | 58 | ||||
| -rwxr-xr-x | .github/workflows/ci_set_matrix.py | 72 | ||||
| -rw-r--r-- | .github/workflows/claude-code-review.yml | 43 | ||||
| -rw-r--r-- | .github/workflows/claude.yml | 49 | ||||
| -rw-r--r-- | .github/workflows/membrowse-report.yml | 101 |
6 files changed, 231 insertions, 213 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ded4e816c..9d8b90f5a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,30 +4,7 @@ on: workflow_dispatch: push: branches: [master] - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'tools/build.py' - - 'tools/get_deps.py' - - '.github/actions/**' - - '.github/workflows/build.yml' - - '.github/workflows/build_util.yml' - - '.github/workflows/ci_set_matrix.py' pull_request: - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'test/hil/**' - - 'tools/build.py' - - 'tools/get_deps.py' - - '.github/actions/**' - - '.github/workflows/build.yml' - - '.github/workflows/build_util.yml' - - '.github/workflows/ci_set_matrix.py' release: types: [ published ] @@ -39,6 +16,36 @@ env: HIL_JSON: test/hil/tinyusb.json jobs: + # Check if the code changes and we need to run ci build + # Cannot use paths filter in the on-event since we want this workflow to run even when there are no code changes, to register the commit chain + check-paths: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + outputs: + code_changed: ${{ steps.filter.outputs.code }} + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 2 # Needed for push commit comparison + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + code: + - 'src/**' + - 'examples/**' + - 'lib/**' + - 'hw/**' + - 'test/hil/**' + - 'tools/build.py' + - 'tools/get_deps.py' + - '.github/actions/**' + - '.github/workflows/build.yml' + - '.github/workflows/build_util.yml' + - '.github/workflows/ci_set_matrix.py' + set-matrix: runs-on: ubuntu-latest outputs: @@ -66,7 +73,7 @@ jobs: # For Make and IAR build: will be done on CircleCI only (one random per family as well) # ------------------------------------------------------------------------------ cmake: - needs: set-matrix + needs: [ check-paths, set-matrix ] uses: ./.github/workflows/build_util.yml strategy: fail-fast: false @@ -84,10 +91,14 @@ jobs: build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }} build-options: '--one-first' upload-metrics: true - upload-artifacts: true + upload-artifacts: false + upload-membrowse: true + code-changed: ${{ needs.check-paths.outputs.code_changed == 'true' }} + secrets: inherit code-metrics: - needs: cmake + needs: [ check-paths, cmake ] + if: needs.check-paths.outputs.code_changed == 'true' runs-on: ubuntu-latest permissions: pull-requests: write @@ -184,24 +195,29 @@ jobs: # Build Make/CMake on Windows/MacOS # --------------------------------------- build-os: + needs: [ check-paths ] + if: needs.check-paths.outputs.code_changed == 'true' uses: ./.github/workflows/build_util.yml strategy: fail-fast: false matrix: os: [ windows-latest, macos-latest ] + build-system: [ 'make', 'cmake' ] with: os: ${{ matrix.os }} - build-system: 'cmake-make' + build-system: ${{ matrix.build-system }} toolchain: 'arm-gcc-${{ matrix.os }}' - build-args: '["stm32h7"]' + build-args: '["stm32h7rs"]' build-options: '--one-random' # --------------------------------------- # Zephyr # --------------------------------------- zephyr: + needs: [ check-paths ] # skip zephyr build due to failed build, fix later if: false + #if: needs.check-paths.outputs.code_changed == 'true' runs-on: ubuntu-latest steps: - name: Checkout TinyUSB @@ -223,8 +239,8 @@ jobs: # Run on PR only (hil-tinyusb), hil-hfp only run on non-forked PR # --------------------------------------- hil-build: - needs: set-matrix - if: github.repository_owner == 'hathach' + needs: [ check-paths, set-matrix ] + if: needs.check-paths.outputs.code_changed == 'true' && github.repository_owner == 'hathach' uses: ./.github/workflows/build_util.yml strategy: fail-fast: false @@ -283,7 +299,9 @@ jobs: # Since IAR Token secret is not passed to forked PR, only build non-forked PR # --------------------------------------- hil-hfp: + needs: [ check-paths ] if: | + needs.check-paths.outputs.code_changed == 'true' && github.repository_owner == 'hathach' && !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true) runs-on: [ self-hosted, Linux, X64, hifiphile ] @@ -318,46 +336,3 @@ jobs: - name: Test on actual hardware (hardware in the loop) run: python3 test/hil/hil_test.py hfp.json - - # --------------------------------------- - # Membrowse Memory Analysis - # Push: always runs (uses identical for doc-only to maintain commit chain) - # PR: only runs if code changed (doc-only PRs skip entirely) - # --------------------------------------- - membrowse: - needs: cmake - permissions: - contents: read - actions: read - uses: ./.github/workflows/membrowse-report.yml - with: - code_changed: true - secrets: inherit - - membrowse-comment: - needs: membrowse - # skip membrowse comment since it is too verbal - if: false && github.event_name == 'pull_request' - runs-on: ubuntu-latest - permissions: - contents: read - actions: read - steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Download report artifacts - id: download - uses: actions/download-artifact@v5 - with: - pattern: membrowse-report-* - path: reports - merge-multiple: true - continue-on-error: true - - - name: Upload Membrowse Comment Artifact - if: steps.download.outcome == 'success' - uses: actions/upload-artifact@v5 - with: - name: membrowse-comment - path: reports/ diff --git a/.github/workflows/build_util.yml b/.github/workflows/build_util.yml index e62c10ca1..d03c9af81 100644 --- a/.github/workflows/build_util.yml +++ b/.github/workflows/build_util.yml @@ -3,6 +3,10 @@ name: Reusable build util on: workflow_call: inputs: + os: + required: false + type: string + default: 'ubuntu-latest' build-system: required: true type: string @@ -24,10 +28,14 @@ on: required: false default: false type: boolean - os: + upload-membrowse: required: false - type: string - default: 'ubuntu-latest' + default: false + type: boolean + code-changed: + required: false + default: true + type: boolean jobs: family: @@ -39,6 +47,8 @@ jobs: steps: - name: Checkout TinyUSB uses: actions/checkout@v6 + with: + fetch-depth: ${{ !inputs.upload-membrowse && 1 || 0 }} - name: Setup Toolchain id: setup-toolchain @@ -52,42 +62,40 @@ jobs: arg: ${{ matrix.arg }} - name: Build + if: ${{ inputs.code-changed }} env: IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} - TOOLCHAIN: ${{ inputs.toolchain }} run: | - if [ "$TOOLCHAIN" == "esp-idf" ]; then - docker run --rm -v $PWD:/project -w /project espressif/idf:tinyusb python tools/build.py ${{ matrix.arg }} - elif [ "${{ inputs.build-system }}" == "cmake-make" ] || [ "${{ inputs.build-system }}" == "make-cmake" ]; then - python tools/build.py -s make ${{ steps.setup-toolchain.outputs.build_option }} ${{ inputs.build-options }} ${{ matrix.arg }} - python tools/build.py -s cmake ${{ steps.setup-toolchain.outputs.build_option }} ${{ inputs.build-options }} ${{ matrix.arg }} + if [ "${{ inputs.toolchain }}" == "esp-idf" ]; then + docker run --rm -e MEMBROWSE_API_KEY="$MEMBROWSE_API_KEY" -v $PWD:/project -w /project espressif/idf:tinyusb python tools/build.py --target all ${{ matrix.arg }} else - python tools/build.py -s ${{ inputs.build-system }} ${{ steps.setup-toolchain.outputs.build_option }} ${{ inputs.build-options }} ${{ matrix.arg }} + BUILD_PY_ARGS="-s ${{ inputs.build-system }} ${{ steps.setup-toolchain.outputs.build_option }} ${{ inputs.build-options }} --target all" + if [ "${{ inputs.upload-metrics }}" = "true" ]; then + BUILD_PY_ARGS="$BUILD_PY_ARGS --target tinyusb_metrics" + fi + python tools/build.py $BUILD_PY_ARGS ${{ matrix.arg }} fi shell: bash + - name: Membrowse Upload + if: inputs.toolchain != 'esp-idf' && inputs.upload-membrowse == true + env: + MEMBROWSE_API_KEY: ${{ secrets.MEMBROWSE_API_KEY }} + run: | + # if code-changed is false --> there is no elf -> membrowse target upload with --identical flag + BUILD_PY_ARGS="-s ${{ inputs.build-system }} ${{ steps.setup-toolchain.outputs.build_option }} ${{ inputs.build-options }}" + python tools/build.py $BUILD_PY_ARGS --target examples-membrowse-upload -j 1 ${{ matrix.arg }} + shell: bash + - name: Upload Artifacts for Metrics - if: ${{ inputs.upload-metrics }} + if: inputs.upload-metrics == true && inputs.code-changed == true uses: actions/upload-artifact@v5 with: name: metrics-${{ matrix.arg }} path: cmake-build/cmake-build-*/metrics.json - - name: Copy linker scripts for artifacts - if: ${{ inputs.upload-artifacts }} - run: | - for dir in cmake-build/cmake-build-*; do - board=$(basename "$dir" | sed 's/cmake-build-//') - ld_path=$(jq -r --arg b "$board" '.targets[] | select(.board == $b) | .ld // empty' .github/membrowse-targets.json) - if [ -n "$ld_path" ] && [ -f "$ld_path" ]; then - mkdir -p "cmake-build/$(dirname "$ld_path")" - cp "$ld_path" "cmake-build/$ld_path" - fi - done - shell: bash - - name: Upload Artifacts for Hardware Testing - if: ${{ inputs.upload-artifacts }} + if: inputs.upload-artifacts == true && inputs.code-changed == true uses: actions/upload-artifact@v5 with: name: binaries-${{ matrix.arg }} diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index 9ab08601d..cd7dfa76b 100755 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -15,32 +15,76 @@ toolchain_list = [ # family: [supported toolchain] family_list = { - "at32f45x at32f402_405 at32f403a_407 at32f413 at32f415 at32f423 at32f425 at32f435_437 broadcom_32bit da1469x": [ - "arm-gcc"], + "at32f402_405": ["arm-gcc"], + "at32f403a_407": ["arm-gcc"], + "at32f413": ["arm-gcc"], + "at32f415": ["arm-gcc"], + "at32f423": ["arm-gcc"], + "at32f425": ["arm-gcc"], + "at32f435_437": ["arm-gcc"], + "at32f45x": ["arm-gcc"], + "broadcom_32bit": ["arm-gcc"], "broadcom_64bit": ["aarch64-gcc"], - "ch32v10x ch32v20x ch32v30x fomu gd32vf103 hpmicro": ["riscv-gcc"], + "ch32v10x": ["riscv-gcc"], + "ch32v20x": ["riscv-gcc"], + "ch32v30x": ["riscv-gcc"], + "da1469x": ["arm-gcc"], + "fomu": ["riscv-gcc"], + "gd32vf103": ["riscv-gcc"], + "hpmicro": ["riscv-gcc"], "imxrt": ["arm-gcc", "arm-clang"], - "kinetis_k kinetis_kl kinetis_k32l2": ["arm-gcc", "arm-clang"], - "lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43": ["arm-gcc", "arm-clang"], - "lpc51 lpc54 lpc55": ["arm-gcc", "arm-clang"], - "maxim mcx mm32 msp432e4 rw61x tm4c": ["arm-gcc"], + "kinetis_k": ["arm-gcc", "arm-clang"], + "kinetis_k32l2": ["arm-gcc", "arm-clang"], + "kinetis_kl": ["arm-gcc", "arm-clang"], + "lpc11": ["arm-gcc", "arm-clang"], + "lpc13": ["arm-gcc", "arm-clang"], + "lpc15": ["arm-gcc", "arm-clang"], + "lpc17": ["arm-gcc", "arm-clang"], + "lpc18": ["arm-gcc", "arm-clang"], + "lpc40": ["arm-gcc", "arm-clang"], + "lpc43": ["arm-gcc", "arm-clang"], + "lpc51": ["arm-gcc", "arm-clang"], + "lpc54": ["arm-gcc", "arm-clang"], + "lpc55": ["arm-gcc", "arm-clang"], + "maxim": ["arm-gcc"], + "mcx": ["arm-gcc"], + "mm32": ["arm-gcc"], "msp430": ["msp430-gcc"], + "msp432e4": ["arm-gcc"], "nrf": ["arm-gcc", "arm-clang"], - "nuc100_120 nuc121_125 nuc126 nuc505 xmc4000": ["arm-gcc"], + "nuc100_120": ["arm-gcc"], + "nuc121_125": ["arm-gcc"], + "nuc126": ["arm-gcc"], + "nuc505": ["arm-gcc"], "ra": ["arm-gcc"], "rp2040": ["arm-gcc"], + "rw61x": ["arm-gcc"], "rx": ["rx-gcc"], - "samd11 samd2x_l2x samd5x_e5x samg": ["arm-gcc", "arm-clang"], - "stm32c0 stm32f0 stm32f1 stm32f2 stm32f3": ["arm-gcc", "arm-clang", "arm-iar"], + "samd11": ["arm-gcc", "arm-clang"], + "samd2x_l2x": ["arm-gcc", "arm-clang"], + "samd5x_e5x": ["arm-gcc", "arm-clang"], + "samg": ["arm-gcc", "arm-clang"], + "stm32c0": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32f0": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32f1": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32f2": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32f3": ["arm-gcc", "arm-clang", "arm-iar"], "stm32f4": ["arm-gcc", "arm-clang", "arm-iar"], "stm32f7": ["arm-gcc", "arm-clang", "arm-iar"], - "stm32g0 stm32g4 stm32h5": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32g0": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32g4": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32h5": ["arm-gcc", "arm-clang", "arm-iar"], "stm32h7": ["arm-gcc", "arm-clang", "arm-iar"], - "stm32h7rs stm32l0 stm32l4": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32h7rs": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32l0": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32l4": ["arm-gcc", "arm-clang", "arm-iar"], "stm32n6": ["arm-gcc"], - "stm32u0 stm32wb stm32wba": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32u0": ["arm-gcc", "arm-clang", "arm-iar"], "stm32u5": ["arm-gcc", "arm-clang", "arm-iar"], - "-bespressif_s2_devkitc": ["esp-idf"], + "stm32wb": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32wba": ["arm-gcc", "arm-clang", "arm-iar"], + "tm4c": ["arm-gcc"], + "xmc4000": ["arm-gcc"], # S3, P4 will be built by hil test # "-bespressif_s3_devkitm": ["esp-idf"], # "-bespressif_p4_function_ev": ["esp-idf"], diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 000000000..25f4ad18c --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -0,0 +1,43 @@ +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 diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml new file mode 100644 index 000000000..9471a0591 --- /dev/null +++ b/.github/workflows/claude.yml @@ -0,0 +1,49 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + 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'))) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + actions: read # Required for Claude to read CI results on PRs + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + + # This is an optional setting that allows Claude to read CI results on PRs + additional_permissions: | + actions: read + + # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it. + # prompt: 'Update the pull request description to include a summary of changes.' + + # Optional: Add claude_args to customize behavior and configuration + # 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/.github/workflows/membrowse-report.yml b/.github/workflows/membrowse-report.yml deleted file mode 100644 index 0667418e6..000000000 --- a/.github/workflows/membrowse-report.yml +++ /dev/null @@ -1,101 +0,0 @@ -name: Membrowse Memory Report - -on: - workflow_call: - inputs: - code_changed: - description: 'Whether code paths changed (true) or doc-only (false)' - type: boolean - required: true - -permissions: - contents: read - actions: read - -jobs: - load-targets: - runs-on: ubuntu-latest - outputs: - targets: ${{ steps.load.outputs.targets }} - steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Load target matrix - id: load - run: echo "targets=$(jq -c '.targets' .github/membrowse-targets.json)" >> $GITHUB_OUTPUT - - analyze: - needs: [load-targets] - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: ${{ fromJson(needs.load-targets.outputs.targets) }} - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 0 - submodules: recursive - - # Download artifacts when code changed (build artifacts available) - - name: Download build artifacts - if: inputs.code_changed - id: download - uses: actions/download-artifact@v5 - with: - pattern: binaries-* - path: cmake-build - merge-multiple: true - continue-on-error: true - - - name: Restore linker scripts - if: inputs.code_changed - run: cp -r cmake-build/hw . 2>/dev/null || true - - - name: Check if ELF exists - id: check-elf - run: | - if [ -f "cmake-build/cmake-build-${{ matrix.board }}/device/${{ matrix.example }}/${{ matrix.example }}.elf" ]; then - echo "exists=true" >> $GITHUB_OUTPUT - else - echo "exists=false" >> $GITHUB_OUTPUT - fi - - # Run with actual ELF analysis when build artifacts available - - name: Run Membrowse Analysis - if: steps.check-elf.outputs.exists == 'true' - id: membrowse - continue-on-error: true - uses: membrowse/membrowse-action@v1 - with: - target_name: ${{ matrix.port }}-${{ matrix.board }}-${{ matrix.example }} - elf: cmake-build/cmake-build-${{ matrix.board }}/device/${{ matrix.example }}/${{ matrix.example }}.elf - ld: ${{ matrix.ld }} - linker_vars: ${{ matrix.linker_vars || '' }} - api_key: ${{ secrets.MEMBROWSE_API_KEY }} - api_url: ${{ vars.MEMBROWSE_API_URL }} - verbose: INFO - - # Run with identical=true when no ELF (doc-only push) - # Preserves the chain of commits in membrowse tracking - - name: Run Membrowse Identical Report - if: steps.check-elf.outputs.exists == 'false' - id: membrowse-identical - continue-on-error: true - uses: membrowse/membrowse-action@v1 - with: - target_name: ${{ matrix.port }}-${{ matrix.board }}-${{ matrix.example }} - identical: true - api_key: ${{ secrets.MEMBROWSE_API_KEY }} - api_url: ${{ vars.MEMBROWSE_API_URL }} - verbose: INFO - - - name: Upload report artifact - if: steps.membrowse.outcome == 'success' || steps.membrowse-identical.outcome == 'success' - uses: actions/upload-artifact@v5 - with: - name: membrowse-report-${{ matrix.port }}-${{ matrix.board }}-${{ matrix.example }} - path: ${{ steps.membrowse.outputs.report_path || steps.membrowse-identical.outputs.report_path }} |
