|
| 1 | +name: Hardware Tests (labgrid) |
| 2 | + |
| 3 | +# Bespoke MATLAB hardware-CI workflow. labgrid (adi-labgrid-plugins) boots |
| 4 | +# the board for a coordinator place, hands MATLAB the booted board's libIIO |
| 5 | +# URI via the IIO_URI env var, and runs runHWTests against it. |
| 6 | +# |
| 7 | +# Two job stages: |
| 8 | +# discover — on a coordinator-adjacent runner, intersect live coordinator |
| 9 | +# places with test/hw_ci/board_map.yaml -> matrix of places. |
| 10 | +# hw — one shard per place, pinned to its hw-<place> self-hosted |
| 11 | +# runner (which must have MATLAB + libiio installed), boots the |
| 12 | +# board and runs MATLAB. |
| 13 | +# |
| 14 | +# Requires a coordinator reachable at vars.ADI_LG_COORDINATOR and self-hosted |
| 15 | +# runners labeled [self-hosted, hw-coordinator] and [self-hosted, hw-<place>] |
| 16 | +# per the adi-labgrid-plugins HW-CI runner contract. |
| 17 | + |
| 18 | +on: |
| 19 | + workflow_dispatch: |
| 20 | + schedule: |
| 21 | + - cron: "0 8 * * *" |
| 22 | + pull_request: |
| 23 | + types: [labeled, opened, synchronize, reopened] |
| 24 | + |
| 25 | +# A pinned reference to adi-labgrid-plugins. Bump alongside the coordinator. |
| 26 | +env: |
| 27 | + ADI_LG_PLUGINS_REF: "v2" |
| 28 | + VENV_DIR: "${{ github.workspace }}/.hw-ci-venv" |
| 29 | + MATLAB_BIN: "/opt/MATLAB/R2025b/bin/matlab" |
| 30 | + |
| 31 | +# Minimal default token permissions; the publish job widens its own below. |
| 32 | +permissions: |
| 33 | + contents: read |
| 34 | + |
| 35 | +jobs: |
| 36 | + discover: |
| 37 | + # Only on PRs that opt in with the `hw-test` label; always on dispatch/cron. |
| 38 | + if: >- |
| 39 | + github.event_name != 'pull_request' || |
| 40 | + contains(github.event.pull_request.labels.*.name, 'hw-test') |
| 41 | + runs-on: [self-hosted, hw-coordinator] |
| 42 | + outputs: |
| 43 | + matrix: ${{ steps.discover.outputs.matrix }} |
| 44 | + count: ${{ steps.discover.outputs.count }} |
| 45 | + steps: |
| 46 | + - uses: actions/checkout@v4 |
| 47 | + |
| 48 | + - name: Setup venv (adi-labgrid-plugins) |
| 49 | + uses: tfcollins/labgrid-plugins/.github/actions/setup-uv-venv@v2 |
| 50 | + with: |
| 51 | + venv_dir: ${{ env.VENV_DIR }} |
| 52 | + install_cmd: >- |
| 53 | + uv pip install --python "$VENV_DIR/bin/python" |
| 54 | + "adi-labgrid-plugins @ git+https://github.com/tfcollins/labgrid-plugins.git@${{ env.ADI_LG_PLUGINS_REF }}" |
| 55 | +
|
| 56 | + - name: Discover places |
| 57 | + id: discover |
| 58 | + env: |
| 59 | + LG_COORDINATOR: ${{ vars.ADI_LG_COORDINATOR }} |
| 60 | + run: | |
| 61 | + "$VENV_DIR/bin/adi-lg-matlab" discover \ |
| 62 | + --coord "$LG_COORDINATOR" \ |
| 63 | + --board-map test/hw_ci/board_map.yaml \ |
| 64 | + --github-output |
| 65 | +
|
| 66 | + hw: |
| 67 | + needs: discover |
| 68 | + if: ${{ needs.discover.outputs.count != '0' }} |
| 69 | + strategy: |
| 70 | + fail-fast: false |
| 71 | + matrix: |
| 72 | + include: ${{ fromJSON(needs.discover.outputs.matrix).include }} |
| 73 | + runs-on: [self-hosted, "hw-${{ matrix.place }}"] |
| 74 | + timeout-minutes: 60 |
| 75 | + steps: |
| 76 | + - uses: actions/checkout@v4 |
| 77 | + |
| 78 | + - name: Setup venv (adi-labgrid-plugins) |
| 79 | + uses: tfcollins/labgrid-plugins/.github/actions/setup-uv-venv@v2 |
| 80 | + with: |
| 81 | + venv_dir: ${{ env.VENV_DIR }} |
| 82 | + install_cmd: >- |
| 83 | + uv pip install --python "$VENV_DIR/bin/python" |
| 84 | + "adi-labgrid-plugins @ git+https://github.com/tfcollins/labgrid-plugins.git@${{ env.ADI_LG_PLUGINS_REF }}" |
| 85 | +
|
| 86 | + - name: Acquire place |
| 87 | + uses: tfcollins/labgrid-plugins/.github/actions/acquire-place@v2 |
| 88 | + with: |
| 89 | + coordinator: ${{ vars.ADI_LG_COORDINATOR }} |
| 90 | + place: ${{ matrix.place }} |
| 91 | + labgrid_client: ${{ env.VENV_DIR }}/bin/labgrid-client |
| 92 | + |
| 93 | + - name: Boot board + run MATLAB HW tests |
| 94 | + env: |
| 95 | + LG_COORDINATOR: ${{ vars.ADI_LG_COORDINATOR }} |
| 96 | + run: | |
| 97 | + # Place is already acquired by the composite action above, so do |
| 98 | + # NOT pass --acquire here (avoids double-acquire). |
| 99 | + "$VENV_DIR/bin/adi-lg-matlab" run \ |
| 100 | + --coord "$LG_COORDINATOR" \ |
| 101 | + --place "${{ matrix.place }}" \ |
| 102 | + --board-map test/hw_ci/board_map.yaml \ |
| 103 | + --repo-dir "$GITHUB_WORKSPACE" \ |
| 104 | + --matlab "$MATLAB_BIN" \ |
| 105 | + --junit "junit-${{ matrix.place }}.xml" |
| 106 | +
|
| 107 | + - name: Release place |
| 108 | + if: always() |
| 109 | + run: | |
| 110 | + "$VENV_DIR/bin/labgrid-client" -x "${{ vars.ADI_LG_COORDINATOR }}" \ |
| 111 | + -p "${{ matrix.place }}" release || true |
| 112 | +
|
| 113 | + - name: Upload JUnit + MATLAB logs |
| 114 | + if: always() |
| 115 | + uses: actions/upload-artifact@v4 |
| 116 | + with: |
| 117 | + name: hw-results-${{ matrix.place }} |
| 118 | + path: | |
| 119 | + junit-${{ matrix.place }}.xml |
| 120 | + ${{ matrix.matlab_board }}_HWTestResults.xml |
| 121 | + failures.txt |
| 122 | + if-no-files-found: ignore |
| 123 | + |
| 124 | + publish: |
| 125 | + needs: hw |
| 126 | + # Run only when the hw matrix actually ran (i.e. the hw-test path was |
| 127 | + # taken). When hw is skipped, there is nothing to publish — skip too, |
| 128 | + # so this job never sits pending on a PR that has no HW runner. |
| 129 | + if: ${{ always() && needs.hw.result != 'skipped' }} |
| 130 | + runs-on: [self-hosted, hw-coordinator] |
| 131 | + # The test-result action posts a check run and a PR comment. |
| 132 | + permissions: |
| 133 | + contents: read |
| 134 | + checks: write |
| 135 | + pull-requests: write |
| 136 | + steps: |
| 137 | + - uses: actions/download-artifact@v4 |
| 138 | + with: |
| 139 | + path: hw-results |
| 140 | + - name: Publish test summary |
| 141 | + uses: EnricoMi/publish-unit-test-result-action@v2 |
| 142 | + with: |
| 143 | + junit_files: "hw-results/**/junit-*.xml" |
0 commit comments