diff options
| author | Zixun LI <[email protected]> | 2026-01-24 23:58:01 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-01-24 23:58:01 +0100 |
| commit | fba582ae2fe7881dcc428e238a5235050ed01e3f (patch) | |
| tree | 36bdec8cda09758e11028b55b18c7f46c209c481 /.github/workflows | |
| parent | 180fab0f39b0a9db4577e63f222014451aae5bf8 (diff) | |
| parent | 697fdca69d7a1df0cc63b0af47ff66459af9367a (diff) | |
Merge pull request #3459 from membrowse/master
Integrate MemBrowse.
Diffstat (limited to '.github/workflows')
| -rw-r--r-- | .github/workflows/build.yml | 133 | ||||
| -rw-r--r-- | .github/workflows/build_util.yml | 14 | ||||
| -rw-r--r-- | .github/workflows/membrowse-comment.yml | 38 | ||||
| -rw-r--r-- | .github/workflows/membrowse-onboard.yml | 62 | ||||
| -rw-r--r-- | .github/workflows/membrowse-report.yml | 101 |
5 files changed, 318 insertions, 30 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bb8c6d65d..e0c1d0a14 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,30 +3,8 @@ name: Build on: workflow_dispatch: push: - 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' + branches: [master] 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 ] concurrency: @@ -37,7 +15,44 @@ env: HIL_JSON: test/hil/tinyusb.json jobs: + # Check if code paths changed (skip builds if doc-only) + check-paths: + if: github.event_name == 'pull_request' || github.event_name == 'push' + 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: + needs: [check-paths] + if: | + always() && ( + github.event_name == 'release' || + github.event_name == 'workflow_dispatch' || + needs.check-paths.outputs.code_changed == 'true' + ) runs-on: ubuntu-latest outputs: json: ${{ steps.set-matrix-json.outputs.matrix }} @@ -82,6 +97,7 @@ jobs: build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }} build-options: '--one-first' upload-metrics: true + upload-artifacts: true code-metrics: needs: cmake @@ -181,7 +197,8 @@ jobs: # Build Make/CMake on Windows/MacOS # --------------------------------------- build-os: - if: github.event_name == 'pull_request' + needs: [check-paths] + if: needs.check-paths.outputs.code_changed == 'true' uses: ./.github/workflows/build_util.yml strategy: fail-fast: false @@ -198,7 +215,8 @@ jobs: # Zephyr # --------------------------------------- zephyr: - if: github.event_name == 'push' + needs: [check-paths] + if: needs.check-paths.outputs.code_changed == 'true' runs-on: ubuntu-latest steps: - name: Checkout TinyUSB @@ -220,10 +238,10 @@ jobs: # Run on PR only (hil-tinyusb), hil-hfp only run on non-forked PR # --------------------------------------- hil-build: + needs: [check-paths, set-matrix] if: | github.repository_owner == 'hathach' && - (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch') - needs: set-matrix + (github.event_name == 'workflow_dispatch' || needs.check-paths.outputs.code_changed == 'true') uses: ./.github/workflows/build_util.yml strategy: fail-fast: false @@ -242,8 +260,10 @@ jobs: # self-hosted on local VM, for attached hardware checkout HIL_JSON # --------------------------------------- hil-tinyusb: - if: github.repository_owner == 'hathach' && github.event_name != 'push' - needs: hil-build + needs: [check-paths, hil-build] + if: | + github.repository_owner == 'hathach' && + (github.event_name == 'release' || github.event_name == 'workflow_dispatch' || needs.check-paths.outputs.code_changed == 'true') runs-on: [ self-hosted, X64, hathach, hardware-in-the-loop ] steps: - name: Get Skip Boards from previous run @@ -283,10 +303,11 @@ jobs: # Since IAR Token secret is not passed to forked PR, only build non-forked PR # --------------------------------------- hil-hfp: + needs: [check-paths] if: | github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false && - github.event_name != 'push' + (github.event_name == 'release' || github.event_name == 'workflow_dispatch' || needs.check-paths.outputs.code_changed == 'true') runs-on: [ self-hosted, Linux, X64, hifiphile ] env: IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} @@ -319,3 +340,55 @@ 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: [check-paths, cmake] + if: | + always() && !cancelled() && ( + github.event_name == 'push' || + github.event_name == 'release' || + github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && needs.check-paths.outputs.code_changed == 'true') + ) + permissions: + contents: read + actions: read + uses: ./.github/workflows/membrowse-report.yml + with: + code_changed: ${{ needs.check-paths.outputs.code_changed == 'true' || github.event_name == 'release' || github.event_name == 'workflow_dispatch' }} + secrets: inherit + + membrowse-comment: + needs: [check-paths, membrowse] + if: > + always() && + github.event_name == 'pull_request' && + needs.check-paths.outputs.code_changed == 'true' + 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 540ee8b47..e62c10ca1 100644 --- a/.github/workflows/build_util.yml +++ b/.github/workflows/build_util.yml @@ -73,6 +73,19 @@ jobs: 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 }} uses: actions/upload-artifact@v5 @@ -86,3 +99,4 @@ jobs: cmake-build/cmake-build-*/*/*/partition_table/partition-table.bin cmake-build/cmake-build-*/*/*/config.env cmake-build/cmake-build-*/*/*/flash_args + cmake-build/hw/mcu/**/*.ld diff --git a/.github/workflows/membrowse-comment.yml b/.github/workflows/membrowse-comment.yml new file mode 100644 index 000000000..a99c9db51 --- /dev/null +++ b/.github/workflows/membrowse-comment.yml @@ -0,0 +1,38 @@ +name: Membrowse Comment + +on: + workflow_run: + workflows: ["Build"] + types: + - completed + +jobs: + post-comment: + runs-on: ubuntu-latest + if: > + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion != 'cancelled' + permissions: + actions: read + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Download Artifacts + id: download + uses: actions/download-artifact@v5 + with: + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + name: membrowse-comment + path: reports + continue-on-error: true + + - name: Post Membrowse PR comment + if: steps.download.outcome == 'success' + uses: membrowse/membrowse-action/comment-action@v1 + with: + json_files: 'reports/*.json' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/membrowse-onboard.yml b/.github/workflows/membrowse-onboard.yml new file mode 100644 index 000000000..aa7204ffa --- /dev/null +++ b/.github/workflows/membrowse-onboard.yml @@ -0,0 +1,62 @@ +name: Onboard to Membrowse + +on: + workflow_dispatch: + inputs: + num_commits: + description: 'Number of commits to process' + required: true + default: '10' + type: string + +jobs: + load-targets: + runs-on: ubuntu-22.04 + outputs: + targets: ${{ steps.load.outputs.targets }} + toolchains: ${{ steps.load.outputs.toolchains }} + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Load target matrix + id: load + run: | + echo "targets=$(jq -c '.targets' .github/membrowse-targets.json)" >> $GITHUB_OUTPUT + echo "toolchains=$(jq -c '.toolchains' .github/membrowse-targets.json)" >> $GITHUB_OUTPUT + + onboard: + needs: load-targets + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + include: ${{ fromJson(needs.load-targets.outputs.targets) }} + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + submodules: recursive + + - name: Install packages + run: | + ${{ 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/[email protected] + with: + key: ${{ matrix.port }}-${{ matrix.board }} + + - name: Run Membrowse Onboard Action + uses: membrowse/membrowse-action/onboard-action@v1 + with: + target_name: ${{ matrix.port }}-${{ matrix.board }}-${{ matrix.example }} + num_commits: ${{ github.event.inputs.num_commits }} + build_script: python3 tools/build.py -s cmake -b ${{ matrix.board }} + 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 }} diff --git a/.github/workflows/membrowse-report.yml b/.github/workflows/membrowse-report.yml new file mode 100644 index 000000000..0667418e6 --- /dev/null +++ b/.github/workflows/membrowse-report.yml @@ -0,0 +1,101 @@ +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 }} |
