diff --git a/.github/workflows/openvmm-ci.yaml b/.github/workflows/openvmm-ci.yaml index c6a5415ea3..98de48fea6 100644 --- a/.github/workflows/openvmm-ci.yaml +++ b/.github/workflows/openvmm-ci.yaml @@ -430,7 +430,7 @@ jobs: - name: check if openvmm needs to be cloned run: |- flowey.exe e 10 flowey_lib_common::git_checkout 0 - flowey.exe v 10 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar6 + flowey.exe v 10 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar5 flowey.exe v 10 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION shell: bash - id: flowey_lib_common__git_checkout__1 @@ -438,7 +438,7 @@ jobs: with: fetch-depth: '1' path: repo0 - persist-credentials: ${{ env.floweyvar6 }} + persist-credentials: ${{ env.floweyvar5 }} name: checkout repo openvmm if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report cloned repo directories @@ -458,14 +458,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey.exe e 10 flowey_lib_common::cache 4 - flowey.exe v 10 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar4 - flowey.exe v 10 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar5 + flowey.exe v 10 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar3 + flowey.exe v 10 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar4 shell: bash - id: flowey_lib_common__cache__5 uses: actions/cache@v4 with: - key: ${{ env.floweyvar4 }} - path: ${{ env.floweyvar5 }} + key: ${{ env.floweyvar3 }} + path: ${{ env.floweyvar4 }} name: 'Restore cache: gh-release-download' - name: download artifacts from github releases run: |- @@ -508,14 +508,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey.exe e 10 flowey_lib_common::cache 0 - flowey.exe v 10 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar2 - flowey.exe v 10 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar3 + flowey.exe v 10 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar1 + flowey.exe v 10 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar2 shell: bash - id: flowey_lib_common__cache__1 uses: actions/cache@v4 with: - key: ${{ env.floweyvar2 }} - path: ${{ env.floweyvar3 }} + key: ${{ env.floweyvar1 }} + path: ${{ env.floweyvar2 }} name: 'Restore cache: cargo-nextest' - name: downloading cargo-nextest run: |- @@ -555,17 +555,7 @@ jobs: flowey.exe e 10 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 0 flowey.exe e 10 flowey_lib_common::publish_test_results 0 flowey.exe e 10 flowey_lib_common::publish_test_results 1 - flowey.exe e 10 flowey_lib_common::publish_test_results 2 - flowey.exe v 10 'flowey_lib_common::publish_test_results:4:flowey_lib_common/src/publish_test_results.rs:95:47' --is-raw-string --condvar flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43 write-to-env github floweyvar1 - flowey.exe v 10 'flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43' write-to-env github FLOWEY_CONDITION shell: bash - - id: flowey_lib_common__publish_test_results__3 - uses: actions/upload-artifact@v4 - with: - name: x64-windows-unit-tests-junit-xml - path: ${{ env.floweyvar1 }} - name: 'publish test results: x64-windows-unit-tests (JUnit XML)' - if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report test results to overall pipeline status run: flowey.exe e 10 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 1 shell: bash @@ -670,7 +660,7 @@ jobs: - name: check if openvmm needs to be cloned run: |- flowey e 11 flowey_lib_common::git_checkout 0 - flowey v 11 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar6 + flowey v 11 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar5 flowey v 11 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION shell: bash - id: flowey_lib_common__git_checkout__1 @@ -678,7 +668,7 @@ jobs: with: fetch-depth: '1' path: repo0 - persist-credentials: ${{ env.floweyvar6 }} + persist-credentials: ${{ env.floweyvar5 }} name: checkout repo openvmm if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report cloned repo directories @@ -698,14 +688,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey e 11 flowey_lib_common::cache 4 - flowey v 11 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar4 - flowey v 11 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar5 + flowey v 11 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar3 + flowey v 11 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar4 shell: bash - id: flowey_lib_common__cache__5 uses: actions/cache@v4 with: - key: ${{ env.floweyvar4 }} - path: ${{ env.floweyvar5 }} + key: ${{ env.floweyvar3 }} + path: ${{ env.floweyvar4 }} name: 'Restore cache: gh-release-download' - name: download artifacts from github releases run: |- @@ -779,14 +769,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey e 11 flowey_lib_common::cache 0 - flowey v 11 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar2 - flowey v 11 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar3 + flowey v 11 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar1 + flowey v 11 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar2 shell: bash - id: flowey_lib_common__cache__1 uses: actions/cache@v4 with: - key: ${{ env.floweyvar2 }} - path: ${{ env.floweyvar3 }} + key: ${{ env.floweyvar1 }} + path: ${{ env.floweyvar2 }} name: 'Restore cache: cargo-nextest' - name: downloading cargo-nextest run: |- @@ -831,17 +821,7 @@ jobs: flowey e 11 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 0 flowey e 11 flowey_lib_common::publish_test_results 0 flowey e 11 flowey_lib_common::publish_test_results 1 - flowey e 11 flowey_lib_common::publish_test_results 2 - flowey v 11 'flowey_lib_common::publish_test_results:4:flowey_lib_common/src/publish_test_results.rs:95:47' --is-raw-string --condvar flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43 write-to-env github floweyvar1 - flowey v 11 'flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43' write-to-env github FLOWEY_CONDITION shell: bash - - id: flowey_lib_common__publish_test_results__3 - uses: actions/upload-artifact@v4 - with: - name: x64-linux-unit-tests-junit-xml - path: ${{ env.floweyvar1 }} - name: 'publish test results: x64-linux-unit-tests (JUnit XML)' - if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report test results to overall pipeline status run: flowey e 11 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 1 shell: bash @@ -946,7 +926,7 @@ jobs: - name: check if openvmm needs to be cloned run: |- flowey e 12 flowey_lib_common::git_checkout 0 - flowey v 12 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar6 + flowey v 12 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar5 flowey v 12 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION shell: bash - id: flowey_lib_common__git_checkout__1 @@ -954,7 +934,7 @@ jobs: with: fetch-depth: '1' path: repo0 - persist-credentials: ${{ env.floweyvar6 }} + persist-credentials: ${{ env.floweyvar5 }} name: checkout repo openvmm if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report cloned repo directories @@ -978,14 +958,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey e 12 flowey_lib_common::cache 4 - flowey v 12 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar4 - flowey v 12 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar5 + flowey v 12 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar3 + flowey v 12 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar4 shell: bash - id: flowey_lib_common__cache__5 uses: actions/cache@v4 with: - key: ${{ env.floweyvar4 }} - path: ${{ env.floweyvar5 }} + key: ${{ env.floweyvar3 }} + path: ${{ env.floweyvar4 }} name: 'Restore cache: gh-release-download' - name: download artifacts from github releases run: |- @@ -1046,14 +1026,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey e 12 flowey_lib_common::cache 0 - flowey v 12 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar2 - flowey v 12 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar3 + flowey v 12 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar1 + flowey v 12 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar2 shell: bash - id: flowey_lib_common__cache__1 uses: actions/cache@v4 with: - key: ${{ env.floweyvar2 }} - path: ${{ env.floweyvar3 }} + key: ${{ env.floweyvar1 }} + path: ${{ env.floweyvar2 }} name: 'Restore cache: cargo-nextest' - name: downloading cargo-nextest run: |- @@ -1098,17 +1078,7 @@ jobs: flowey e 12 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 0 flowey e 12 flowey_lib_common::publish_test_results 0 flowey e 12 flowey_lib_common::publish_test_results 1 - flowey e 12 flowey_lib_common::publish_test_results 2 - flowey v 12 'flowey_lib_common::publish_test_results:4:flowey_lib_common/src/publish_test_results.rs:95:47' --is-raw-string --condvar flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43 write-to-env github floweyvar1 - flowey v 12 'flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43' write-to-env github FLOWEY_CONDITION shell: bash - - id: flowey_lib_common__publish_test_results__3 - uses: actions/upload-artifact@v4 - with: - name: x64-linux-musl-unit-tests-junit-xml - path: ${{ env.floweyvar1 }} - name: 'publish test results: x64-linux-musl-unit-tests (JUnit XML)' - if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report test results to overall pipeline status run: flowey e 12 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 1 shell: bash @@ -1210,7 +1180,7 @@ jobs: - name: check if openvmm needs to be cloned run: |- flowey.exe e 13 flowey_lib_common::git_checkout 0 - flowey.exe v 13 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar6 + flowey.exe v 13 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar5 flowey.exe v 13 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION shell: bash - id: flowey_lib_common__git_checkout__1 @@ -1218,7 +1188,7 @@ jobs: with: fetch-depth: '1' path: repo0 - persist-credentials: ${{ env.floweyvar6 }} + persist-credentials: ${{ env.floweyvar5 }} name: checkout repo openvmm if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report cloned repo directories @@ -1238,14 +1208,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey.exe e 13 flowey_lib_common::cache 4 - flowey.exe v 13 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar4 - flowey.exe v 13 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar5 + flowey.exe v 13 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar3 + flowey.exe v 13 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar4 shell: bash - id: flowey_lib_common__cache__5 uses: actions/cache@v4 with: - key: ${{ env.floweyvar4 }} - path: ${{ env.floweyvar5 }} + key: ${{ env.floweyvar3 }} + path: ${{ env.floweyvar4 }} name: 'Restore cache: gh-release-download' - name: download artifacts from github releases run: |- @@ -1288,14 +1258,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey.exe e 13 flowey_lib_common::cache 0 - flowey.exe v 13 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar2 - flowey.exe v 13 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar3 + flowey.exe v 13 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar1 + flowey.exe v 13 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar2 shell: bash - id: flowey_lib_common__cache__1 uses: actions/cache@v4 with: - key: ${{ env.floweyvar2 }} - path: ${{ env.floweyvar3 }} + key: ${{ env.floweyvar1 }} + path: ${{ env.floweyvar2 }} name: 'Restore cache: cargo-nextest' - name: downloading cargo-nextest run: |- @@ -1335,17 +1305,7 @@ jobs: flowey.exe e 13 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 0 flowey.exe e 13 flowey_lib_common::publish_test_results 0 flowey.exe e 13 flowey_lib_common::publish_test_results 1 - flowey.exe e 13 flowey_lib_common::publish_test_results 2 - flowey.exe v 13 'flowey_lib_common::publish_test_results:4:flowey_lib_common/src/publish_test_results.rs:95:47' --is-raw-string --condvar flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43 write-to-env github floweyvar1 - flowey.exe v 13 'flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43' write-to-env github FLOWEY_CONDITION shell: bash - - id: flowey_lib_common__publish_test_results__3 - uses: actions/upload-artifact@v4 - with: - name: aarch64-windows-unit-tests-junit-xml - path: ${{ env.floweyvar1 }} - name: 'publish test results: aarch64-windows-unit-tests (JUnit XML)' - if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report test results to overall pipeline status run: flowey.exe e 13 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 1 shell: bash @@ -1453,7 +1413,7 @@ jobs: - name: check if openvmm needs to be cloned run: |- flowey e 14 flowey_lib_common::git_checkout 0 - flowey v 14 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar6 + flowey v 14 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar5 flowey v 14 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION shell: bash - id: flowey_lib_common__git_checkout__1 @@ -1461,7 +1421,7 @@ jobs: with: fetch-depth: '1' path: repo0 - persist-credentials: ${{ env.floweyvar6 }} + persist-credentials: ${{ env.floweyvar5 }} name: checkout repo openvmm if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report cloned repo directories @@ -1481,14 +1441,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey e 14 flowey_lib_common::cache 4 - flowey v 14 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar4 - flowey v 14 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar5 + flowey v 14 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar3 + flowey v 14 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar4 shell: bash - id: flowey_lib_common__cache__5 uses: actions/cache@v4 with: - key: ${{ env.floweyvar4 }} - path: ${{ env.floweyvar5 }} + key: ${{ env.floweyvar3 }} + path: ${{ env.floweyvar4 }} name: 'Restore cache: gh-release-download' - name: download artifacts from github releases run: |- @@ -1536,14 +1496,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey e 14 flowey_lib_common::cache 0 - flowey v 14 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar2 - flowey v 14 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar3 + flowey v 14 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar1 + flowey v 14 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar2 shell: bash - id: flowey_lib_common__cache__1 uses: actions/cache@v4 with: - key: ${{ env.floweyvar2 }} - path: ${{ env.floweyvar3 }} + key: ${{ env.floweyvar1 }} + path: ${{ env.floweyvar2 }} name: 'Restore cache: cargo-nextest' - name: downloading cargo-nextest run: |- @@ -1588,17 +1548,7 @@ jobs: flowey e 14 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 0 flowey e 14 flowey_lib_common::publish_test_results 0 flowey e 14 flowey_lib_common::publish_test_results 1 - flowey e 14 flowey_lib_common::publish_test_results 2 - flowey v 14 'flowey_lib_common::publish_test_results:4:flowey_lib_common/src/publish_test_results.rs:95:47' --is-raw-string --condvar flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43 write-to-env github floweyvar1 - flowey v 14 'flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43' write-to-env github FLOWEY_CONDITION shell: bash - - id: flowey_lib_common__publish_test_results__3 - uses: actions/upload-artifact@v4 - with: - name: aarch64-linux-unit-tests-junit-xml - path: ${{ env.floweyvar1 }} - name: 'publish test results: aarch64-linux-unit-tests (JUnit XML)' - if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report test results to overall pipeline status run: flowey e 14 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 1 shell: bash @@ -1700,7 +1650,7 @@ jobs: - name: check if openvmm needs to be cloned run: |- flowey e 15 flowey_lib_common::git_checkout 0 - flowey v 15 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar6 + flowey v 15 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar5 flowey v 15 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION shell: bash - id: flowey_lib_common__git_checkout__1 @@ -1708,7 +1658,7 @@ jobs: with: fetch-depth: '1' path: repo0 - persist-credentials: ${{ env.floweyvar6 }} + persist-credentials: ${{ env.floweyvar5 }} name: checkout repo openvmm if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report cloned repo directories @@ -1732,14 +1682,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey e 15 flowey_lib_common::cache 4 - flowey v 15 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar4 - flowey v 15 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar5 + flowey v 15 'flowey_lib_common::cache:10:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar3 + flowey v 15 'flowey_lib_common::cache:9:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar4 shell: bash - id: flowey_lib_common__cache__5 uses: actions/cache@v4 with: - key: ${{ env.floweyvar4 }} - path: ${{ env.floweyvar5 }} + key: ${{ env.floweyvar3 }} + path: ${{ env.floweyvar4 }} name: 'Restore cache: gh-release-download' - name: download artifacts from github releases run: |- @@ -1800,14 +1750,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey e 15 flowey_lib_common::cache 0 - flowey v 15 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar2 - flowey v 15 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar3 + flowey v 15 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar1 + flowey v 15 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar2 shell: bash - id: flowey_lib_common__cache__1 uses: actions/cache@v4 with: - key: ${{ env.floweyvar2 }} - path: ${{ env.floweyvar3 }} + key: ${{ env.floweyvar1 }} + path: ${{ env.floweyvar2 }} name: 'Restore cache: cargo-nextest' - name: downloading cargo-nextest run: |- @@ -1852,17 +1802,7 @@ jobs: flowey e 15 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 0 flowey e 15 flowey_lib_common::publish_test_results 0 flowey e 15 flowey_lib_common::publish_test_results 1 - flowey e 15 flowey_lib_common::publish_test_results 2 - flowey v 15 'flowey_lib_common::publish_test_results:4:flowey_lib_common/src/publish_test_results.rs:95:47' --is-raw-string --condvar flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43 write-to-env github floweyvar1 - flowey v 15 'flowey_lib_common::publish_test_results:0:flowey_lib_common/src/publish_test_results.rs:77:43' write-to-env github FLOWEY_CONDITION shell: bash - - id: flowey_lib_common__publish_test_results__3 - uses: actions/upload-artifact@v4 - with: - name: aarch64-linux-musl-unit-tests-junit-xml - path: ${{ env.floweyvar1 }} - name: 'publish test results: aarch64-linux-musl-unit-tests (JUnit XML)' - if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report test results to overall pipeline status run: flowey e 15 flowey_lib_hvlite::_jobs::build_and_run_nextest_unit_tests 1 shell: bash @@ -1912,6 +1852,12 @@ jobs: cat <<'EOF' | flowey.exe v 16 'verbose' update ${{ inputs.verbose != '' && inputs.verbose || 'false' }} EOF + mkdir -p "$AgentTempDirNormal/publish_artifacts/x64-windows-intel-vmm-tests-results" + echo "${{ runner.temp }}\\publish_artifacts\\x64-windows-intel-vmm-tests-results" | flowey.exe v 16 'artifact_publish_from_x64-windows-intel-vmm-tests-results' --is-raw-string update + mkdir -p "$AgentTempDirNormal/publish_artifacts/x64-windows-intel-vmm-tests-results-junit-xml" + echo "${{ runner.temp }}\\publish_artifacts\\x64-windows-intel-vmm-tests-results-junit-xml" | flowey.exe v 16 'artifact_publish_from_x64-windows-intel-vmm-tests-results-junit-xml' --is-raw-string update + mkdir -p "$AgentTempDirNormal/publish_artifacts/x64-windows-intel-vmm-tests-results-nextest-list-json" + echo "${{ runner.temp }}\\publish_artifacts\\x64-windows-intel-vmm-tests-results-nextest-list-json" | flowey.exe v 16 'artifact_publish_from_x64-windows-intel-vmm-tests-results-nextest-list-json' --is-raw-string update echo "${{ runner.temp }}\\used_artifacts\\x64-guest_test_uefi" | flowey.exe v 16 'artifact_use_from_x64-guest_test_uefi' --is-raw-string update echo "${{ runner.temp }}\\used_artifacts\\x64-linux-musl-pipette" | flowey.exe v 16 'artifact_use_from_x64-linux-musl-pipette' --is-raw-string update echo "${{ runner.temp }}\\used_artifacts\\x64-linux-musl-tmk_vmm" | flowey.exe v 16 'artifact_use_from_x64-linux-musl-tmk_vmm' --is-raw-string update @@ -1949,14 +1895,14 @@ jobs: - name: Pre-processing cache vars run: |- flowey.exe e 16 flowey_lib_common::cache 0 - flowey.exe v 16 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar4 - flowey.exe v 16 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar5 + flowey.exe v 16 'flowey_lib_common::cache:2:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar2 + flowey.exe v 16 'flowey_lib_common::cache:1:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar3 shell: bash - id: flowey_lib_common__cache__1 uses: actions/cache@v4 with: - key: ${{ env.floweyvar4 }} - path: ${{ env.floweyvar5 }} + key: ${{ env.floweyvar2 }} + path: ${{ env.floweyvar3 }} name: 'Restore cache: azcopy' - name: installing azcopy run: |- @@ -1979,11 +1925,11 @@ jobs: shell: bash - name: Pre-processing cache vars run: |- - flowey.exe e 16 flowey_lib_common::cache 8 - flowey.exe v 16 'flowey_lib_common::cache:18:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar8 - flowey.exe v 16 'flowey_lib_common::cache:17:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar9 + flowey.exe e 16 flowey_lib_common::cache 12 + flowey.exe v 16 'flowey_lib_common::cache:26:flowey_lib_common/src/cache.rs:407:72' --is-raw-string write-to-env github floweyvar8 + flowey.exe v 16 'flowey_lib_common::cache:25:flowey_lib_common/src/cache.rs:406:72' --is-raw-string write-to-env github floweyvar9 shell: bash - - id: flowey_lib_common__cache__9 + - id: flowey_lib_common__cache__13 uses: actions/cache@v4 with: key: ${{ env.floweyvar8 }} @@ -1991,10 +1937,10 @@ jobs: name: 'Restore cache: gh-cli' - name: installing gh run: |- - flowey.exe v 16 'flowey_lib_common::cache:20:flowey_lib_common/src/cache.rs:462:70' --is-raw-string update --env-source steps.flowey_lib_common__cache__9.outputs.cache-hit <> $GITHUB_PATH + shell: bash + name: πŸŒΌπŸ“¦ Add flowey to PATH + - name: πŸŒΌπŸ›« Initialize job + run: | + AgentTempDirNormal="${{ runner.temp }}" + AgentTempDirNormal=$(echo "$AgentTempDirNormal" | sed -e 's|\\|\/|g' -e 's|^\([A-Za-z]\)\:/\(.*\)|/\L\1\E/\2|') + echo "AgentTempDirNormal=$AgentTempDirNormal" >> $GITHUB_ENV + + chmod +x $AgentTempDirNormal/used_artifacts/_internal-flowey-bootstrap-x86_64-linux-uid-8/flowey + + echo '"debug"' | flowey v 22 'FLOWEY_LOG' update + echo "${{ runner.temp }}/work" | flowey v 22 '_internal_WORKING_DIR' --is-raw-string update + + cat <<'EOF' | flowey v 22 'verbose' update + ${{ inputs.verbose != '' && inputs.verbose || 'false' }} + EOF + echo "$AgentTempDirNormal/used_artifacts/aarch64-windows-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_aarch64-windows-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/aarch64-windows-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_aarch64-windows-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-linux-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_x64-linux-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-linux-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_x64-linux-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-snp-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_x64-windows-amd-snp-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-snp-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_x64-windows-amd-snp-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_x64-windows-amd-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_x64-windows-amd-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-tdx-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_x64-windows-intel-tdx-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-tdx-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_x64-windows-intel-tdx-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_x64-windows-intel-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_x64-windows-intel-vmm-tests-results-nextest-list-json' --is-raw-string update + shell: bash + - name: parse and analyze junit logs and nextest list output + run: flowey e 22 flowey_lib_hvlite::_jobs::verify_all_tests_run 0 + shell: bash + job23: name: test flowey local backend runs-on: ubuntu-latest permissions: @@ -3868,18 +4191,18 @@ jobs: chmod +x $AgentTempDirNormal/bootstrapped-flowey/flowey - echo '"debug"' | flowey v 22 'FLOWEY_LOG' update - echo "${{ runner.temp }}/work" | flowey v 22 '_internal_WORKING_DIR' --is-raw-string update + echo '"debug"' | flowey v 23 'FLOWEY_LOG' update + echo "${{ runner.temp }}/work" | flowey v 23 '_internal_WORKING_DIR' --is-raw-string update - cat <<'EOF' | flowey v 22 'verbose' update + cat <<'EOF' | flowey v 23 'verbose' update ${{ inputs.verbose != '' && inputs.verbose || 'false' }} EOF shell: bash - name: check if openvmm needs to be cloned run: |- - flowey e 22 flowey_lib_common::git_checkout 0 - flowey v 22 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar1 - flowey v 22 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION + flowey e 23 flowey_lib_common::git_checkout 0 + flowey v 23 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar1 + flowey v 23 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION shell: bash - id: flowey_lib_common__git_checkout__1 uses: actions/checkout@v4 @@ -3891,24 +4214,24 @@ jobs: if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report cloned repo directories run: |- - flowey v 22 'flowey_lib_common::git_checkout:4:flowey_core/src/node/github_context.rs:55:41' --is-raw-string update --env-source github.workspace <> $GITHUB_PATH + shell: bash + name: πŸŒΌπŸ“¦ Add flowey to PATH + - name: πŸŒΌπŸ›« Initialize job + run: | + AgentTempDirNormal="${{ runner.temp }}" + AgentTempDirNormal=$(echo "$AgentTempDirNormal" | sed -e 's|\\|\/|g' -e 's|^\([A-Za-z]\)\:/\(.*\)|/\L\1\E/\2|') + echo "AgentTempDirNormal=$AgentTempDirNormal" >> $GITHUB_ENV + + chmod +x $AgentTempDirNormal/used_artifacts/_internal-flowey-bootstrap-x86_64-linux-uid-8/flowey + + echo '"debug"' | flowey v 22 'FLOWEY_LOG' update + echo "${{ runner.temp }}/work" | flowey v 22 '_internal_WORKING_DIR' --is-raw-string update + + cat <<'EOF' | flowey v 22 'verbose' update + ${{ inputs.verbose != '' && inputs.verbose || 'false' }} + EOF + echo "$AgentTempDirNormal/used_artifacts/aarch64-windows-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_aarch64-windows-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/aarch64-windows-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_aarch64-windows-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-linux-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_x64-linux-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-linux-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_x64-linux-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-snp-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_x64-windows-amd-snp-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-snp-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_x64-windows-amd-snp-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_x64-windows-amd-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_x64-windows-amd-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-tdx-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_x64-windows-intel-tdx-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-tdx-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_x64-windows-intel-tdx-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-vmm-tests-results-junit-xml" | flowey v 22 'artifact_use_from_x64-windows-intel-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-vmm-tests-results-nextest-list-json" | flowey v 22 'artifact_use_from_x64-windows-intel-vmm-tests-results-nextest-list-json' --is-raw-string update + shell: bash + - name: parse and analyze junit logs and nextest list output + run: flowey e 22 flowey_lib_hvlite::_jobs::verify_all_tests_run 0 + shell: bash + job23: name: test flowey local backend runs-on: ubuntu-latest permissions: @@ -3877,18 +4200,18 @@ jobs: chmod +x $AgentTempDirNormal/bootstrapped-flowey/flowey - echo '"debug"' | flowey v 22 'FLOWEY_LOG' update - echo "${{ runner.temp }}/work" | flowey v 22 '_internal_WORKING_DIR' --is-raw-string update + echo '"debug"' | flowey v 23 'FLOWEY_LOG' update + echo "${{ runner.temp }}/work" | flowey v 23 '_internal_WORKING_DIR' --is-raw-string update - cat <<'EOF' | flowey v 22 'verbose' update + cat <<'EOF' | flowey v 23 'verbose' update ${{ inputs.verbose != '' && inputs.verbose || 'false' }} EOF shell: bash - name: check if openvmm needs to be cloned run: |- - flowey e 22 flowey_lib_common::git_checkout 0 - flowey v 22 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar1 - flowey v 22 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION + flowey e 23 flowey_lib_common::git_checkout 0 + flowey v 23 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar1 + flowey v 23 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION shell: bash - id: flowey_lib_common__git_checkout__1 uses: actions/checkout@v4 @@ -3900,24 +4223,24 @@ jobs: if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report cloned repo directories run: |- - flowey v 22 'flowey_lib_common::git_checkout:4:flowey_core/src/node/github_context.rs:55:41' --is-raw-string update --env-source github.workspace <> $GITHUB_PATH + shell: bash + name: πŸŒΌπŸ“¦ Add flowey to PATH + - name: πŸŒΌπŸ›« Initialize job + run: | + AgentTempDirNormal="${{ runner.temp }}" + AgentTempDirNormal=$(echo "$AgentTempDirNormal" | sed -e 's|\\|\/|g' -e 's|^\([A-Za-z]\)\:/\(.*\)|/\L\1\E/\2|') + echo "AgentTempDirNormal=$AgentTempDirNormal" >> $GITHUB_ENV + + chmod +x $AgentTempDirNormal/used_artifacts/_internal-flowey-bootstrap-x86_64-linux-uid-9/flowey + + echo '"debug"' | flowey v 24 'FLOWEY_LOG' update + echo "${{ runner.temp }}/work" | flowey v 24 '_internal_WORKING_DIR' --is-raw-string update + + cat <<'EOF' | flowey v 24 'verbose' update + ${{ inputs.verbose != '' && inputs.verbose || 'false' }} + EOF + echo "$AgentTempDirNormal/used_artifacts/aarch64-windows-vmm-tests-results-junit-xml" | flowey v 24 'artifact_use_from_aarch64-windows-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/aarch64-windows-vmm-tests-results-nextest-list-json" | flowey v 24 'artifact_use_from_aarch64-windows-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-linux-vmm-tests-results-junit-xml" | flowey v 24 'artifact_use_from_x64-linux-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-linux-vmm-tests-results-nextest-list-json" | flowey v 24 'artifact_use_from_x64-linux-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-snp-vmm-tests-results-junit-xml" | flowey v 24 'artifact_use_from_x64-windows-amd-snp-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-snp-vmm-tests-results-nextest-list-json" | flowey v 24 'artifact_use_from_x64-windows-amd-snp-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-vmm-tests-results-junit-xml" | flowey v 24 'artifact_use_from_x64-windows-amd-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-amd-vmm-tests-results-nextest-list-json" | flowey v 24 'artifact_use_from_x64-windows-amd-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-tdx-vmm-tests-results-junit-xml" | flowey v 24 'artifact_use_from_x64-windows-intel-tdx-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-tdx-vmm-tests-results-nextest-list-json" | flowey v 24 'artifact_use_from_x64-windows-intel-tdx-vmm-tests-results-nextest-list-json' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-vmm-tests-results-junit-xml" | flowey v 24 'artifact_use_from_x64-windows-intel-vmm-tests-results-junit-xml' --is-raw-string update + echo "$AgentTempDirNormal/used_artifacts/x64-windows-intel-vmm-tests-results-nextest-list-json" | flowey v 24 'artifact_use_from_x64-windows-intel-vmm-tests-results-nextest-list-json' --is-raw-string update + shell: bash + - name: parse and analyze junit logs and nextest list output + run: flowey e 24 flowey_lib_hvlite::_jobs::verify_all_tests_run 0 + shell: bash + job25: name: test flowey local backend runs-on: ubuntu-latest permissions: @@ -4543,18 +4866,18 @@ jobs: chmod +x $AgentTempDirNormal/bootstrapped-flowey/flowey - echo '"debug"' | flowey v 24 'FLOWEY_LOG' update - echo "${{ runner.temp }}/work" | flowey v 24 '_internal_WORKING_DIR' --is-raw-string update + echo '"debug"' | flowey v 25 'FLOWEY_LOG' update + echo "${{ runner.temp }}/work" | flowey v 25 '_internal_WORKING_DIR' --is-raw-string update - cat <<'EOF' | flowey v 24 'verbose' update + cat <<'EOF' | flowey v 25 'verbose' update ${{ inputs.verbose != '' && inputs.verbose || 'false' }} EOF shell: bash - name: check if openvmm needs to be cloned run: |- - flowey e 24 flowey_lib_common::git_checkout 0 - flowey v 24 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar1 - flowey v 24 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION + flowey e 25 flowey_lib_common::git_checkout 0 + flowey v 25 'flowey_lib_common::git_checkout:0:flowey_lib_common/src/git_checkout.rs:469:80' --is-raw-string --condvar flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46 write-to-env github floweyvar1 + flowey v 25 'flowey_lib_common::git_checkout:1:flowey_lib_common/src/git_checkout.rs:470:46' write-to-env github FLOWEY_CONDITION shell: bash - id: flowey_lib_common__git_checkout__1 uses: actions/checkout@v4 @@ -4566,26 +4889,26 @@ jobs: if: ${{ fromJSON(env.FLOWEY_CONDITION) }} - name: report cloned repo directories run: |- - flowey v 24 'flowey_lib_common::git_checkout:4:flowey_core/src/node/github_context.rs:55:41' --is-raw-string update --env-source github.workspace <, // correspond to injected download nodes at the start of the job - pub artifacts_used: Vec, + pub artifacts_used: Vec, // correspond to injected publish nodes at the end of the job - pub artifacts_published: Vec, + pub artifacts_published: Vec, } pub fn resolve_pipeline(pipeline: Pipeline) -> anyhow::Result { @@ -113,6 +120,7 @@ pub fn resolve_pipeline(pipeline: Pipeline) -> anyhow::Result name, published_by_job, used_by_jobs, + force_published: _, } in &artifacts { let no_existing = m @@ -185,16 +193,21 @@ pub fn resolve_pipeline(pipeline: Pipeline) -> anyhow::Result let artifacts_published: Vec<_> = artifacts_published .into_iter() - .map(|a| ResolvedJobArtifact { - flowey_var: flowey_core::pipeline::internal::consistent_artifact_runtime_var_name( - &a, false, - ), - name: a, + .map(|a| { + let artifact_meta = artifacts.iter().find(|meta| meta.name == a).unwrap(); + ResolvedPublishedArtifact { + flowey_var: + flowey_core::pipeline::internal::consistent_artifact_runtime_var_name( + &a, false, + ), + name: a, + force_upload: artifact_meta.force_published, + } }) .collect(); let artifacts_used: Vec<_> = artifacts_used .into_iter() - .map(|a| ResolvedJobArtifact { + .map(|a| ResolvedUsedArtifact { flowey_var: flowey_core::pipeline::internal::consistent_artifact_runtime_var_name( &a, true, ), @@ -248,6 +261,7 @@ pub fn resolve_pipeline(pipeline: Pipeline) -> anyhow::Result name: _, published_by_job, used_by_jobs, + force_published: _, } in artifacts { let published_idx = job_graph_idx[published_by_job.expect("checked in loop above")]; diff --git a/flowey/flowey_cli/src/pipeline_resolver/github_yaml/mod.rs b/flowey/flowey_cli/src/pipeline_resolver/github_yaml/mod.rs index 55ae5e170e..ba6f3f942c 100644 --- a/flowey/flowey_cli/src/pipeline_resolver/github_yaml/mod.rs +++ b/flowey/flowey_cli/src/pipeline_resolver/github_yaml/mod.rs @@ -6,8 +6,9 @@ use super::common_yaml::BashCommands; use super::common_yaml::check_generated_yaml_and_json; use super::common_yaml::write_generated_yaml_and_json; -use super::generic::ResolvedJobArtifact; use super::generic::ResolvedJobUseParameter; +use super::generic::ResolvedPublishedArtifact; +use super::generic::ResolvedUsedArtifact; use crate::cli::exec_snippet::FloweyPipelineStaticDb; use crate::cli::exec_snippet::VAR_DB_SEEDVAR_FLOWEY_WORKING_DIR; use crate::cli::pipeline::CheckMode; @@ -375,7 +376,10 @@ EOF // next, emit GitHub steps to create dirs for artifacts which will be // published - for ResolvedJobArtifact { flowey_var, name } in artifacts_published { + for ResolvedPublishedArtifact { + flowey_var, name, .. + } in artifacts_published + { writeln!( flowey_bootstrap_bash, r#"mkdir -p "$AgentTempDirNormal/publish_artifacts/{name}""# @@ -399,7 +403,7 @@ EOF // lastly, emit GitHub steps that report the dirs for any artifacts which // are used by this job - for ResolvedJobArtifact { flowey_var, name } in artifacts_used { + for ResolvedUsedArtifact { flowey_var, name } in artifacts_used { let var_db_inject_cmd = bootstrap_bash_var_db_inject(flowey_var, true); match platform.kind() { FlowPlatformKind::Windows => { @@ -434,13 +438,14 @@ EOF // ..and once that's done, the last order of business is to emit some // GitHub steps to publish the various artifacts created by this job - for ResolvedJobArtifact { + for ResolvedPublishedArtifact { flowey_var: _, name, + force_upload, } in artifacts_published { gh_steps.push({ - let map: serde_yaml::Mapping = serde_yaml::from_str(&format!( + let mut map: serde_yaml::Mapping = serde_yaml::from_str(&format!( r#" name: πŸŒΌπŸ“¦ Publish {name} uses: actions/upload-artifact@v4 @@ -451,6 +456,9 @@ EOF "# )) .unwrap(); + if *force_upload { + map.insert("if".into(), serde_yaml::Value::String("always()".into())); + } map.into() }); } diff --git a/flowey/flowey_core/src/pipeline.rs b/flowey/flowey_core/src/pipeline.rs index 11a67b4506..866c16d542 100644 --- a/flowey/flowey_core/src/pipeline.rs +++ b/flowey/flowey_core/src/pipeline.rs @@ -640,6 +640,7 @@ impl Pipeline { name: owned_name, published_by_job: None, used_by_jobs: BTreeSet::new(), + force_published: false, }); (PublishArtifact { idx }, UseArtifact { idx }) @@ -659,6 +660,30 @@ impl Pipeline { ) } + /// Mark an artifact to be force published, meaning it will be published + /// even if the job fails. + /// + /// This is useful for artifacts that contain diagnostic information or logs + /// that are needed to debug failures. + #[track_caller] + pub fn force_publish_artifact(&mut self, artifact: &PublishArtifact) -> &mut Self { + self.artifacts[artifact.idx].force_published = true; + self + } + + /// Mark a typed artifact to be force published, meaning it will be published + /// even if the job fails. + /// + /// This is useful for artifacts that contain diagnostic information or logs + /// that are needed to debug failures. + #[track_caller] + pub fn force_publish_typed_artifact( + &mut self, + artifact: &PublishTypedArtifact, + ) -> &mut Self { + self.force_publish_artifact(&artifact.0) + } + /// (ADO only) Set the pipeline-level name. /// /// @@ -1341,6 +1366,7 @@ pub mod internal { pub name: String, pub published_by_job: Option, pub used_by_jobs: BTreeSet, + pub force_published: bool, } #[derive(Debug)] diff --git a/flowey/flowey_hvlite/src/pipelines/checkin_gates.rs b/flowey/flowey_hvlite/src/pipelines/checkin_gates.rs index a9c83dbec7..6a77c77151 100644 --- a/flowey/flowey_hvlite/src/pipelines/checkin_gates.rs +++ b/flowey/flowey_hvlite/src/pipelines/checkin_gates.rs @@ -971,6 +971,8 @@ impl IntoPipeline for CheckinGatesCli { KnownTestArtifacts::Ubuntu2504ServerX64Vhd, ]; + let mut vmm_tests_results_artifacts = vec![]; + for VmmTestJobParams { platform, arch, @@ -1056,11 +1058,22 @@ impl IntoPipeline for CheckinGatesCli { ] { let test_label = format!("{label}-vmm-tests"); - let pub_vmm_tests_results = if matches!(backend_hint, PipelineBackendHint::Local) { - Some(pipeline.new_artifact(&test_label).0) - } else { - None - }; + let (pub_vmm_tests_results_full, _) = + pipeline.new_artifact(format!("{label}-vmm-tests-results")); + + let (pub_vmm_tests_junit_xml, use_vmm_tests_junit_xml) = + pipeline.new_artifact(format!("{label}-vmm-tests-results-junit-xml")); + let (pub_vmm_tests_nextest_list_json, use_vmm_tests_nextest_list_json) = + pipeline.new_artifact(format!("{label}-vmm-tests-results-nextest-list-json")); + + pipeline.force_publish_artifact(&pub_vmm_tests_results_full); + pipeline.force_publish_artifact(&pub_vmm_tests_junit_xml); + pipeline.force_publish_artifact(&pub_vmm_tests_nextest_list_json); + + vmm_tests_results_artifacts.push(( + label.to_string(), + (use_vmm_tests_junit_xml, use_vmm_tests_nextest_list_json), + )); let use_vmm_tests_archive = match target { CommonTriple::X86_64_WINDOWS_MSVC => &use_vmm_tests_archive_windows_x86, @@ -1083,7 +1096,13 @@ impl IntoPipeline for CheckinGatesCli { dep_artifact_dirs: resolve_vmm_tests_artifacts(ctx), test_artifacts, fail_job_on_test_fail: true, - artifact_dir: pub_vmm_tests_results.map(|x| ctx.publish_artifact(x)), + artifacts_to_publish: Some( + flowey_lib_hvlite::_jobs::consume_and_test_nextest_vmm_tests_archive::VmmTestsPublishArtifacts { + junit_xml: ctx.publish_artifact(pub_vmm_tests_junit_xml), + nextest_list_json: ctx.publish_artifact(pub_vmm_tests_nextest_list_json), + test_logs_dir: ctx.publish_artifact(pub_vmm_tests_results_full), + } + ), needs_prep_run, done: ctx.new_done_handle(), } @@ -1100,6 +1119,35 @@ impl IntoPipeline for CheckinGatesCli { all_jobs.push(vmm_tests_run_job.finish()); } + { + let job = pipeline + .new_job( + FlowPlatform::Linux(FlowPlatformLinuxDistro::Ubuntu), + FlowArch::X86_64, + "verify all tests run at least once", + ) + .gh_set_pool(crate::pipelines_shared::gh_pools::gh_hosted_x64_linux()) + .dep_on( + |ctx| flowey_lib_hvlite::_jobs::verify_all_tests_run::Request { + test_artifacts: vmm_tests_results_artifacts + .iter() + .map(|elem| { + ( + elem.0.clone(), + flowey_lib_hvlite::_jobs::verify_all_tests_run::VmmTestResultsArtifacts { + junit_xml: ctx.use_artifact(&elem.1.0), + nextest_list_json: ctx.use_artifact(&elem.1.1), + }, + ) + }) + .collect(), + done: ctx.new_done_handle(), + }, + ) + .finish(); + all_jobs.push(job); + } + // test the flowey local backend by running cargo xflowey build-igvm on x64 { let job = pipeline diff --git a/flowey/flowey_lib_common/src/gen_cargo_nextest_list_cmd.rs b/flowey/flowey_lib_common/src/gen_cargo_nextest_list_cmd.rs new file mode 100644 index 0000000000..9b99b036df --- /dev/null +++ b/flowey/flowey_lib_common/src/gen_cargo_nextest_list_cmd.rs @@ -0,0 +1,110 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +//! Run cargo-nextest list subcommand. +use crate::gen_cargo_nextest_run_cmd; +use flowey::node::prelude::*; +use std::collections::BTreeMap; + +flowey_request! { + pub struct Request { + /// Path to nextest archive file + pub archive_file: ReadVar, + /// Path to nextest binary + pub nextest_bin: ReadVar, + /// Target triple for the build + pub target: ReadVar, + /// Working directory the test archive was created from. + pub working_dir: ReadVar, + /// Path to `.config/nextest.toml` + pub config_file: ReadVar, + /// Nextest profile to use when running the source code + pub nextest_profile: String, + /// Nextest test filter expression + pub nextest_filter_expr: Option, + /// Whether to include ignored tests in the list output + pub run_ignored: bool, + /// Additional env vars set when executing the tests. + pub extra_env: Option>>, + /// Generated cargo-nextest list command + pub command: WriteVar, + } +} + +new_flow_node!(struct Node); + +impl FlowNode for Node { + type Request = Request; + + fn imports(ctx: &mut ImportCtx<'_>) { + ctx.import::(); + } + + fn emit(requests: Vec, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> { + for Request { + archive_file, + nextest_bin, + target, + working_dir, + config_file, + nextest_profile, + nextest_filter_expr, + run_ignored, + extra_env, + command: list_cmd, + } in requests + { + let run_script = ctx.reqv(|v| gen_cargo_nextest_run_cmd::Request { + run_kind_deps: gen_cargo_nextest_run_cmd::RunKindDeps::RunFromArchive { + archive_file, + nextest_bin, + target, + }, + working_dir, + config_file, + tool_config_files: Vec::new(), // Ignored + nextest_profile, + extra_env, + extra_commands: None, + nextest_filter_expr, + run_ignored, + fail_fast: None, + portable: false, + command: v, + }); + + ctx.emit_rust_step("generate nextest list command", |ctx| { + let run_script = run_script.claim(ctx); + let list_cmd = list_cmd.claim(ctx); + move |rt| { + let mut script = rt.read(run_script); + let run_cmd_args: Vec<_> = script + .commands + .first() + .unwrap() + .1 + .iter() + .map(|arg| { + if arg == "run" { + "list".into() + } else { + arg.clone() + } + }) + .collect(); + + script.commands[0].1 = run_cmd_args; + script.commands[0] + .1 + .extend(["--message-format".into(), "json".into()]); + + rt.write(list_cmd, &script); + log::info!("Generated command: {}", script); + + Ok(()) + } + }); + } + Ok(()) + } +} diff --git a/flowey/flowey_lib_common/src/lib.rs b/flowey/flowey_lib_common/src/lib.rs index c72ded3af4..9880c69756 100644 --- a/flowey/flowey_lib_common/src/lib.rs +++ b/flowey/flowey_lib_common/src/lib.rs @@ -31,6 +31,7 @@ pub mod download_mdbook_admonish; pub mod download_mdbook_mermaid; pub mod download_nuget_exe; pub mod download_protoc; +pub mod gen_cargo_nextest_list_cmd; pub mod gen_cargo_nextest_run_cmd; pub mod gh_download_azure_key_vault_secret; pub mod gh_latest_completed_workflow_id; @@ -51,5 +52,6 @@ pub mod run_cargo_build; pub mod run_cargo_clippy; pub mod run_cargo_doc; pub mod run_cargo_nextest_archive; +pub mod run_cargo_nextest_list; pub mod run_cargo_nextest_run; pub mod use_gh_cli; diff --git a/flowey/flowey_lib_common/src/publish_test_results.rs b/flowey/flowey_lib_common/src/publish_test_results.rs index 5407168be3..0ab544a533 100644 --- a/flowey/flowey_lib_common/src/publish_test_results.rs +++ b/flowey/flowey_lib_common/src/publish_test_results.rs @@ -14,7 +14,7 @@ use flowey::node::prelude::*; use std::collections::BTreeMap; flowey_request! { - pub struct Request { + pub enum Request { /// Path to a junit.xml file /// /// HACK: this is an optional since `flowey` doesn't (yet?) have any way @@ -23,22 +23,35 @@ flowey_request! { /// /// To keep making forward progress, I've tweaked this node to accept an /// optional... but this ain't great. - pub junit_xml: ReadVar>, - /// Brief string used when publishing the test. - /// Must be unique to the pipeline. - pub test_label: String, - /// Additional files or directories to upload. - /// - /// The boolean indicates whether the attachment is referenced in the - /// JUnit XML file. On backends with native JUnit attachment support, - /// these attachments will not be uploaded as distinct artifacts and - /// will instead be uploaded via the JUnit integration. - pub attachments: BTreeMap, bool)>, - /// Copy the xml file and attachments to the provided directory. - /// Only supported on local backend. - pub output_dir: Option>, - /// Side-effect confirming that the publish has succeeded - pub done: WriteVar, + PublishJunitXml { + junit_xml: ReadVar>, + test_label: String, + /// Copy full test results (all logs, dumps, etc) to the provided directory. + output_dir: Option>, + /// Side-effect confirming that the publish has succeeded + done: WriteVar, + }, + PublishTestLogs { + test_label: String, + /// Additional files or directories to upload. + /// + /// The boolean indicates whether the attachment is referenced in the + /// JUnit XML file. On backends with native JUnit attachment support, + /// these attachments will not be uploaded as distinct artifacts and + /// will instead be uploaded via the JUnit integration. + attachments: BTreeMap, bool)>, + output_dir: ReadVar, + /// Side-effect confirming that the publish has succeeded + done: WriteVar, + }, + PublishNextestListJson { + /// Path to a nextest-list.json file + nextest_list_json: ReadVar, + test_label: String, + output_dir: ReadVar, + /// Side-effect confirming that the publish has succeeded + done: WriteVar, + }, } } @@ -55,178 +68,181 @@ impl FlowNode for Node { let mut use_side_effects = Vec::new(); let mut resolve_side_effects = Vec::new(); - for Request { - junit_xml, - test_label: label, - attachments, - output_dir, - done, - } in requests - { - resolve_side_effects.push(done); - - if output_dir.is_some() && !matches!(ctx.backend(), FlowBackend::Local) { - anyhow::bail!( - "Copying to a custom output directory is only supported on local backend." - ) - } - - let step_name = format!("publish test results: {label} (JUnit XML)"); - let artifact_name = format!("{label}-junit-xml"); - - let has_junit_xml = junit_xml.map(ctx, |p| p.is_some()); - let junit_xml = junit_xml.map(ctx, |p| p.unwrap_or_default()); - - match ctx.backend() { - FlowBackend::Ado => { - use_side_effects.push(ctx.reqv(|v| { - crate::ado_task_publish_test_results::Request { - step_name, - format: - crate::ado_task_publish_test_results::AdoTestResultsFormat::JUnit, - results_file: junit_xml, - test_title: label.clone(), - condition: Some(has_junit_xml), - done: v, - } - })); - } - FlowBackend::Github => { - let junit_xml = junit_xml.map(ctx, |p| { - p.absolute().expect("invalid path").display().to_string() - }); - - // Note: usually flowey's built-in artifact publishing API - // should be used instead of this, but here we need to - // manually upload the artifact now so that it is still - // uploaded even if the pipeline fails. - use_side_effects.push( - ctx.emit_gh_step(step_name, "actions/upload-artifact@v4") - .condition(has_junit_xml) - .with("name", artifact_name) - .with("path", junit_xml) - .finish(ctx), - ); - } - FlowBackend::Local => { - if let Some(output_dir) = output_dir.clone() { - use_side_effects.push(ctx.emit_rust_step(step_name, |ctx| { - let output_dir = output_dir.claim(ctx); - let has_junit_xml = has_junit_xml.claim(ctx); - let junit_xml = junit_xml.claim(ctx); - - move |rt| { - let output_dir = rt.read(output_dir); - let has_junit_xml = rt.read(has_junit_xml); - let junit_xml = rt.read(junit_xml); - - if has_junit_xml { - fs_err::copy( - junit_xml, - output_dir.join(format!("{artifact_name}.xml")), - )?; + for req in requests { + match req { + Request::PublishJunitXml { + junit_xml, + test_label: label, + output_dir, + done, + } => { + resolve_side_effects.push(done); + + let step_name = + format!("copy test results to artifact directory: {label} (JUnit XML)"); + let artifact_name = format!("{label}-junit-xml"); + + let has_junit_xml = junit_xml.map(ctx, |p| p.is_some()); + let junit_xml = junit_xml.map(ctx, |p| p.unwrap_or_default()); + + match ctx.backend() { + FlowBackend::Ado => { + use_side_effects.push(ctx.reqv(|v| { + crate::ado_task_publish_test_results::Request { + step_name, + format: crate::ado_task_publish_test_results::AdoTestResultsFormat::JUnit, + results_file: junit_xml, + test_title: label.clone(), + condition: Some(has_junit_xml), + done: v, } + })); + } + FlowBackend::Github | FlowBackend::Local => { + if let Some(junit_xml_dst) = output_dir { + use_side_effects.push(ctx.emit_rust_step(step_name, move |ctx| { + let output_dir = junit_xml_dst.claim(ctx); + let has_junit_xml = has_junit_xml.claim(ctx); + let junit_xml = junit_xml.claim(ctx); - Ok(()) + move |rt| { + let output_dir = rt.read(output_dir); + let has_junit_xml = rt.read(has_junit_xml); + let junit_xml = rt.read(junit_xml); + + if has_junit_xml { + fs_err::copy( + junit_xml, + output_dir.join(format!("{artifact_name}.xml")), + )?; + } + + Ok(()) + } + })); + } else { + use_side_effects.push(has_junit_xml.into_side_effect()); + use_side_effects.push(junit_xml.into_side_effect()); } - })); - } else { - use_side_effects.push(has_junit_xml.into_side_effect()); - use_side_effects.push(junit_xml.into_side_effect()); + } } } - } - - for (attachment_label, (attachment_path, publish_on_ado)) in attachments { - let step_name = format!("publish test results: {label} ({attachment_label})"); - let artifact_name = format!("{label}-{attachment_label}"); - - let attachment_exists = attachment_path.map(ctx, |p| { - p.exists() - && (p.is_file() - || p.read_dir() - .expect("failed to read attachment dir") - .next() - .is_some()) - }); - let attachment_path_string = attachment_path.map(ctx, |p| { - p.absolute().expect("invalid path").display().to_string() - }); - - match ctx.backend() { - FlowBackend::Ado => { - if publish_on_ado { - let (published_read, published_write) = ctx.new_var(); - use_side_effects.push(published_read); - - // Note: usually flowey's built-in artifact publishing API - // should be used instead of this, but here we need to - // manually upload the artifact now so that it is still - // uploaded even if the pipeline fails. - ctx.emit_ado_step_with_condition( - step_name.clone(), - attachment_exists, - |ctx| { - published_write.claim(ctx); - let attachment_path_string = attachment_path_string.claim(ctx); - move |rt| { - let path_var = - rt.get_var(attachment_path_string).as_raw_var_name(); - // Artifact name includes the JobAttempt to - // differentiate between artifacts that were - // generated when rerunning failed jobs. - format!( - r#" + Request::PublishTestLogs { + test_label: label, + attachments, + output_dir, + done, + } => { + resolve_side_effects.push(done); + + for (attachment_label, (attachment_path, publish_on_ado)) in attachments { + let step_name = + format!("publish test results: {label} ({attachment_label})"); + let artifact_name = format!("{label}-{attachment_label}"); + + let attachment_exists = attachment_path.map(ctx, |p| { + p.exists() + && (p.is_file() + || p.read_dir() + .expect("failed to read attachment dir") + .next() + .is_some()) + }); + let attachment_path_string = attachment_path.map(ctx, |p| { + p.absolute().expect("invalid path").display().to_string() + }); + match ctx.backend() { + FlowBackend::Ado => { + if publish_on_ado { + let (published_read, published_write) = ctx.new_var(); + use_side_effects.push(published_read); + + // Note: usually flowey's built-in artifact publishing API + // should be used instead of this, but here we need to + // manually upload the artifact now so that we can overwrite the artifact name. + ctx.emit_ado_step_with_condition( + step_name.clone(), + attachment_exists, + |ctx| { + published_write.claim(ctx); + let attachment_path_string = + attachment_path_string.claim(ctx); + move |rt| { + let path_var = rt + .get_var(attachment_path_string) + .as_raw_var_name(); + // Artifact name includes the JobAttempt to + // differentiate between artifacts that were + // generated when rerunning failed jobs. + format!( + r#" - publish: $({path_var}) artifact: {artifact_name}-$({}) "#, - AdoRuntimeVar::SYSTEM__JOB_ATTEMPT.as_raw_var_name() - ) + AdoRuntimeVar::SYSTEM__JOB_ATTEMPT + .as_raw_var_name() + ) + } + }, + ); + } else { + use_side_effects.push(attachment_exists.into_side_effect()); + use_side_effects + .push(attachment_path_string.into_side_effect()); + } + } + FlowBackend::Local | FlowBackend::Github => { + use_side_effects.push(ctx.emit_rust_step(step_name, |ctx| { + let output_dir = output_dir.clone().claim(ctx); + let attachment_exists = attachment_exists.claim(ctx); + let attachment_path = attachment_path.claim(ctx); + + move |rt| { + let output_dir = rt.read(output_dir); + let attachment_exists = rt.read(attachment_exists); + let attachment_path = rt.read(attachment_path); + + if attachment_exists { + copy_dir_all( + attachment_path, + output_dir.join(artifact_name), + )?; + } + + Ok(()) } - }, - ); - } else { - use_side_effects.push(attachment_exists.into_side_effect()); - use_side_effects.push(attachment_path_string.into_side_effect()); + })); + + use_side_effects.push(attachment_path_string.into_side_effect()); + } } } - FlowBackend::Github => { - // See above comment about manually publishing artifacts - use_side_effects.push( - ctx.emit_gh_step(step_name.clone(), "actions/upload-artifact@v4") - .condition(attachment_exists) - .with("name", artifact_name) - .with("path", attachment_path_string) - .finish(ctx), - ); - } - FlowBackend::Local => { - if let Some(output_dir) = output_dir.clone() { - use_side_effects.push(ctx.emit_rust_step(step_name, |ctx| { - let output_dir = output_dir.claim(ctx); - let attachment_exists = attachment_exists.claim(ctx); - let attachment_path = attachment_path.claim(ctx); - - move |rt| { - let output_dir = rt.read(output_dir); - let attachment_exists = rt.read(attachment_exists); - let attachment_path = rt.read(attachment_path); - - if attachment_exists { - copy_dir_all( - attachment_path, - output_dir.join(artifact_name), - )?; - } + } + Request::PublishNextestListJson { + nextest_list_json, + test_label: label, + output_dir, + done, + } => { + resolve_side_effects.push(done); - Ok(()) - } - })); - } else { - use_side_effects.push(attachment_exists.into_side_effect()); + let step_name = + format!("copy nextest-list.json to artifact directory: {label}"); + let artifact_name = format!("{label}-nextest-list.json"); + + use_side_effects.push(ctx.emit_rust_step(step_name, move |ctx| { + let output_dir = output_dir.claim(ctx); + let nextest_list_json = nextest_list_json.claim(ctx); + + move |rt| { + let output_dir = rt.read(output_dir); + let nextest_list_json = rt.read(nextest_list_json); + + fs_err::copy(nextest_list_json, output_dir.join(artifact_name))?; + + Ok(()) } - use_side_effects.push(attachment_path_string.into_side_effect()); - } + })); } } } diff --git a/flowey/flowey_lib_common/src/run_cargo_nextest_list.rs b/flowey/flowey_lib_common/src/run_cargo_nextest_list.rs new file mode 100644 index 0000000000..109bf3a73e --- /dev/null +++ b/flowey/flowey_lib_common/src/run_cargo_nextest_list.rs @@ -0,0 +1,167 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +//! Run cargo-nextest list command. +use flowey::node::prelude::*; +use std::collections::BTreeMap; +use std::io::Write; +use std::process::ExitStatus; +use std::process::Stdio; + +flowey_request! { + pub struct Request { + /// Path to nextest archive file + pub archive_file: ReadVar, + /// Path to nextest binary + pub nextest_bin: Option>, + /// Target triple for the build + pub target: Option>, + /// Working directory the test archive was created from. + pub working_dir: ReadVar, + /// Path to `.config/nextest.toml` + pub config_file: ReadVar, + /// Nextest profile to use when running the source code + pub nextest_profile: String, + /// Nextest test filter expression + pub nextest_filter_expr: Option, + /// Whether to include ignored tests in the list output + pub run_ignored: bool, + /// Additional env vars set when executing the tests. + pub extra_env: Option>>, + /// Output directory for the nextest list output file + pub output_dir: ReadVar, + /// Wait for specified side-effects to resolve + pub pre_run_deps: Vec>, + /// Final path to nextest list output file + pub output_file: WriteVar, + } +} + +new_simple_flow_node!(struct Node); + +impl SimpleFlowNode for Node { + type Request = Request; + + fn imports(ctx: &mut ImportCtx<'_>) { + ctx.import::(); + ctx.import::(); + } + + fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> { + let Request { + archive_file, + nextest_bin, + target, + working_dir, + config_file, + nextest_profile, + nextest_filter_expr, + run_ignored, + extra_env, + output_dir, + pre_run_deps, + output_file, + } = request; + + let target = target.unwrap_or(ReadVar::from_static(target_lexicon::Triple::host())); + + let nextest_bin = nextest_bin.unwrap_or_else(|| { + ctx.reqv(|v| crate::download_cargo_nextest::Request::Get(target.clone(), v)) + }); + + let cmd = ctx.reqv(|v| crate::gen_cargo_nextest_list_cmd::Request { + archive_file, + nextest_bin, + target, + working_dir: working_dir.clone(), + config_file, + nextest_profile, + nextest_filter_expr, + run_ignored, + extra_env, + command: v, + }); + + ctx.emit_rust_step("run cargo-nextest list", |ctx| { + pre_run_deps.claim(ctx); + let cmd = cmd.claim(ctx); + let working_dir = working_dir.claim(ctx); + let output_file = output_file.claim(ctx); + let output_dir = output_dir.claim(ctx); + + move |rt| { + let working_dir = rt.read(working_dir); + let cmd = rt.read(cmd); + let output_dir = rt.read(output_dir); + + let (status, stdout) = run_command(&cmd, &working_dir, true)?; + + if !status.success() { + anyhow::bail!( + "cargo-nextest list command failed with exit code: {}", + status.code().unwrap_or(-1) + ); + } + + let stdout = stdout + .as_deref() + .ok_or_else(|| anyhow::anyhow!("failed to capture stdout"))?; + + let json_value = get_nextest_list_output_from_stdout(stdout)?; + + let final_path = output_dir.join("nextest_list_output.json"); + let mut file = fs_err::File::create(&final_path)?; + file.write_all(serde_json::to_string_pretty(&json_value)?.as_bytes())?; + file.flush()?; + + rt.write(output_file, &final_path.to_path_buf()); + + Ok(()) + } + }); + + Ok(()) + } +} + +fn run_command( + cmd: &crate::gen_cargo_nextest_run_cmd::Script, + working_dir: &PathBuf, + capture_stdout: bool, +) -> anyhow::Result<(ExitStatus, Option)> { + let mut command = std::process::Command::new(&cmd.commands[0].0); + command + .args(&cmd.commands[0].1) + .envs(&cmd.env) + .current_dir(working_dir); + + if capture_stdout { + command.stdout(Stdio::piped()); + } else { + command.stdout(Stdio::inherit()); + } + + let mut child = command + .spawn() + .with_context(|| format!("failed to spawn '{}'", &cmd.commands[0].0.to_string_lossy()))?; + + if capture_stdout { + let output = child.wait_with_output()?; + let stdout_str = String::from_utf8_lossy(&output.stdout).into_owned(); + Ok((output.status, Some(stdout_str))) + } else { + let status = child.wait()?; + Ok((status, None)) + } +} + +fn get_nextest_list_output_from_stdout(output: &str) -> anyhow::Result { + // nextest list prints a few lines of non-json output before the actual + // JSON output, so we need to find the first line that is valid JSON + for line in output.lines() { + if let Ok(json_value) = serde_json::from_str::(line) { + return Ok(json_value); + } + } + anyhow::bail!("failed to find JSON output in nextest list command output"); +} diff --git a/flowey/flowey_lib_hvlite/Cargo.toml b/flowey/flowey_lib_hvlite/Cargo.toml index c3f5cdc435..544ec7c364 100644 --- a/flowey/flowey_lib_hvlite/Cargo.toml +++ b/flowey/flowey_lib_hvlite/Cargo.toml @@ -17,6 +17,7 @@ igvmfilegen_config.workspace = true anyhow.workspace = true fs-err.workspace = true log.workspace = true +quick-xml.workspace = true serde = { workspace = true, features = ["std"] } serde_json = { workspace = true, features = ["std"] } target-lexicon = { workspace = true, features = ["serde_support"] } diff --git a/flowey/flowey_lib_hvlite/src/_jobs/build_and_run_nextest_unit_tests.rs b/flowey/flowey_lib_hvlite/src/_jobs/build_and_run_nextest_unit_tests.rs index f8206f2d76..b351ade117 100644 --- a/flowey/flowey_lib_hvlite/src/_jobs/build_and_run_nextest_unit_tests.rs +++ b/flowey/flowey_lib_hvlite/src/_jobs/build_and_run_nextest_unit_tests.rs @@ -8,7 +8,6 @@ use crate::run_cargo_build::common::CommonProfile; use crate::run_cargo_nextest_run::NextestProfile; use flowey::node::prelude::*; use flowey_lib_common::run_cargo_nextest_run::build_params::PanicAbortTests; -use std::collections::BTreeMap; flowey_request! { pub struct Params { @@ -66,13 +65,15 @@ impl SimpleFlowNode for Node { let mut side_effects = Vec::new(); let junit_xml = results.map(ctx, |r| r.junit_xml); - let reported_results = ctx.reqv(|v| flowey_lib_common::publish_test_results::Request { - junit_xml, - test_label: junit_test_label, - attachments: BTreeMap::new(), - output_dir: artifact_dir, - done: v, - }); + let reported_results = + ctx.reqv( + |v| flowey_lib_common::publish_test_results::Request::PublishJunitXml { + junit_xml, + test_label: junit_test_label, + output_dir: artifact_dir, + done: v, + }, + ); side_effects.push(reported_results); diff --git a/flowey/flowey_lib_hvlite/src/_jobs/consume_and_test_nextest_unit_tests_archive.rs b/flowey/flowey_lib_hvlite/src/_jobs/consume_and_test_nextest_unit_tests_archive.rs deleted file mode 100644 index 00d642e555..0000000000 --- a/flowey/flowey_lib_hvlite/src/_jobs/consume_and_test_nextest_unit_tests_archive.rs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -//! Run a pre-built cargo-nextest based unit test archive. - -use crate::build_nextest_unit_tests::NextestUnitTestArchive; -use crate::run_cargo_nextest_run::NextestProfile; -use flowey::node::prelude::*; -use std::collections::BTreeMap; - -flowey_request! { - pub struct Params { - /// Friendly label for report JUnit test results - pub junit_test_label: String, - /// Existing unit test archive - pub nextest_unit_test_archive: ReadVar, - /// Nextest profile to use when running the source code - pub nextest_profile: NextestProfile, - - /// Whether the job should fail if any test has failed - pub fail_job_on_test_fail: bool, - /// (optionally) Also publish raw junit.xml test results as an artifact. - pub artifact_dir: Option>, - pub done: WriteVar, - } -} - -new_simple_flow_node!(struct Node); - -impl SimpleFlowNode for Node { - type Request = Params; - - fn imports(ctx: &mut ImportCtx<'_>) { - ctx.import::(); - ctx.import::(); - } - - fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> { - let Params { - junit_test_label, - nextest_unit_test_archive, - nextest_profile, - fail_job_on_test_fail, - artifact_dir, - done, - } = request; - - let results = ctx.reqv(|v| crate::test_nextest_unit_tests_archive::Request { - nextest_archive_file: nextest_unit_test_archive, - nextest_profile, - nextest_bin: None, - target: None, - results: v, - }); - - let mut side_effects = Vec::new(); - - let junit_xml = results.map(ctx, |r| r.junit_xml); - let reported_results = ctx.reqv(|v| flowey_lib_common::publish_test_results::Request { - junit_xml, - test_label: junit_test_label, - attachments: BTreeMap::new(), - output_dir: artifact_dir, - done: v, - }); - - side_effects.push(reported_results); - - ctx.emit_rust_step("report test results to overall pipeline status", |ctx| { - side_effects.claim(ctx); - done.claim(ctx); - - let results = results.clone().claim(ctx); - move |rt| { - let results = rt.read(results); - if results.all_tests_passed { - log::info!("all tests passed!"); - } else { - if fail_job_on_test_fail { - anyhow::bail!("encountered test failures.") - } else { - log::error!("encountered test failures.") - } - } - - Ok(()) - } - }); - - Ok(()) - } -} diff --git a/flowey/flowey_lib_hvlite/src/_jobs/consume_and_test_nextest_vmm_tests_archive.rs b/flowey/flowey_lib_hvlite/src/_jobs/consume_and_test_nextest_vmm_tests_archive.rs index 7e805f7447..07490e7f25 100644 --- a/flowey/flowey_lib_hvlite/src/_jobs/consume_and_test_nextest_vmm_tests_archive.rs +++ b/flowey/flowey_lib_hvlite/src/_jobs/consume_and_test_nextest_vmm_tests_archive.rs @@ -34,6 +34,13 @@ pub struct VmmTestsDepArtifacts { pub tpm_guest_tests_linux: Option>, } +#[derive(Serialize, Deserialize)] +pub struct VmmTestsPublishArtifacts { + pub junit_xml: ReadVar, + pub nextest_list_json: ReadVar, + pub test_logs_dir: ReadVar, +} + flowey_request! { pub struct Params { /// Friendly label for report JUnit test results @@ -55,8 +62,7 @@ flowey_request! { /// Whether the job should fail if any test has failed pub fail_job_on_test_fail: bool, - /// If provided, also publish junit.xml test results as an artifact. - pub artifact_dir: Option>, + pub artifacts_to_publish: Option, pub done: WriteVar, } } @@ -74,6 +80,7 @@ impl SimpleFlowNode for Node { ctx.import::(); ctx.import::(); ctx.import::(); + ctx.import::(); ctx.import::(); ctx.import::(); ctx.import::(); @@ -90,7 +97,7 @@ impl SimpleFlowNode for Node { test_artifacts, fail_job_on_test_fail, needs_prep_run, - artifact_dir, + artifacts_to_publish, done, } = request; @@ -195,14 +202,14 @@ impl SimpleFlowNode for Node { } let results = ctx.reqv(|v| crate::test_nextest_vmm_tests_archive::Request { - nextest_archive_file: nextest_vmm_tests_archive, - nextest_profile, - nextest_filter_expr, + nextest_archive_file: nextest_vmm_tests_archive.clone(), + nextest_profile: nextest_profile.clone(), + nextest_filter_expr: nextest_filter_expr.clone(), nextest_working_dir: None, nextest_config_file: None, nextest_bin: None, target: None, - extra_env, + extra_env: extra_env.clone(), pre_run_deps, results: v, }); @@ -212,16 +219,72 @@ impl SimpleFlowNode for Node { let test_log_path = test_log_path.depending_on(ctx, &results); let junit_xml = results.map(ctx, |r| r.junit_xml); - let reported_results = ctx.reqv(|v| flowey_lib_common::publish_test_results::Request { - junit_xml, - test_label: junit_test_label, - attachments: BTreeMap::from([("logs".to_string(), (test_log_path, false))]), - output_dir: artifact_dir, - done: v, + let archive_file = nextest_vmm_tests_archive.map(ctx, |x| x.archive_file); + // Run_ignored option is set to true so that we can dump all the tests that were built, instead of just the ones that were run. + let nextest_list_json = ctx.reqv(|v| crate::run_cargo_nextest_list::Request { + archive_file, + nextest_bin: None, + target: None, + working_dir: None, + config_file: None, + nextest_profile: nextest_profile.as_str().to_owned(), + nextest_filter_expr: nextest_filter_expr.clone(), + run_ignored: true, + extra_env: Some(extra_env), + output_dir: test_log_path.clone(), + pre_run_deps: vec![], + output_file: v, }); + let mut side_effects = Vec::new(); + + if let Some(artifacts_to_publish) = artifacts_to_publish { + let VmmTestsPublishArtifacts { + junit_xml: junit_xml_output_dir, + nextest_list_json: nextest_list_json_output_dir, + test_logs_dir: test_results_full_output_dir, + } = artifacts_to_publish; + + // Publish JUnit XML + side_effects.push(ctx.reqv(|v| { + flowey_lib_common::publish_test_results::Request::PublishJunitXml { + junit_xml: junit_xml.clone(), + test_label: junit_test_label.clone(), + output_dir: Some(junit_xml_output_dir), + done: v, + } + })); + + // Publish test logs + side_effects.push(ctx.reqv(|v| { + flowey_lib_common::publish_test_results::Request::PublishTestLogs { + test_label: junit_test_label.clone(), + attachments: BTreeMap::from([( + "logs".to_string(), + (test_log_path.clone(), false), + )]), + output_dir: test_results_full_output_dir, + done: v, + } + })); + + // Publish nextest-list.json + side_effects.push(ctx.reqv(|v| { + flowey_lib_common::publish_test_results::Request::PublishNextestListJson { + nextest_list_json: nextest_list_json.clone(), + test_label: junit_test_label.clone(), + output_dir: nextest_list_json_output_dir, + done: v, + } + })); + } else { + side_effects.push(test_log_path.into_side_effect()); + side_effects.push(nextest_list_json.into_side_effect()); + side_effects.push(junit_xml.into_side_effect()); + } + ctx.emit_rust_step("report test results to overall pipeline status", |ctx| { - reported_results.claim(ctx); + side_effects.claim(ctx); done.claim(ctx); let results = results.clone().claim(ctx); diff --git a/flowey/flowey_lib_hvlite/src/_jobs/local_build_and_run_nextest_vmm_tests.rs b/flowey/flowey_lib_hvlite/src/_jobs/local_build_and_run_nextest_vmm_tests.rs index a31d85c8d8..d40d99a0c5 100644 --- a/flowey/flowey_lib_hvlite/src/_jobs/local_build_and_run_nextest_vmm_tests.rs +++ b/flowey/flowey_lib_hvlite/src/_jobs/local_build_and_run_nextest_vmm_tests.rs @@ -18,7 +18,6 @@ use crate::run_cargo_build::common::CommonTriple; use flowey::node::prelude::*; use flowey_lib_common::gen_cargo_nextest_run_cmd::CommandShell; use flowey_lib_common::gen_cargo_nextest_run_cmd::RunKindDeps; -use std::collections::BTreeMap; use std::str::FromStr; use vmm_test_images::KnownTestArtifacts; @@ -1019,13 +1018,14 @@ impl SimpleFlowNode for Node { let junit_xml = results.map(ctx, |r| r.junit_xml); let published_results = - ctx.reqv(|v| flowey_lib_common::publish_test_results::Request { - junit_xml, - test_label, - attachments: BTreeMap::new(), // the logs are already there - output_dir: Some(ReadVar::from_static(test_content_dir)), - done: v, - }); + ctx.reqv( + |v| flowey_lib_common::publish_test_results::Request::PublishJunitXml { + junit_xml, + test_label, + output_dir: Some(ReadVar::from_static(test_content_dir)), + done: v, + }, + ); ctx.emit_rust_step("report test results", |ctx| { published_results.claim(ctx); diff --git a/flowey/flowey_lib_hvlite/src/_jobs/mod.rs b/flowey/flowey_lib_hvlite/src/_jobs/mod.rs index 89f2247ee2..9d7bde670c 100644 --- a/flowey/flowey_lib_hvlite/src/_jobs/mod.rs +++ b/flowey/flowey_lib_hvlite/src/_jobs/mod.rs @@ -17,10 +17,10 @@ pub mod check_clippy; pub mod check_openvmm_hcl_size; pub mod check_xtask_fmt; pub mod consolidate_and_publish_gh_pages; -pub mod consume_and_test_nextest_unit_tests_archive; pub mod consume_and_test_nextest_vmm_tests_archive; pub mod local_build_and_run_nextest_vmm_tests; pub mod local_build_igvm; pub mod local_custom_vmfirmwareigvm_dll; pub mod local_restore_packages; pub mod test_local_flowey_build_igvm; +pub mod verify_all_tests_run; diff --git a/flowey/flowey_lib_hvlite/src/_jobs/verify_all_tests_run.rs b/flowey/flowey_lib_hvlite/src/_jobs/verify_all_tests_run.rs new file mode 100644 index 0000000000..ecc8ef3623 --- /dev/null +++ b/flowey/flowey_lib_hvlite/src/_jobs/verify_all_tests_run.rs @@ -0,0 +1,175 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +//! Verifies that all tests that are built are run at least once over the course of an entire pipeline run. +use flowey::node::prelude::*; +use quick_xml::Reader; +use quick_xml::events::Event; +use serde::Deserialize; +use std::collections::HashMap; +use std::collections::HashSet; + +#[derive(Debug, Deserialize)] +struct Root { + #[serde(rename = "rust-suites")] + rust_suites: HashMap, +} + +#[derive(Debug, Deserialize)] +struct Suite { + testcases: HashMap, // we don't care about contents +} + +#[derive(Serialize, Deserialize)] +pub struct VmmTestResultsArtifacts { + pub junit_xml: ReadVar, + pub nextest_list_json: ReadVar, +} + +flowey_request! { + pub struct Request { + pub test_artifacts: Vec<(String, VmmTestResultsArtifacts)>, + pub done: WriteVar, + } +} + +new_simple_flow_node!(struct Node); + +impl SimpleFlowNode for Node { + type Request = Request; + + fn imports(_ctx: &mut ImportCtx<'_>) {} + + fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> { + let Request { + test_artifacts, + done, + } = request; + + // It doesn't make sense for this node to run locally since there is no way for one machine + // to run all the vmm_tests we have. + if ctx.backend() == FlowBackend::Local { + return Ok(()); + } + + let parse = ctx.emit_rust_step( + "parse and analyze junit logs and nextest list output", + |ctx| { + // This step takes all of the junit XML files (i.e. the tests that were run) and the nextest list (with the --include-ignored flag) + // command output (i.e. all the tests that were built) and verifies that the set of all tests that were built is the same as the set + // of all tests that were run. If these sets were to differ it would be because a test was built but not run, which indicates a test gap. + // We have automation in the test run step that will automatically skip tests that are not meant to run on a given host because the host does + // not meet the test case requirements. For example, TDX/SNP tests are skipped on non-compatible hardware. + let artifacts: Vec<_> = test_artifacts + .into_iter() + .map(|(prefix, artifacts)| { + ( + prefix, + artifacts.junit_xml.claim(ctx), + artifacts.nextest_list_json.claim(ctx), + ) + }) + .collect(); + + move |rt| { + let mut combined_junit_testcases: HashSet = HashSet::new(); + let mut combined_nextest_testcases: HashSet = HashSet::new(); + + for (prefix, junit_xml_dir, nextest_list_json_dir) in artifacts { + let junit_xml_dir = rt.read(junit_xml_dir); + let nextest_list_dir = rt.read(nextest_list_json_dir); + println!("Artifact dir: {}", junit_xml_dir.display()); + println!("Artifact dir: {}", nextest_list_dir.display()); + assert!(junit_xml_dir.exists(), "expected artifact dir to exist"); + assert!(nextest_list_dir.exists(), "expected artifact dir to exist"); + + let junit_xml = prefix.clone() + "-vmm-tests-junit-xml.xml"; + let nextest_list = prefix.clone() + "-vmm-tests-nextest-list.json"; + + let junit_xml = junit_xml_dir.clone().join(&junit_xml); + let nextest_list = nextest_list_dir.clone().join(&nextest_list); + + get_testcase_names_from_junit_xml( + &junit_xml, + &mut combined_junit_testcases, + )?; + + get_testcase_names_from_nextest_list_json( + &nextest_list, + &mut combined_nextest_testcases, + )?; + } + + assert!( + combined_junit_testcases == combined_nextest_testcases, + "Mismatch between test cases in junit XML and nextest list JSON.\n\ + Test cases in junit XML but not in nextest list JSON: {:?}\n\ + Test cases in nextest list JSON but not in junit XML: {:?}", + combined_junit_testcases + .difference(&combined_nextest_testcases) + .collect::>(), + combined_nextest_testcases + .difference(&combined_junit_testcases) + .collect::>(), + ); + + Ok(()) + } + }, + ); + + ctx.emit_side_effect_step(vec![parse], [done]); + + Ok(()) + } +} + +fn get_testcase_names_from_junit_xml( + junit_path: &PathBuf, + test_names: &mut HashSet, +) -> anyhow::Result<()> { + let mut reader = Reader::from_file(junit_path)?; + + let mut buf = Vec::new(); + + loop { + match reader.read_event_into(&mut buf)? { + Event::Start(e) if e.name().as_ref() == b"testcase" => { + let mut name = None; + let mut classname = None; + + for attr in e.attributes() { + let attr = attr?; + match attr.key.as_ref() { + b"name" => name = Some(attr.unescape_value()?.to_string()), + b"classname" => classname = Some(attr.unescape_value()?.to_string()), + _ => {} + } + } + + test_names.insert(classname.unwrap() + "::" + &name.unwrap()); + } + + Event::Eof => break, + _ => {} + } + } + + Ok(()) +} + +fn get_testcase_names_from_nextest_list_json( + nextest_list_output_path: &PathBuf, + test_names: &mut HashSet, +) -> anyhow::Result<()> { + let data = fs_err::read_to_string(nextest_list_output_path)?; + let root: Root = serde_json::from_str(&data)?; + + for (suite_name, suite) in root.rust_suites { + for test_name in suite.testcases.keys() { + test_names.insert(format!("{}::{}", suite_name, test_name)); + } + } + + Ok(()) +} diff --git a/flowey/flowey_lib_hvlite/src/lib.rs b/flowey/flowey_lib_hvlite/src/lib.rs index b1ddecbe91..6edf2baafd 100644 --- a/flowey/flowey_lib_hvlite/src/lib.rs +++ b/flowey/flowey_lib_hvlite/src/lib.rs @@ -52,6 +52,7 @@ pub mod install_git_credential_manager; pub mod install_openvmm_rust_build_essential; pub mod install_vmm_tests_deps; pub mod run_cargo_build; +pub mod run_cargo_nextest_list; pub mod run_cargo_nextest_run; pub mod run_igvmfilegen; pub mod run_prep_steps; diff --git a/flowey/flowey_lib_hvlite/src/run_cargo_nextest_list.rs b/flowey/flowey_lib_hvlite/src/run_cargo_nextest_list.rs new file mode 100644 index 0000000000..0a75f750b8 --- /dev/null +++ b/flowey/flowey_lib_hvlite/src/run_cargo_nextest_list.rs @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +//! Run cargo-nextest list. +use flowey::node::prelude::*; +use std::collections::BTreeMap; + +flowey_request! { + pub struct Request { + /// Path to nextest archive file + pub archive_file: ReadVar, + /// Path to nextest binary + pub nextest_bin: Option>, + /// Target triple for the build + pub target: Option>, + /// Working directory the test archive was created from. + pub working_dir: Option>, + /// Path to `.config/nextest.toml` + pub config_file: Option>, + /// Nextest profile to use when running the source code + pub nextest_profile: String, + /// Nextest test filter expression + pub nextest_filter_expr: Option, + /// Whether to include ignored tests in the list output + pub run_ignored: bool, + /// Additional env vars set when executing the tests. + pub extra_env: Option>>, + /// Output directory for the nextest list output file + pub output_dir: ReadVar, + /// Wait for specified side-effects to resolve + pub pre_run_deps: Vec>, + /// Final path to nextest list output file + pub output_file: WriteVar, + } +} + +new_simple_flow_node!(struct Node); + +impl SimpleFlowNode for Node { + type Request = Request; + + fn imports(ctx: &mut ImportCtx<'_>) { + ctx.import::(); + ctx.import::(); + } + + fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> { + let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir); + + let default_nextest_config_file = crate::run_cargo_nextest_run::default_nextest_config_file( + openvmm_repo_path.clone(), + ctx, + ); + + let base_env = crate::run_cargo_nextest_run::base_env(); + + let Request { + archive_file, + nextest_bin, + target, + working_dir, + config_file, + nextest_profile, + nextest_filter_expr, + run_ignored, + extra_env, + output_dir, + mut pre_run_deps, + output_file, + } = request; + + let extra_env = + crate::run_cargo_nextest_run::merged_extra_env(extra_env, base_env.clone(), ctx); + + let working_dir = crate::run_cargo_nextest_run::resolve_working_dir( + working_dir, + openvmm_repo_path.clone(), + &mut pre_run_deps, + ); + + let config_file = crate::run_cargo_nextest_run::resolve_config_file( + config_file, + default_nextest_config_file.clone(), + &mut pre_run_deps, + ); + + ctx.req(flowey_lib_common::run_cargo_nextest_list::Request { + archive_file, + nextest_bin, + target, + working_dir, + config_file, + nextest_profile, + nextest_filter_expr, + run_ignored, + extra_env: Some(extra_env), + output_dir, + pre_run_deps, + output_file, + }); + + Ok(()) + } +} diff --git a/flowey/flowey_lib_hvlite/src/run_cargo_nextest_run.rs b/flowey/flowey_lib_hvlite/src/run_cargo_nextest_run.rs index 997e40fe28..9104fe4f53 100644 --- a/flowey/flowey_lib_hvlite/src/run_cargo_nextest_run.rs +++ b/flowey/flowey_lib_hvlite/src/run_cargo_nextest_run.rs @@ -11,8 +11,73 @@ use flowey_lib_common::run_cargo_nextest_run::NextestRunKind; use flowey_lib_common::run_cargo_nextest_run::TestResults; use std::collections::BTreeMap; +pub fn default_nextest_config_file( + openvmm_repo_path: ReadVar, + ctx: &mut NodeCtx<'_>, +) -> ReadVar { + openvmm_repo_path.map(ctx, |p| p.join(".config").join("nextest.toml")) +} + +pub fn base_env() -> BTreeMap { + [ + // Used by the test_with_tracing macro in test runners + ("RUST_LOG", "trace"), + ] + .into_iter() + .map(|(a, b)| (a.to_owned(), b.to_owned())) + .collect::>() +} + +/// Merge optional extra_env with the base env. Returns a ReadVar containing the merged map. +pub fn merged_extra_env( + extra_env: Option>>, + base_env: BTreeMap, + ctx: &mut NodeCtx<'_>, +) -> ReadVar> { + if let Some(with_env) = extra_env { + let base_env = base_env.clone(); + with_env.map(ctx, move |mut m| { + m.extend(base_env); + m + }) + } else { + ReadVar::from_static(base_env.clone()) + } +} + +/// Resolve the working directory: if an explicit working dir is provided, add a side-effect +/// on the repo path to `pre_run_deps` and return the provided value, otherwise return the repo path. +pub fn resolve_working_dir( + nextest_working_dir: Option>, + openvmm_repo_path: ReadVar, + pre_run_deps: &mut Vec>, +) -> ReadVar { + if let Some(nextest_working_dir) = nextest_working_dir { + pre_run_deps.push(openvmm_repo_path.clone().into_side_effect()); + nextest_working_dir + } else { + openvmm_repo_path.clone() + } +} + +/// Resolve the config file: if an explicit config file is provided, add a side-effect +/// on the default config file to `pre_run_deps` and return the provided value, otherwise +/// return the default config file. +pub fn resolve_config_file( + nextest_config_file: Option>, + default_nextest_config_file: ReadVar, + pre_run_deps: &mut Vec>, +) -> ReadVar { + if let Some(nextest_config_file) = nextest_config_file { + pre_run_deps.push(default_nextest_config_file.clone().into_side_effect()); + nextest_config_file + } else { + default_nextest_config_file.clone() + } +} + /// Nextest profiles defined in HvLite's `.config/nextest.toml` -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub enum NextestProfile { Default, Ci, @@ -68,15 +133,9 @@ impl FlowNode for Node { let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir); let default_nextest_config_file = - openvmm_repo_path.map(ctx, |p| p.join(".config").join("nextest.toml")); + default_nextest_config_file(openvmm_repo_path.clone(), ctx); - let base_env = [ - // Used by the test_with_tracing macro in test runners - ("RUST_LOG", "trace"), - ] - .into_iter() - .map(|(a, b)| (a.to_owned(), b.to_owned())) - .collect::>(); + let base_env = base_env(); for Request { friendly_name, @@ -91,29 +150,19 @@ impl FlowNode for Node { extra_env, } in requests { - let extra_env = if let Some(with_env) = extra_env { - let base_env = base_env.clone(); - with_env.map(ctx, move |mut m| { - m.extend(base_env); - m - }) - } else { - ReadVar::from_static(base_env.clone()) - }; - - let working_dir = if let Some(nextest_working_dir) = nextest_working_dir { - pre_run_deps.push(openvmm_repo_path.clone().into_side_effect()); - nextest_working_dir - } else { - openvmm_repo_path.clone() - }; - - let config_file = if let Some(nextest_config_file) = nextest_config_file { - pre_run_deps.push(default_nextest_config_file.clone().into_side_effect()); - nextest_config_file - } else { - default_nextest_config_file.clone() - }; + let extra_env = merged_extra_env(extra_env, base_env.clone(), ctx); + + let working_dir = resolve_working_dir( + nextest_working_dir, + openvmm_repo_path.clone(), + &mut pre_run_deps, + ); + + let config_file = resolve_config_file( + nextest_config_file, + default_nextest_config_file.clone(), + &mut pre_run_deps, + ); ctx.req(flowey_lib_common::run_cargo_nextest_run::Request::Run( flowey_lib_common::run_cargo_nextest_run::Run {