From b4a1fbff9422e9e0838fcc48fef213a8df612ead Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:42:22 -0300 Subject: [PATCH] ci(tests): Avoid the use of pull_request_target where possible --- .github/workflows/tests.yml | 137 +++------ .../{build_tests.yml => tests_build.yml} | 19 +- .github/workflows/{hw.yml => tests_hw.yml} | 21 +- .../workflows/{qemu.yml => tests_qemu.yml} | 8 +- .github/workflows/tests_results.yml | 107 +++++++ .github/workflows/tests_wokwi.yml | 289 ++++++++++++++++++ .github/workflows/wokwi.yml | 124 -------- 7 files changed, 440 insertions(+), 265 deletions(-) rename .github/workflows/{build_tests.yml => tests_build.yml} (78%) rename .github/workflows/{hw.yml => tests_hw.yml} (79%) rename .github/workflows/{qemu.yml => tests_qemu.yml} (95%) create mode 100644 .github/workflows/tests_results.yml create mode 100644 .github/workflows/tests_wokwi.yml delete mode 100644 .github/workflows/wokwi.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d5a8e267c5f..26de19d8f10 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,10 +1,29 @@ +# This file is used to run the runtime tests for the Arduino core for ESP32. +# The tests are run on the hardware, Wokwi and QEMU emulators. +# The QEMU tests are disabled for now as they are redundant with most of the Wokwi tests. +# As the Wokwi tests require access to secrets, they are run in a separate workflow. +# We need to ensure that the artifacts from previous tests in the chain are propagated for publishing the results. +# This is the current trigger sequence for the tests: +# tests.yml -> tests_wokwi.yml -> tests_results.yml +# ⌙> tests_build.yml +# ⌙> tests_hw.yml +# ⌙> tests_qemu.yml + name: Runtime Tests on: workflow_dispatch: - pull_request_target: + pull_request: types: [opened, reopened, closed, synchronize, labeled, unlabeled] paths: + - '.github/workflows/tests*' + - '.github/scripts/*.sh' + - '!.github/scripts/check-cmakelists.sh' + - '!.github/scripts/find_*' + - '!.github/scripts/on-*.sh' + - '!.github/scripts/set_push_chunks.sh' + - '!.github/scripts/update-version.sh' + - '!.github/scripts/upload_py_tools.sh' - 'tests/**' - 'cores/**' - 'libraries/**' @@ -19,14 +38,19 @@ concurrency: group: tests-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true -# To avoid giving elevated permissions to the entire workflow, specify default permissions at the top level -# and then override them for specific jobs. -permissions: { contents: read } - jobs: + push-event-file: + name: Push event file + runs-on: ubuntu-latest + steps: + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: event_file + path: ${{ github.event_path }} + gen-matrix: name: Generate matrix - if: github.event.action != 'closed' runs-on: ubuntu-latest outputs: build-types: ${{ steps.set-matrix.outputs.build-types }} @@ -59,9 +83,8 @@ jobs: call-build-tests: name: Build - uses: espressif/arduino-esp32/.github/workflows/build_tests.yml@master + uses: ./.github/workflows/tests_build.yml needs: gen-matrix - if: github.event.action != 'closed' strategy: matrix: type: ${{ fromJson(needs.gen-matrix.outputs.build-types) }} @@ -72,11 +95,11 @@ jobs: call-hardware-tests: name: Hardware - uses: espressif/arduino-esp32/.github/workflows/hw.yml@master + uses: ./.github/workflows/tests_hw.yml needs: [gen-matrix, call-build-tests] if: | github.repository == 'espressif/arduino-esp32' && - (github.event_name != 'pull_request_target' || + (github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'hil_test')) strategy: fail-fast: false @@ -87,26 +110,10 @@ jobs: type: ${{ matrix.type }} chip: ${{ matrix.chip }} - call-wokwi-tests: - name: Wokwi - uses: espressif/arduino-esp32/.github/workflows/wokwi.yml@master - needs: [gen-matrix, call-build-tests] - if: github.event.action != 'closed' - strategy: - fail-fast: false - matrix: - type: ${{ fromJson(needs.gen-matrix.outputs.wokwi-types) }} - chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] - secrets: - WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }} - with: - type: ${{ matrix.type }} - chip: ${{ matrix.chip }} - # This job is disabled for now call-qemu-tests: name: QEMU - uses: espressif/arduino-esp32/.github/workflows/qemu.yml@master + uses: ./.github/workflows/tests_qemu.yml needs: [gen-matrix, call-build-tests] if: false strategy: @@ -118,78 +125,4 @@ jobs: type: ${{ matrix.type }} chip: ${{ matrix.chip }} - unit-test-results: - name: Unit Test Results - needs: [call-hardware-tests, call-wokwi-tests, call-qemu-tests] - if: always() && github.event_name == 'pull_request_target' - runs-on: ubuntu-latest - permissions: - checks: write - pull-requests: write - steps: - - name: Download and Extract HW Artifacts - uses: actions/download-artifact@v4 - continue-on-error: true - with: - merge-multiple: true - pattern: tests-results-hw-* - path: ./results/hw - - - name: Download and Extract Wokwi Artifacts - uses: actions/download-artifact@v4 - continue-on-error: true - with: - merge-multiple: true - pattern: tests-results-wokwi-* - path: ./results/wokwi - - - name: Download and Extract QEMU Artifacts - uses: actions/download-artifact@v4 - continue-on-error: true - with: - merge-multiple: true - pattern: tests-results-qemu-* - path: ./results/qemu - - - name: Publish Unit Test Results - uses: EnricoMi/publish-unit-test-result-action@v2 - with: - commit: ${{ github.event.pull_request.head.sha || github.sha }} - files: ./results/**/*.xml - clean: - name: Clean objects - needs: unit-test-results - if: always() - permissions: - actions: write - runs-on: ubuntu-latest - steps: - - name: Clean up caches - uses: actions/github-script@v7 - with: - script: | - const ref = '${{ github.event.pull_request.number || github.ref }}'; - const key_prefix = 'tests-' + ref + '-'; - - if ('${{ github.event_name }}' == 'pull_request_target' && '${{ github.event.action }}' != 'closed') { - console.log('Skipping cache cleanup for open PR'); - return; - } - - await github.paginate(github.rest.actions.getActionsCacheList, { - owner: context.repo.owner, - repo: context.repo.repo, - per_page: 100, - key: key_prefix - }).then(caches => { - if (caches) { - for (const cache of caches) { - console.log(`Deleting cache: ${cache.key}`); - github.rest.actions.deleteActionsCacheById({ - owner: context.repo.owner, - repo: context.repo.repo, - cache_id: cache.id - }); - } - } - }); + # Wokwi tests are run after this workflow as it needs access to secrets diff --git a/.github/workflows/build_tests.yml b/.github/workflows/tests_build.yml similarity index 78% rename from .github/workflows/build_tests.yml rename to .github/workflows/tests_build.yml index b7c4ec40f1a..f865078b1c3 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/tests_build.yml @@ -20,8 +20,8 @@ jobs: id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }} steps: - name: Check if already built - if: ${{ github.event.pull_request.number != null }} id: cache-build-binaries + if: github.event.pull_request.number != null uses: actions/cache/restore@v4 with: key: tests-${{ env.id }}-bin @@ -46,21 +46,6 @@ jobs: - name: Checkout user repository if: ${{ steps.check-build.outputs.enabled == 'true' }} uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - persist-credentials: false - sparse-checkout-cone-mode: false - sparse-checkout: | - /* - !.github - - # To avoid giving unknown scripts elevated permissions, download them from the master branch - - name: Get CI scripts from master - if: ${{ steps.check-build.outputs.enabled == 'true' }} - run: | - mkdir -p .github - cd .github - curl https://codeload.github.com/${{ github.repository }}/tar.gz/master | tar -xz --strip=2 arduino-esp32-master/.github - name: Get libs cache uses: actions/cache@v4 @@ -83,7 +68,7 @@ jobs: - name: Upload ${{ inputs.chip }} ${{ inputs.type }} binaries as cache uses: actions/cache/save@v4 - if: ${{ steps.check-build.outputs.enabled == 'true' }} + if: steps.check-build.outputs.enabled == 'true' && github.event.pull_request.number != null with: key: tests-${{ env.id }}-bin path: | diff --git a/.github/workflows/hw.yml b/.github/workflows/tests_hw.yml similarity index 79% rename from .github/workflows/hw.yml rename to .github/workflows/tests_hw.yml index b401f0f3f07..e6e1f7a3251 100644 --- a/.github/workflows/hw.yml +++ b/.github/workflows/tests_hw.yml @@ -22,9 +22,9 @@ jobs: image: python:3.10.1-bullseye options: --privileged steps: - - name: Check if already built - if: ${{ github.event.pull_request.number != null }} + - name: Check if already passed id: cache-results + if: github.event.pull_request.number != null uses: actions/cache/restore@v4 with: key: tests-${{ env.id }}-results-hw @@ -48,21 +48,6 @@ jobs: - name: Checkout user repository if: ${{ steps.check-tests.outputs.enabled == 'true' }} uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - persist-credentials: false - sparse-checkout-cone-mode: false - sparse-checkout: | - /* - !.github - - # To avoid giving unknown scripts elevated permissions, download them from the master branch - - name: Get CI scripts from master - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - run: | - mkdir -p .github - cd .github - curl https://codeload.github.com/${{ github.repository }}/tar.gz/master | tar -xz --strip=2 arduino-esp32-master/.github # setup-python currently only works on ubuntu images # - uses: actions/setup-python@v5 @@ -95,7 +80,7 @@ jobs: - name: Upload ${{ inputs.chip }} ${{ inputs.type }} hardware results as cache uses: actions/cache/save@v4 - if: ${{ always() && steps.check-tests.outputs.enabled == 'true' }} + if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null with: key: tests-${{ env.id }}-results-hw path: | diff --git a/.github/workflows/qemu.yml b/.github/workflows/tests_qemu.yml similarity index 95% rename from .github/workflows/qemu.yml rename to .github/workflows/tests_qemu.yml index da31054aeef..0b4ec18e7ac 100644 --- a/.github/workflows/qemu.yml +++ b/.github/workflows/tests_qemu.yml @@ -18,9 +18,9 @@ jobs: QEMU_INSTALL_PATH: "$HOME" runs-on: ubuntu-latest steps: - - name: Check if already run - if: ${{ github.event.pull_request.number != null }} + - name: Check if already passed id: get-cache-results + if: github.event.pull_request.number != null uses: actions/cache/restore@v4 with: key: tests-${{ env.id }}-results-qemu @@ -97,7 +97,7 @@ jobs: with: path: | ~/qemu - key: qemu-${{ steps.get-qemu-version.outputs.release }}-${{ hashFiles('.github/workflows/qemu.yml') }} + key: qemu-${{ steps.get-qemu-version.outputs.release }}-${{ hashFiles('.github/workflows/tests_qemu.yml') }} - name: Download QEMU if: ${{ steps.cache-qemu.outputs.cache-hit != 'true' && steps.check-tests.outputs.enabled == 'true' }} @@ -125,7 +125,7 @@ jobs: - name: Upload ${{ inputs.chip }} ${{ inputs.type }} QEMU results as cache uses: actions/cache/save@v4 - if: ${{ always() && steps.check-tests.outputs.enabled == 'true' }} + if: steps.check-tests.outputs.enabled == 'true' && github.event.pull_request.number != null with: key: tests-${{ env.id }}-results-qemu path: | diff --git a/.github/workflows/tests_results.yml b/.github/workflows/tests_results.yml new file mode 100644 index 00000000000..1172d582954 --- /dev/null +++ b/.github/workflows/tests_results.yml @@ -0,0 +1,107 @@ +name: Publish and clean test results + +on: + workflow_run: + workflows: ["Wokwi tests"] + types: + - completed + +# No permissions by default +permissions: { contents: read } + +jobs: + unit-test-results: + name: Unit Test Results + if: | + github.event.workflow_run.conclusion == 'success' || + github.event.workflow_run.conclusion == 'failure' || + github.event.workflow_run.conclusion == 'timed_out' + runs-on: ubuntu-latest + permissions: + actions: write + statuses: write + checks: write + pull-requests: write + steps: + - name: Download and Extract Artifacts + uses: dawidd6/action-download-artifact@v6 + with: + run_id: ${{ github.event.workflow_run.id }} + path: ./artifacts + + - name: Get original info + run: | + original_event=$(cat ./artifacts/parent-artifacts/event.txt) + original_action=$(cat ./artifacts/parent-artifacts/action.txt) + original_sha=$(cat ./artifacts/parent-artifacts/sha.txt) + original_ref=$(cat ./artifacts/parent-artifacts/ref.txt) + echo "original_event=$original_event" >> $GITHUB_ENV + echo "original_action=$original_action" >> $GITHUB_ENV + echo "original_sha=$original_sha" >> $GITHUB_ENV + echo "original_ref=$original_ref" >> $GITHUB_ENV + + echo "original_event = $original_event" + echo "original_action = $original_action" + echo "original_sha = $original_sha" + echo "original_ref = $original_ref" + + - name: Publish Unit Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + with: + commit: ${{ env.original_sha }} + event_file: ./artifacts/parent-artifacts/event_file/event.json + event_name: ${{ env.original_event }} + files: ./artifacts/**/*.xml + action_fail: true + + - name: Clean up caches + uses: actions/github-script@v7 + with: + script: | + const ref = '${{ env.original_ref }}'; + const key_prefix = 'tests-' + ref + '-'; + + if ('${{ env.original_event }}' == 'pull_request' && '${{ env.original_action }}' != 'closed') { + console.log('Skipping cache cleanup for open PR'); + return; + } + + await github.paginate(github.rest.actions.getActionsCacheList, { + owner: context.repo.owner, + repo: context.repo.repo, + per_page: 100, + key: key_prefix + }).then(caches => { + if (caches) { + for (const cache of caches) { + console.log(`Deleting cache: ${cache.key}`); + github.rest.actions.deleteActionsCacheById({ + owner: context.repo.owner, + repo: context.repo.repo, + cache_id: cache.id + }); + } + } + }); + + - name: Report conclusion + uses: actions/github-script@v7 + if: always() + with: + script: | + const owner = '${{ github.repository_owner }}'; + const repo = '${{ github.repository }}'.split('/')[1]; + const sha = '${{ env.original_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 / Report results (${{ env.original_event }} -> workflow_run -> workflow_run)', + owner: owner, + repo: repo, + sha: sha, + state: '${{ job.status }}', + description: '${{ job.status }}' ? 'Runtime tests successful' : 'Runtime tests failed', + target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' + })).data; + core.info(`${name} is ${state}`); diff --git a/.github/workflows/tests_wokwi.yml b/.github/workflows/tests_wokwi.yml new file mode 100644 index 00000000000..c2b1c03d5a8 --- /dev/null +++ b/.github/workflows/tests_wokwi.yml @@ -0,0 +1,289 @@ +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 }} + steps: + - name: Report pending + uses: actions/github-script@v7 + 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@v4 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + name: event_file + path: artifacts/event_file + + - name: Try to read PR number + id: set-ref + run: | + pr_num=$(jq -r '.pull_request.number' artifacts/event_file/event.json) + 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) + if [ "$action" == "null" ]; then + action="" + fi + + 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 + + if [ -z "$ref" ] || [ "$ref" == "null" ]; then + echo "Failed to get PR number or ref" + exit 1 + fi + + echo "pr_num=$pr_num" >> $GITHUB_OUTPUT + echo "ref=$ref" >> $GITHUB_OUTPUT + + - name: Download and extract parent hardware results + uses: actions/download-artifact@v4 + 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@v4 + 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@v4 + with: + name: parent-artifacts + path: artifacts + if-no-files-found: error + + - name: Report conclusion + uses: actions/github-script@v7 + 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: ['validation'] + chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'] + steps: + - name: Report pending + uses: actions/github-script@v7 + 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@v4 + 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 + - name: Checkout repository + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + 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@v1 + + - name: Get binaries + if: ${{ steps.check-tests.outputs.enabled == 'true' }} + uses: actions/download-artifact@v4 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + name: tests-bin-${{ matrix.chip }}-${{ matrix.type }} + path: | + ~/.arduino/tests + + - 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@v4 + 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@v4 + 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@v7 + 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}`); diff --git a/.github/workflows/wokwi.yml b/.github/workflows/wokwi.yml deleted file mode 100644 index f9eee85f95f..00000000000 --- a/.github/workflows/wokwi.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: Wokwi tests - -on: - workflow_call: - inputs: - chip: - type: string - description: 'Chip to run tests for' - required: true - type: - type: string - description: 'Type of tests to run' - required: true - secrets: - WOKWI_CLI_TOKEN: - description: 'Wokwi CLI API token' - required: true - -env: - WOKWI_TIMEOUT: 600000 # Milliseconds - -jobs: - wokwi-test: - name: Wokwi ${{ inputs.chip }} ${{ inputs.type }} tests - env: - id: ${{ github.event.pull_request.number || github.ref }}-${{ github.event.pull_request.head.sha || github.sha }}-${{ inputs.chip }}-${{ inputs.type }} - runs-on: ubuntu-latest - steps: - - name: Check if already run - if: ${{ github.event.pull_request.number != null }} - id: get-cache-results - uses: actions/cache/restore@v4 - 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 - - - name: Checkout user repository - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - persist-credentials: false - sparse-checkout-cone-mode: false - sparse-checkout: | - /* - !.github - - # To avoid giving unknown scripts elevated permissions, download them from the master branch - - name: Get CI scripts from master - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - run: | - mkdir -p .github - cd .github - curl https://codeload.github.com/${{ github.repository }}/tar.gz/master | tar -xz --strip=2 arduino-esp32-master/.github - - - uses: actions/setup-python@v5 - 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@v1 - - - name: Get binaries - if: ${{ steps.check-tests.outputs.enabled == 'true' }} - uses: actions/download-artifact@v4 - with: - name: tests-bin-${{ inputs.chip }}-${{ inputs.type }} - path: | - ~/.arduino/tests - - - 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 ${{ inputs.type }} -t ${{inputs.chip}} -i 0 -m 1 -W ${{env.WOKWI_TIMEOUT}} - - - name: Upload ${{ inputs.chip }} ${{ inputs.type }} Wokwi results as cache - uses: actions/cache/save@v4 - if: ${{ always() && steps.check-tests.outputs.enabled == 'true' }} - with: - key: tests-${{ env.id }}-results-wokwi - path: | - tests/**/*.xml - tests/**/result_*.json - - - name: Upload ${{ inputs.chip }} ${{ inputs.type }} Wokwi results as artifacts - uses: actions/upload-artifact@v4 - if: always() - with: - name: tests-results-wokwi-${{ inputs.chip }}-${{ inputs.type }} - overwrite: true - path: | - tests/**/*.xml - tests/**/result_*.json