name: Wokwi tests on: workflow_run: workflows: ["Runtime Tests"] types: - completed # No permissions by default permissions: { contents: read } env: WOKWI_TIMEOUT: 600000 # Milliseconds jobs: get-artifacts: name: Get required artifacts runs-on: ubuntu-latest permissions: actions: read statuses: write outputs: pr_num: ${{ steps.set-ref.outputs.pr_num }} ref: ${{ steps.set-ref.outputs.ref }} base: ${{ steps.set-ref.outputs.base }} targets: ${{ steps.set-ref.outputs.targets }} types: ${{ steps.set-ref.outputs.types }} steps: - name: Report pending uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const owner = '${{ github.repository_owner }}'; const repo = '${{ github.repository }}'.split('/')[1]; const sha = '${{ github.event.workflow_run.head_sha }}'; core.debug(`owner: ${owner}`); core.debug(`repo: ${repo}`); core.debug(`sha: ${sha}`); const { context: name, state } = (await github.rest.repos.createCommitStatus({ context: 'Runtime Tests / Wokwi (Get artifacts) (${{ github.event.workflow_run.event }} -> workflow_run)', owner: owner, repo: repo, sha: sha, state: 'pending', target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' })).data; core.info(`${name} is ${state}`); - name: Download and extract event file uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} name: event_file path: artifacts/event_file - name: Download and extract matrix info uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} name: matrix_info path: artifacts/matrix_info - name: Try to read PR number id: set-ref run: | pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json | tr -cd "[:digit:]") if [ -z "$pr_num" ] || [ "$pr_num" == "null" ]; then pr_num="" fi ref=$pr_num if [ -z "$ref" ] || [ "$ref" == "null" ]; then ref=${{ github.ref }} fi action=$(jq -r '.action' artifacts/event_file/event.json | tr -cd "[:alpha:]_") if [ "$action" == "null" ]; then action="" fi base=$(jq -r '.pull_request.base.ref' artifacts/event_file/event.json | tr -cd "[:alnum:]/_.-") if [ -z "$base" ] || [ "$base" == "null" ]; then base=${{ github.ref }} fi types=$(cat artifacts/matrix_info/wokwi_types.txt | tr -cd "[:alpha:],[]'") targets=$(cat artifacts/matrix_info/targets.txt | tr -cd "[:alnum:],[]'") echo "base = $base" echo "targets = $targets" echo "types = $types" echo "pr_num = $pr_num" printf "$ref" >> artifacts/ref.txt printf "Ref = " cat artifacts/ref.txt printf "${{ github.event.workflow_run.event }}" >> artifacts/event.txt printf "\nEvent name = " cat artifacts/event.txt printf "${{ github.event.workflow_run.head_sha || github.sha }}" >> artifacts/sha.txt printf "\nHead SHA = " cat artifacts/sha.txt printf "$action" >> artifacts/action.txt printf "\nAction = " cat artifacts/action.txt printf "${{ github.event.workflow_run.id }}" >> artifacts/run_id.txt printf "\nRun ID = " cat artifacts/run_id.txt if [ -z "$ref" ] || [ "$ref" == "null" ]; then echo "Failed to get PR number or ref" exit 1 fi conclusion="${{ github.event.workflow_run.conclusion }}" printf "$conclusion" >> artifacts/conclusion.txt printf "\nConclusion = " cat artifacts/conclusion.txt echo "pr_num=$pr_num" >> $GITHUB_OUTPUT echo "base=$base" >> $GITHUB_OUTPUT echo "targets=$targets" >> $GITHUB_OUTPUT echo "types=$types" >> $GITHUB_OUTPUT echo "ref=$ref" >> $GITHUB_OUTPUT - name: Download and extract parent hardware results uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 continue-on-error: true with: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} pattern: tests-results-hw-* merge-multiple: true path: artifacts/results/hw - name: Download and extract parent QEMU results uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 continue-on-error: true with: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} pattern: tests-results-qemu-* merge-multiple: true path: artifacts/results/qemu - name: Upload parent artifacts uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: parent-artifacts path: artifacts if-no-files-found: error - name: Report conclusion uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 if: always() with: script: | const owner = '${{ github.repository_owner }}'; const repo = '${{ github.repository }}'.split('/')[1]; const sha = '${{ github.event.workflow_run.head_sha }}'; core.debug(`owner: ${owner}`); core.debug(`repo: ${repo}`); core.debug(`sha: ${sha}`); const { context: name, state } = (await github.rest.repos.createCommitStatus({ context: 'Runtime Tests / Wokwi (Get artifacts) (${{ github.event.workflow_run.event }} -> workflow_run)', owner: owner, repo: repo, sha: sha, state: '${{ job.status }}', target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' })).data; core.info(`${name} is ${state}`); wokwi-test: name: Wokwi ${{ matrix.chip }} ${{ matrix.type }} tests if: | github.event.workflow_run.conclusion == 'success' || github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'timed_out' runs-on: ubuntu-latest needs: get-artifacts env: id: ${{ needs.get-artifacts.outputs.ref }}-${{ github.event.workflow_run.head_sha || github.sha }}-${{ matrix.chip }}-${{ matrix.type }} permissions: actions: read statuses: write strategy: fail-fast: false matrix: type: ${{ fromJson(needs.get-artifacts.outputs.types) }} chip: ${{ fromJson(needs.get-artifacts.outputs.targets) }} steps: - name: Report pending uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const owner = '${{ github.repository_owner }}'; const repo = '${{ github.repository }}'.split('/')[1]; const sha = '${{ github.event.workflow_run.head_sha }}'; core.debug(`owner: ${owner}`); core.debug(`repo: ${repo}`); core.debug(`sha: ${sha}`); const { context: name, state } = (await github.rest.repos.createCommitStatus({ context: 'Runtime Tests / Wokwi (${{ matrix.type }}, ${{ matrix.chip }}) / Wokwi ${{ matrix.chip }} ${{ matrix.type }} tests (${{ github.event.workflow_run.event }} -> workflow_run)', owner: owner, repo: repo, sha: sha, state: 'pending', target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' })).data; core.info(`${name} is ${state}`); - name: Check if already passed id: get-cache-results if: needs.get-artifacts.outputs.pr_num uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: key: tests-${{ env.id }}-results-wokwi path: | tests/**/*.xml tests/**/result_*.json - name: Evaluate if tests should be run id: check-tests run: | cache_exists=${{ steps.get-cache-results.outputs.cache-hit == 'true' }} enabled=true if [[ $cache_exists == 'true' ]]; then echo "Already ran, skipping" enabled=false fi echo "enabled=$enabled" >> $GITHUB_OUTPUT # Note that changes to the workflows and tests will only be picked up after the PR is merged # DO NOT CHECKOUT THE USER'S REPOSITORY IN THIS WORKFLOW. IT HAS HIGH SECURITY RISKS. - name: Checkout repository if: ${{ steps.check-tests.outputs.enabled == 'true' }} uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ needs.get-artifacts.outputs.base || github.ref }} - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4 if: ${{ steps.check-tests.outputs.enabled == 'true' }} with: cache-dependency-path: tests/requirements.txt cache: "pip" python-version: "3.x" - name: Install dependencies if: ${{ steps.check-tests.outputs.enabled == 'true' }} run: | pip install -U pip pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi - name: Install Wokwi CLI if: ${{ steps.check-tests.outputs.enabled == 'true' }} run: curl -L https://wokwi.com/ci/install.sh | sh - name: Wokwi CI Server if: ${{ steps.check-tests.outputs.enabled == 'true' }} uses: wokwi/wokwi-ci-server-action@a6fabb5a49e080158c7a1d121ea5b789536a82c3 # v1 - name: Get binaries if: ${{ steps.check-tests.outputs.enabled == 'true' }} uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} name: tests-bin-${{ matrix.chip }}-${{ matrix.type }} path: | ~/.arduino/tests/${{ matrix.chip }} - name: Run Tests if: ${{ steps.check-tests.outputs.enabled == 'true' }} env: WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }} run: | bash .github/scripts/tests_run.sh -c -type ${{ matrix.type }} -t ${{ matrix.chip }} -i 0 -m 1 -W ${{ env.WOKWI_TIMEOUT }} - name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as cache uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 if: steps.check-tests.outputs.enabled == 'true' && needs.get-artifacts.outputs.pr_num with: key: tests-${{ env.id }}-results-wokwi path: | tests/**/*.xml tests/**/result_*.json - name: Upload ${{ matrix.chip }} ${{ matrix.type }} Wokwi results as artifacts uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: always() with: name: tests-results-wokwi-${{ matrix.chip }}-${{ matrix.type }} overwrite: true path: | tests/**/*.xml tests/**/result_*.json - name: Report conclusion uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 if: always() with: script: | const owner = '${{ github.repository_owner }}'; const repo = '${{ github.repository }}'.split('/')[1]; const sha = '${{ github.event.workflow_run.head_sha }}'; core.debug(`owner: ${owner}`); core.debug(`repo: ${repo}`); core.debug(`sha: ${sha}`); const { context: name, state } = (await github.rest.repos.createCommitStatus({ context: 'Runtime Tests / Wokwi (${{ matrix.type }}, ${{ matrix.chip }}) / Wokwi ${{ matrix.chip }} ${{ matrix.type }} tests (${{ github.event.workflow_run.event }} -> workflow_run)', owner: owner, repo: repo, sha: sha, state: '${{ job.status }}', target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' })).data; core.info(`${name} is ${state}`);