diff options
| author | Michael Rogov Papernov <[email protected]> | 2026-01-10 17:58:41 +0000 |
|---|---|---|
| committer | Michael Rogov Papernov <[email protected]> | 2026-01-16 21:49:16 +0000 |
| commit | 5ad42064ea544080d47c893dafb1b41447ab9f32 (patch) | |
| tree | ae3c7f5ee5919a7ffa92658fb14e8cda26e01695 /.github/workflows | |
| parent | 71ed9d1498e04f99f69fc8c0336ca41ec7a576af (diff) | |
Integrate MemBrowse
Diffstat (limited to '.github/workflows')
| -rw-r--r-- | .github/workflows/build.yml | 137 | ||||
| -rw-r--r-- | .github/workflows/build_util.yml | 14 | ||||
| -rw-r--r-- | .github/workflows/membrowse-comment.yml | 44 | ||||
| -rw-r--r-- | .github/workflows/membrowse-onboard.yml | 58 | ||||
| -rw-r--r-- | .github/workflows/membrowse-report.yml | 101 |
5 files changed, 324 insertions, 30 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bb8c6d65d..dc5b1975e 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,59 @@ 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: Save PR number + if: steps.download.outcome == 'success' + run: echo ${{ github.event.number }} > reports/pr_number.txt + + - 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..e0fef7ce4 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" '.[] | 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..a3db37360 --- /dev/null +++ b/.github/workflows/membrowse-comment.yml @@ -0,0 +1,44 @@ +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 == 'success' + permissions: + actions: read + pull-requests: write + steps: + - 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: Read PR Number + if: steps.download.outcome == 'success' + id: pr_number + run: | + if [ -f reports/pr_number.txt ]; then + echo "number=$(cat reports/pr_number.txt)" >> $GITHUB_OUTPUT + fi + + - name: Post Membrowse PR comment + if: steps.download.outcome == 'success' && steps.pr_number.outputs.number != '' + uses: membrowse/membrowse-action/comment-action@v1 + with: + json_files: 'reports/*.json' + pr_number: ${{ steps.pr_number.outputs.number }} + 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..a183297b2 --- /dev/null +++ b/.github/workflows/membrowse-onboard.yml @@ -0,0 +1,58 @@ +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: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Load target matrix + id: set-matrix + run: echo "matrix=$(jq -c '.' .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.matrix) }} + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + submodules: recursive + + - name: Install packages + run: ${{ matrix.setup_cmd }} + + - 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.target_name }} + num_commits: ${{ github.event.inputs.num_commits }} + build_script: ${{ matrix.build_cmd }} + elf: ${{ matrix.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..aff9fe138 --- /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: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Load target matrix + id: set-matrix + run: echo "matrix=$(jq -c '.' .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.matrix) }} + + 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 "${{ matrix.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.target_name }} + elf: ${{ matrix.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.target_name }} + 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.target_name }} + path: ${{ steps.membrowse.outputs.report_path || steps.membrowse-identical.outputs.report_path }} |
