From 417e089caa53739135ae0e20da9b487daa2c3f62 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Mon, 23 Sep 2024 08:59:12 -0400 Subject: [PATCH 1/7] Add initial Treadmill Hardware CI workflow scaffold --- .github/workflows/treadmill-ci.yml | 204 +++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 .github/workflows/treadmill-ci.yml diff --git a/.github/workflows/treadmill-ci.yml b/.github/workflows/treadmill-ci.yml new file mode 100644 index 0000000000..55d62ada16 --- /dev/null +++ b/.github/workflows/treadmill-ci.yml @@ -0,0 +1,204 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2023. + +# This workflow contains all Treadmill-based hardware CI jobs. + +name: treadmill-ci +env: + TERM: xterm # Makes tput work in actions output + +# Controls when the action will run. Triggers the workflow on pull request and +# merge group checks: +on: + push: + branches: + - master + pull_request: # Run CI for PRs on any branch + merge_group: # Run CI for the GitHub merge queue + +permissions: + contents: read + +jobs: + test-prepare: + runs-on: ubuntu-latest + + # This provides access to the secrets required below, after approval by + # certain persons or GH teams: + environment: treadmill-ci + + outputs: + tml-job-ids: ${{ steps.treadmill-job-launch.outputs.tml-job-ids }} + tml-jobs: ${{ steps.treadmill-job-launch.outputs.tml-jobs }} + + steps: + - uses: actions-rust-lang/setup-rust-toolchain@v1 + + - name: Checkout Treadmill repository + uses: actions/checkout@v4 + with: + repository: treadmill-tb/treadmill + path: treadmill + + - name: Cache Treadmill CLI compilation artifacts + id: cache-tml-cli + uses: actions/cache@v4 + with: + path: treadmill/target + key: ${{ runner.os }}-tml-cli + + - name: Compile the Treadmill CLI binary + run: | + pushd treadmill + cargo build --package tml-cli + popd + echo "$PWD/treadmill/target/debug" >> "$GITHUB_PATH" + + # - uses: actions/checkout@v4 + # with: + # path: tock + + # - name: Analyze changes and determine types of tests to run + # run: | + # echo "TODO: implement this!" + + - name: Generate a token to register new just-in-time runners + id: generate-token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ vars.TREADMILL_GH_APP_CLIENT_ID }} + private-key: ${{ secrets.TREADMILL_GH_APP_PRIVATE_KEY }} + + - name: Create GitHub just-in-time runners and enqueue Treadmill jobs + id: treadmill-job-launch + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + TML_API_TOKEN: ${{ secrets.TREADMILL_API_TOKEN }} + + # Currently, all tests run only on hosts attached to an nRF52840DK + DUT_BOARD: nrf52840dk + + # A Ubuntu 22.04 image with a GitHub Actions self-hosted runner pre-configured: + IMAGE_ID: d407b09b9f56c666d0d3350890e364ba16aad08b484f4ca1de19d42569cc79b1 + run: | + TREADMILL_DUT_BOARD="nrf52840dk" + + # When we eventually launch tests on multiple hardware platforms in + # parallel, we need to supply different SUB_TEST_IDs here: + SUB_TEST_ID="0" + + RUNNER_ID="tml-gh-actions-runner-${GITHUB_REPOSITORY_ID}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${SUB_TEST_ID}" + + RUNNER_CONFIG_JSON="$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/${{ github.repository }}/actions/runners/generate-jitconfig \ + -f "name=$RUNNER_ID" \ + -F "runner_group_id=1" \ + -f "labels[]=$RUNNER_ID" \ + -f "work_folder=_work")" + echo "Generated configuration for runner $(echo "$RUNNER_CONFIG_JSON" | jq -r '.runner.name')" + + echo "Enqueueing treadmill job:" + TML_JOB_PARAMETERS="{\"gh-actions-runner-encoded-jit-config\": {\"secret\": true, \"value\": \"$(echo "$RUNNER_CONFIG_JSON" | jq -r '.encoded_jit_config')\"}}" + TML_JOB_ID_JSON="$(tml job enqueue \ + "$IMAGE_ID" \ + --tag-config "board:$DUT_BOARD" \ + --parameters "$TML_JOB_PARAMETERS" \ + )" + + TML_JOB_ID="$(echo "$TML_JOB_ID_JSON" | jq -r .job_id)" + echo "Enqueued Treadmill job with ID $TML_JOB_ID" + + # Pass the job IDs and other configuration data into the outputs of + # this step, such that we can run test-execute job instances for each + # Treadmill job we've started: + echo "tml-job-ids=[ \ + \"$TML_JOB_ID\" \ + ]" >> "$GITHUB_OUTPUT" + + echo "tml-jobs={ \ + \"$TML_JOB_ID\": { \ + \"runner-id\": \"$RUNNER_ID\", \ + } \ + }" >> "$GITHUB_OUTPUT" + + test-execute: + needs: test-prepare + + strategy: + matrix: + tml-job-id: ${{ fromJSON(needs.test-prepare.outputs.tml-job-ids) }} + + runs-on: ${{ fromJSON(needs.test-prepare.outputs.tml-jobs)[matrix.tml-job-id].runner-id }} + + steps: + - name: Print Treadmill Job Context and Debug Information + run: | + echo "Treadmill job id: ${{ matrix.tml-job-id }}" + echo "GitHub Actions Runner ID: ${{ fromJSON(needs.test-prepare.outputs.tml-jobs)[matrix.tml-job-id] }}" + echo "Network configration:" + ip address + echo "Attached USB devices:" + lsusb + echo "Parameters:" + ls /run/tml/parameters + + - uses: actions/checkout@v4 + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + + - name: Build the Tock kernel + run: | + pushd boards/nordic/nrf52840dk + unset RUSTFLAGS + make + popd + + # TODO: remove once jobs are automatically terminated when the QEMU + # process exits... + test-terminate: + needs: + - test-prepare + - test-execute + + # This provides access to the secrets required below, after approval by + # certain persons or GH teams: + environment: treadmill-ci + + runs-on: ubuntu-latest + + steps: + - uses: actions-rust-lang/setup-rust-toolchain@v1 + + - name: Checkout Treadmill repository + uses: actions/checkout@v4 + with: + repository: treadmill-tb/treadmill + path: treadmill + + - name: Cache Treadmill CLI compilation artifacts + id: cache-tml-cli + uses: actions/cache@v4 + with: + path: treadmill/target + key: ${{ runner.os }}-tml-cli + + - name: Compile the Treadmill CLI binary + run: | + pushd treadmill + cargo build --package tml-cli + popd + echo "$PWD/treadmill/target/debug" >> "$GITHUB_PATH" + + - name: Cancel Treadmill jobs + env: + TML_API_TOKEN: ${{ secrets.TREADMILL_API_TOKEN }} + run: | + echo '${{ needs.test-prepare.outputs.tml-job-ids }}' \ + | jq -rc '.[]' \ + | while read JOB_ID; do + echo "Canceling job ID $JOB_ID..." + tml job cancel "$JOB_ID" + done From f497c0a3548e23020827afdc2a83f0c0b2ec5708 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Mon, 23 Sep 2024 14:57:11 -0400 Subject: [PATCH 2/7] .github/workflows/treadmill-ci.yml: update copyright to 2024 Co-authored-by: Brad Campbell --- .github/workflows/treadmill-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/treadmill-ci.yml b/.github/workflows/treadmill-ci.yml index 55d62ada16..52f75dd1bb 100644 --- a/.github/workflows/treadmill-ci.yml +++ b/.github/workflows/treadmill-ci.yml @@ -1,6 +1,6 @@ # Licensed under the Apache License, Version 2.0 or the MIT License. # SPDX-License-Identifier: Apache-2.0 OR MIT -# Copyright Tock Contributors 2023. +# Copyright Tock Contributors 2024. # This workflow contains all Treadmill-based hardware CI jobs. From f9ad65afb6c68fc29397444b953646c7cd454929 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Mon, 23 Sep 2024 15:35:18 -0400 Subject: [PATCH 3/7] treadmill-ci: do not require approval for merge queue & master refs --- .github/workflows/treadmill-ci.yml | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/treadmill-ci.yml b/.github/workflows/treadmill-ci.yml index 52f75dd1bb..a2fd5ecc20 100644 --- a/.github/workflows/treadmill-ci.yml +++ b/.github/workflows/treadmill-ci.yml @@ -10,6 +10,8 @@ env: # Controls when the action will run. Triggers the workflow on pull request and # merge group checks: +# +# KEEP IN SYNC WITH `environment:` ATTRIBUTE BELOW: on: push: branches: @@ -24,9 +26,13 @@ jobs: test-prepare: runs-on: ubuntu-latest - # This provides access to the secrets required below, after approval by - # certain persons or GH teams: - environment: treadmill-ci + # This provides access to the secrets required below: + # - for `treadmill-ci`: after approval by certain persons or GH teams + # - for `treadmill-ci-merged`: without approval, on merge queue branches + # and the master branch + # + # KEEP IN SYNC WITH `on:` EVENTS ABOVE: + environment: ${{ github.event_name == 'pull_request' && 'treadmill-ci' || 'treadmill-ci-merged' }} outputs: tml-job-ids: ${{ steps.treadmill-job-launch.outputs.tml-job-ids }} @@ -163,9 +169,13 @@ jobs: - test-prepare - test-execute - # This provides access to the secrets required below, after approval by - # certain persons or GH teams: - environment: treadmill-ci + # This provides access to the secrets required below: + # - for `treadmill-ci`: after approval by certain persons or GH teams + # - for `treadmill-ci-merged`: without approval, on merge queue branches + # and the master branch + # + # KEEP IN SYNC WITH `on:` EVENTS ABOVE: + environment: ${{ github.event_name == 'pull_request' && 'treadmill-ci' || 'treadmill-ci-merged' }} runs-on: ubuntu-latest From 9ca4e77001418939846fa46aabe0d51e9f337845 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Tue, 24 Sep 2024 07:31:14 -0400 Subject: [PATCH 4/7] treadmill-ci: automatically terminate Treadmill job after runner exit --- .github/workflows/treadmill-ci.yml | 74 ++++++++---------------------- 1 file changed, 19 insertions(+), 55 deletions(-) diff --git a/.github/workflows/treadmill-ci.yml b/.github/workflows/treadmill-ci.yml index a2fd5ecc20..0cfffe135c 100644 --- a/.github/workflows/treadmill-ci.yml +++ b/.github/workflows/treadmill-ci.yml @@ -86,16 +86,18 @@ jobs: DUT_BOARD: nrf52840dk # A Ubuntu 22.04 image with a GitHub Actions self-hosted runner pre-configured: - IMAGE_ID: d407b09b9f56c666d0d3350890e364ba16aad08b484f4ca1de19d42569cc79b1 + IMAGE_ID: 489d1b9f677856e415b87c6ffa3312b567de437b75a462a0253cf359a0bd51e9 run: | - TREADMILL_DUT_BOARD="nrf52840dk" - # When we eventually launch tests on multiple hardware platforms in # parallel, we need to supply different SUB_TEST_IDs here: SUB_TEST_ID="0" + # This runner ID uniquely identifies the GitHub Actions runner we're + # registering and allows us to launch test-execute jobs on this exact + # runner (connected to the exact board we want to run tests on). RUNNER_ID="tml-gh-actions-runner-${GITHUB_REPOSITORY_ID}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${SUB_TEST_ID}" + # Obtain a new just-in-time runner registration token: RUNNER_CONFIG_JSON="$(gh api \ -H "Accept: application/vnd.github+json" \ -H "X-GitHub-Api-Version: 2022-11-28" \ @@ -106,8 +108,21 @@ jobs: -f "work_folder=_work")" echo "Generated configuration for runner $(echo "$RUNNER_CONFIG_JSON" | jq -r '.runner.name')" + # Generate a set of job paramters that includes the GitHub runner + # registration token and a script that shuts down the host once the + # runner has run through successfully: + TML_JOB_PARAMETERS="{\ + \"gh-actions-runner-encoded-jit-config\": {\ + \"secret\": true, \ + \"value\": \"$(echo "$RUNNER_CONFIG_JSON" | jq -r '.encoded_jit_config')\" \ + }, \ + \"gh-actions-runner-exec-stop-post-sh\": {\ + \"secret\": false, \ + \"value\": \"if [ \\\"\$SERVICE_RESULT\\\" = \\\"success\\\" ]; then systemctl poweroff; fi\" \ + }\ + }" + echo "Enqueueing treadmill job:" - TML_JOB_PARAMETERS="{\"gh-actions-runner-encoded-jit-config\": {\"secret\": true, \"value\": \"$(echo "$RUNNER_CONFIG_JSON" | jq -r '.encoded_jit_config')\"}}" TML_JOB_ID_JSON="$(tml job enqueue \ "$IMAGE_ID" \ --tag-config "board:$DUT_BOARD" \ @@ -161,54 +176,3 @@ jobs: unset RUSTFLAGS make popd - - # TODO: remove once jobs are automatically terminated when the QEMU - # process exits... - test-terminate: - needs: - - test-prepare - - test-execute - - # This provides access to the secrets required below: - # - for `treadmill-ci`: after approval by certain persons or GH teams - # - for `treadmill-ci-merged`: without approval, on merge queue branches - # and the master branch - # - # KEEP IN SYNC WITH `on:` EVENTS ABOVE: - environment: ${{ github.event_name == 'pull_request' && 'treadmill-ci' || 'treadmill-ci-merged' }} - - runs-on: ubuntu-latest - - steps: - - uses: actions-rust-lang/setup-rust-toolchain@v1 - - - name: Checkout Treadmill repository - uses: actions/checkout@v4 - with: - repository: treadmill-tb/treadmill - path: treadmill - - - name: Cache Treadmill CLI compilation artifacts - id: cache-tml-cli - uses: actions/cache@v4 - with: - path: treadmill/target - key: ${{ runner.os }}-tml-cli - - - name: Compile the Treadmill CLI binary - run: | - pushd treadmill - cargo build --package tml-cli - popd - echo "$PWD/treadmill/target/debug" >> "$GITHUB_PATH" - - - name: Cancel Treadmill jobs - env: - TML_API_TOKEN: ${{ secrets.TREADMILL_API_TOKEN }} - run: | - echo '${{ needs.test-prepare.outputs.tml-job-ids }}' \ - | jq -rc '.[]' \ - | while read JOB_ID; do - echo "Canceling job ID $JOB_ID..." - tml job cancel "$JOB_ID" - done From 071e8396725af1d37e764f6127af3b1dee8e29ea Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Tue, 24 Sep 2024 07:41:18 -0400 Subject: [PATCH 5/7] treadmill-ci: refer to Treadmill book & repo in workflow --- .github/workflows/treadmill-ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/treadmill-ci.yml b/.github/workflows/treadmill-ci.yml index 0cfffe135c..4a11c5d6eb 100644 --- a/.github/workflows/treadmill-ci.yml +++ b/.github/workflows/treadmill-ci.yml @@ -3,6 +3,19 @@ # Copyright Tock Contributors 2024. # This workflow contains all Treadmill-based hardware CI jobs. +# +# Treadmill is a distributed hardware testbed developed within the Tock OS +# project. For more information on Treadmill, have a look at its documentation +# [1] or repository [2]. +# +# This workflow is based on the Treadmill GitHub Actions integration guide [3]. +# In addition, it features the ability to run multiple Treadmill jobs and +# test-execute stages through GitHub Action's job matrices, and uses a GitHub +# environment to allow deployments with access to secrets for select PRs. +# +# [1]: https://book.treadmill.ci/ +# [2]: https://github.com/treadmill-tb/treadmill +# [3]: https://book.treadmill.ci/user-guide/github-actions-integration.html name: treadmill-ci env: From 1214797456555bb222693d2cad77819f49535dba Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Tue, 24 Sep 2024 07:43:06 -0400 Subject: [PATCH 6/7] treadmill-ci: add todo for addl. test steps --- .github/workflows/treadmill-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/treadmill-ci.yml b/.github/workflows/treadmill-ci.yml index 4a11c5d6eb..1547fe91d7 100644 --- a/.github/workflows/treadmill-ci.yml +++ b/.github/workflows/treadmill-ci.yml @@ -189,3 +189,6 @@ jobs: unset RUSTFLAGS make popd + + # TODO: this job runs on the Treadmill host, with access to the target + # board. Add additional test & testing scripts. From 0934adf104dec961ece94ec888c6d8493f889095 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Tue, 24 Sep 2024 10:43:59 -0400 Subject: [PATCH 7/7] treadmill-ci: update GH actions VM image and refer to image overview --- .github/workflows/treadmill-ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/treadmill-ci.yml b/.github/workflows/treadmill-ci.yml index 1547fe91d7..cc6c2a6085 100644 --- a/.github/workflows/treadmill-ci.yml +++ b/.github/workflows/treadmill-ci.yml @@ -98,8 +98,10 @@ jobs: # Currently, all tests run only on hosts attached to an nRF52840DK DUT_BOARD: nrf52840dk - # A Ubuntu 22.04 image with a GitHub Actions self-hosted runner pre-configured: - IMAGE_ID: 489d1b9f677856e415b87c6ffa3312b567de437b75a462a0253cf359a0bd51e9 + # A Ubuntu 22.04 image with a GitHub Actions self-hosted runner pre-configured. + # + # For the available images see https://book.treadmill.ci/treadmillci-deployment/images.html + IMAGE_ID: 0373bb7d728b36cb6083cfe12f27038b71972ceb90563b0037d4012df7b62bf4 run: | # When we eventually launch tests on multiple hardware platforms in # parallel, we need to supply different SUB_TEST_IDs here: