Healthcheck #185
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Healthcheck | |
| on: | |
| schedule: | |
| - cron: "0 0 * * *" | |
| workflow_dispatch: | |
| env: | |
| PYTHONUNBUFFERED: "1" | |
| PYTEST_ADDOPTS: "--color=yes" | |
| LG_CONSOLE: "internal" | |
| RELEASE: "24.10.2" | |
| USER: "labgrid-dev" | |
| jobs: | |
| generate-matrix: | |
| name: Generate labnet.yaml matrix | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.set-matrix.outputs.matrix }} | |
| steps: | |
| - name: Check out repository code | |
| uses: actions/checkout@v5 | |
| - name: Generate matrix | |
| id: set-matrix | |
| run: | | |
| sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq &&\ | |
| sudo chmod +x /usr/local/bin/yq | |
| # Use pipe because of this bug | |
| # https://github.com/mikefarah/yq/issues/2454 | |
| matrix=$(yq -o=json labnet.yaml | jq ' | |
| . as $root | | |
| $root.labs as $labs | | |
| $root.devices as $devices | | |
| $labs | |
| | to_entries | |
| | map( | |
| .key as $lab | | |
| .value.devices | |
| | map( | |
| select($devices[.] != null and $devices[.].snapshots_only != true) | | |
| { | |
| "device": ., | |
| "proxy": $labs[$lab].proxy, | |
| "target": $devices[.].target, | |
| "firmware": $devices[.].firmware, | |
| "maintainers": $labs[$lab].maintainers, | |
| "snapshots_only": ($devices[.].snapshots_only // false) | |
| } | |
| ) | |
| ) | |
| | flatten | |
| ') | |
| echo "matrix=$(echo "$matrix" | jq -c '.')" >> $GITHUB_OUTPUT | |
| test-real: | |
| name: ${{ matrix.device }} (${{ matrix.proxy }}) | |
| needs: generate-matrix | |
| runs-on: global-coordinator | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: ${{ fromJson(needs.generate-matrix.outputs.matrix) }} | |
| steps: | |
| - name: Check out repository code | |
| uses: actions/checkout@v5 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| - name: Set environment | |
| env: | |
| target: ${{ matrix.target }} | |
| run: | | |
| # workaround until 24.10.x is fixed on tplink_tl-wr1043nd-v3 | |
| if [ "${{ matrix.device }}" = "tplink_tl-wr1043nd-v3" ]; then | |
| export RELEASE=23.05.5 | |
| echo "RELEASE=${RELEASE}" >> $GITHUB_ENV | |
| fi | |
| export firmware=openwrt-${RELEASE}-${{ matrix.target }}-${{ matrix.device }}-${{ matrix.firmware }} | |
| export upstream_url="https://mirror-03.infra.openwrt.org/releases/${RELEASE}/targets" | |
| mkdir -p $GITHUB_WORKSPACE/tftp/${{ matrix.device }} | |
| wget $upstream_url/${target/-/\/}/$firmware \ | |
| --output-document $GITHUB_WORKSPACE/tftp/${{ matrix.device }}/$firmware | |
| (cd $GITHUB_WORKSPACE/tftp/ && gzip -d ${{ matrix.device }}/$firmware) || true | |
| FIRMWARE_VERSION=$(curl $upstream_url/${target/-/\/}/version.buildinfo) | |
| echo "FIRMWARE_VERSION=$FIRMWARE_VERSION" >> $GITHUB_ENV | |
| echo "LG_IMAGE=$GITHUB_WORKSPACE/tftp/${{ matrix.device }}/${firmware/.gz/}" >> $GITHUB_ENV | |
| echo "LG_PROXY=${{ matrix.proxy }}" >> $GITHUB_ENV | |
| - name: Wait for free device | |
| run: | | |
| eval $(uv run labgrid-client reserve --wait --shell device=${{ matrix.device }}) | |
| echo "LG_TOKEN=$LG_TOKEN" >> $GITHUB_ENV | |
| echo "LG_PLACE=+" >> $GITHUB_ENV | |
| uv run labgrid-client -p +$LG_TOKEN lock | |
| echo "LG_ENV=targets/${{ matrix.device }}.yaml" >> $GITHUB_ENV | |
| - name: Run test | |
| id: test | |
| run: | | |
| uv run pytest tests/ \ | |
| --lg-log \ | |
| --lg-colored-steps \ | |
| --log-cli-level=CONSOLE | |
| - name: Poweroff and unlock device | |
| if: always() | |
| run: | | |
| uv run labgrid-client power off || true | |
| uv run labgrid-client unlock | |
| - name: Upload console logs | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: console-${{ matrix.proxy }}-${{ matrix.device }} | |
| path: console_* | |
| - name: Handle test result | |
| uses: actions/github-script@v8 | |
| if: always() | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const issueTitle = "Healthcheck ${{ matrix.proxy }}/${{ matrix.device }}"; | |
| const runUrl = "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"; | |
| const isSuccess = "${{ job.status }}" === "success"; | |
| const failureBody = ` | |
| ### ❌ Healthcheck Failed | |
| The automated healthcheck for: | |
| - **Proxy**: \`${{ matrix.proxy }}\` | |
| - **Device**: \`${{ matrix.device }}\` | |
| - **Maintainers**: ${{ matrix.maintainers }} | |
| has **failed**. Please review the logs and investigate the issue. | |
| 🔗 [View the full workflow run](${runUrl}) | |
| `.trim(); | |
| // Fetch existing issues | |
| const issues = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'all', | |
| per_page: 100, | |
| }); | |
| let testIssue = issues.data.find(issue => | |
| issue.title === issueTitle && | |
| issue.user.type === "Bot" | |
| ); | |
| if (isSuccess) { | |
| if (testIssue) { | |
| await github.rest.issues.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: testIssue.number, | |
| state: "closed", | |
| }); | |
| } | |
| console.log("Closed issue as test passed."); | |
| } else { | |
| if (testIssue) { | |
| await github.rest.issues.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: testIssue.number, | |
| state: "open", | |
| body: failureBody, | |
| labels: ["healthcheck"], | |
| }); | |
| console.log("Reopened existing issue due to test failure."); | |
| } else { | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: issueTitle, | |
| body: failureBody, | |
| labels: ["healthcheck"], | |
| }); | |
| console.log("Created new issue due to test failure."); | |
| } | |
| } |