diff --git a/.github/workflows/treadmill-ci.yml b/.github/workflows/treadmill-ci.yml new file mode 100644 index 0000000000..cc6c2a6085 --- /dev/null +++ b/.github/workflows/treadmill-ci.yml @@ -0,0 +1,196 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# 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: + TERM: xterm # Makes tput work in actions output + +# 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: + - 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: + # - 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 }} + 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. + # + # 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: + 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" \ + /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')" + + # 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_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: this job runs on the Treadmill host, with access to the target + # board. Add additional test & testing scripts.