| name: Build |
| |
| on: |
| workflow_dispatch: |
| push: |
| branches: [master] |
| pull_request: |
| release: |
| types: [ published ] |
| |
| concurrency: |
| group: ${{ github.workflow }}-${{ github.ref }} |
| cancel-in-progress: true |
| |
| 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: |
| json: ${{ steps.set-matrix-json.outputs.matrix }} |
| hil_json: ${{ steps.set-matrix-json.outputs.hil_matrix }} |
| steps: |
| - name: Checkout TinyUSB |
| uses: actions/checkout@v6 |
| |
| - name: Generate matrix json |
| id: set-matrix-json |
| run: | |
| # build matrix |
| MATRIX_JSON=$(python .github/workflows/ci_set_matrix.py)/ |
| echo "matrix=$MATRIX_JSON" |
| echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT |
| # hil matrix |
| HIL_MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py ${{ env.HIL_JSON }}) |
| echo "hil_matrix=$HIL_MATRIX_JSON" |
| echo "hil_matrix=$HIL_MATRIX_JSON" >> $GITHUB_OUTPUT |
| |
| # ------------------------------------------------------------------------------ |
| # CMake build: only one board per family (first alphabetically). Full build is done by CircleCI in PR |
| # Note: |
| # For Make and IAR build: will be done on CircleCI only (one random per family as well) |
| # ------------------------------------------------------------------------------ |
| cmake: |
| needs: [ check-paths, set-matrix ] |
| uses: ./.github/workflows/build_util.yml |
| strategy: |
| fail-fast: false |
| matrix: |
| toolchain: |
| - 'aarch64-gcc' |
| #- 'arm-clang' |
| - 'arm-gcc' |
| #- 'esp-idf' |
| - 'msp430-gcc' |
| - 'riscv-gcc' |
| with: |
| build-system: 'cmake' |
| toolchain: ${{ matrix.toolchain }} |
| build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }} |
| build-options: '--one-first' |
| upload-metrics: true |
| upload-artifacts: false |
| upload-membrowse: true |
| code-changed: ${{ needs.check-paths.outputs.code_changed == 'true' }} |
| secrets: inherit |
| |
| code-metrics: |
| needs: [ check-paths, cmake ] |
| if: needs.check-paths.outputs.code_changed == 'true' |
| runs-on: ubuntu-latest |
| permissions: |
| pull-requests: write |
| contents: write |
| steps: |
| - name: Checkout TinyUSB |
| uses: actions/checkout@v6 |
| with: |
| fetch-tags: ${{ github.event_name == 'release' }} |
| |
| - name: Download Artifacts |
| uses: actions/download-artifact@v5 |
| with: |
| pattern: metrics-* |
| path: cmake-build |
| merge-multiple: true |
| |
| - name: Aggregate Code Metrics |
| run: | |
| python tools/get_deps.py |
| python tools/metrics.py combine -j -m -f tinyusb/src cmake-build/*/metrics.json |
| |
| - name: Upload Metrics Artifact |
| if: github.event_name == 'push' || github.event_name == 'release' |
| uses: actions/upload-artifact@v5 |
| with: |
| name: metrics-tinyusb |
| path: metrics.json |
| |
| - name: Download Base Branch Metrics |
| if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' |
| uses: dawidd6/action-download-artifact@v11 |
| with: |
| workflow: build.yml |
| branch: ${{ github.base_ref }} |
| name: metrics-tinyusb |
| path: base-metrics |
| continue-on-error: true |
| |
| - name: Download Previous Release Asset |
| if: github.event_name == 'release' |
| env: |
| GH_TOKEN: ${{ github.token }} |
| run: | |
| PREV_TAG=$(git tag --sort=-creatordate | head -n 2 | tail -n 1) |
| echo "Previous Release: $PREV_TAG" |
| echo "PREV_TAG=$PREV_TAG" >> $GITHUB_ENV |
| |
| mkdir -p base-metrics |
| gh release download $PREV_TAG -p metrics.json -D base-metrics || echo "No metrics.json found in $PREV_TAG release" |
| |
| - name: Compare with Base Branch |
| if: github.event_name != 'push' |
| run: | |
| if [ -f base-metrics/metrics.json ]; then |
| python tools/metrics.py compare -m -f tinyusb/src base-metrics/metrics.json metrics.json |
| cat metrics_compare.md |
| else |
| echo "No base metrics found, skipping comparison" |
| cp metrics.md metrics_compare.md |
| fi |
| |
| - name: Upload Release Assets |
| if: github.event_name == 'release' |
| env: |
| GH_TOKEN: ${{ github.token }} |
| run: | |
| CURR_TAG=${{ github.event.release.tag_name }} |
| COMPARE_FILE="metrics_compare_${CURR_TAG}-${PREV_TAG}.md" |
| mv metrics_compare.md $COMPARE_FILE |
| gh release upload $CURR_TAG metrics.json $COMPARE_FILE |
| |
| - name: Save PR number |
| if: github.event_name == 'pull_request' |
| run: echo ${{ github.event.number }} > pr_number.txt |
| |
| - name: Upload Metrics Comment Artifact |
| if: github.event_name == 'pull_request' |
| uses: actions/upload-artifact@v5 |
| with: |
| name: metrics-comment |
| path: | |
| metrics_compare.md |
| pr_number.txt |
| |
| - name: Post Code Metrics as PR Comment |
| if: (github.event_name == 'workflow_dispatch') || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false) |
| uses: marocchino/sticky-pull-request-comment@v2 |
| with: |
| header: code-metrics |
| path: metrics_compare.md |
| |
| # --------------------------------------- |
| # 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: ${{ matrix.build-system }} |
| toolchain: 'arm-gcc-${{ matrix.os }}' |
| 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 |
| uses: actions/checkout@v6 |
| |
| - name: Setup Zephyr project |
| uses: zephyrproject-rtos/action-zephyr-setup@v1 |
| with: |
| app-path: examples |
| toolchains: arm-zephyr-eabi |
| |
| - name: Build |
| run: | |
| west build -b nrf52840dk -d examples/device/cdc_msc/build examples/device/cdc_msc -- -DRTOS=zephyr |
| west build -b nrf52840dk -d examples/device/msc_dual_lun/build examples/device/msc_dual_lun -- -DRTOS=zephyr |
| |
| # --------------------------------------- |
| # Hardware in the loop (HIL) |
| # Run on PR only (hil-tinyusb), hil-hfp only run on non-forked PR |
| # --------------------------------------- |
| hil-build: |
| 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 |
| matrix: |
| toolchain: |
| - 'arm-gcc' |
| - 'esp-idf' |
| with: |
| build-system: 'cmake' |
| toolchain: ${{ matrix.toolchain }} |
| build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.hil_json)[matrix.toolchain]) }} |
| upload-artifacts: true |
| |
| # --------------------------------------- |
| # Hardware in the loop (HIL) |
| # self-hosted on local VM, for attached hardware checkout HIL_JSON |
| # --------------------------------------- |
| hil-tinyusb: |
| needs: hil-build |
| runs-on: [ self-hosted, X64, hathach, hardware-in-the-loop ] |
| steps: |
| - name: Get Skip Boards from previous run |
| if: github.run_attempt != '1' |
| run: | |
| if [ -f "${{ env.HIL_JSON }}.skip" ]; then |
| SKIP_BOARDS=$(cat "${{ env.HIL_JSON }}.skip") |
| else |
| SKIP_BOARDS="" |
| fi |
| echo "SKIP_BOARDS=$SKIP_BOARDS" |
| echo "SKIP_BOARDS=$SKIP_BOARDS" >> $GITHUB_ENV |
| |
| - name: Clean workspace |
| run: | |
| echo "Cleaning up for the first run" |
| rm -rf "${{ github.workspace }}" |
| mkdir -p "${{ github.workspace }}" |
| |
| - name: Checkout TinyUSB |
| uses: actions/checkout@v6 |
| |
| - name: Download Artifacts |
| uses: actions/download-artifact@v5 |
| with: |
| pattern: binaries-* |
| path: cmake-build |
| merge-multiple: true |
| |
| - name: Test on actual hardware |
| run: | |
| 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) |
| # self-hosted by HFP, build with IAR toolchain, for attached hardware checkout test/hil/hfp.json |
| # 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 ] |
| env: |
| IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} |
| steps: |
| - name: Clean workspace |
| run: | |
| echo "Cleaning up previous run" |
| rm -rf "${{ github.workspace }}"3 |
| mkdir -p "${{ github.workspace }}" |
| |
| - name: Toolchain version |
| run: | |
| iccarm --version |
| |
| - name: Checkout TinyUSB |
| uses: actions/checkout@v6 |
| |
| - name: Get build boards |
| run: | |
| MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py test/hil/hfp.json) |
| BUILD_ARGS=$(echo $MATRIX_JSON | jq -r '.["arm-gcc"] | join(" ")') |
| echo "BUILD_ARGS=$BUILD_ARGS" |
| echo "BUILD_ARGS=$BUILD_ARGS" >> $GITHUB_ENV |
| |
| - name: Get Dependencies |
| run: python3 tools/get_deps.py $BUILD_ARGS |
| |
| - name: Build |
| run: python3 tools/build.py --toolchain iar $BUILD_ARGS |
| |
| - name: Test on actual hardware (hardware in the loop) |
| run: python3 test/hil/hil_test.py hfp.json |