From 9a26a56d306921e2219b3e9c8ce5ca91fab9696d Mon Sep 17 00:00:00 2001 From: Avimitin Date: Mon, 19 Aug 2024 17:37:42 +0800 Subject: [PATCH] [ci] split t1rocket to new CI workflow Signed-off-by: Avimitin --- .../t1rocket/default.json | 0 .../t1rocket/perf.json | 0 .github/workflows/t1rocket.yml | 107 ++++++++++++++++++ script/ci/src/Main.scala | 46 ++++---- tests/default.nix | 35 ++---- 5 files changed, 142 insertions(+), 46 deletions(-) rename .github/{cases => t1rocket-cases}/t1rocket/default.json (100%) rename .github/{cases => t1rocket-cases}/t1rocket/perf.json (100%) create mode 100644 .github/workflows/t1rocket.yml diff --git a/.github/cases/t1rocket/default.json b/.github/t1rocket-cases/t1rocket/default.json similarity index 100% rename from .github/cases/t1rocket/default.json rename to .github/t1rocket-cases/t1rocket/default.json diff --git a/.github/cases/t1rocket/perf.json b/.github/t1rocket-cases/t1rocket/perf.json similarity index 100% rename from .github/cases/t1rocket/perf.json rename to .github/t1rocket-cases/t1rocket/perf.json diff --git a/.github/workflows/t1rocket.yml b/.github/workflows/t1rocket.yml new file mode 100644 index 0000000000..5d67578ac4 --- /dev/null +++ b/.github/workflows/t1rocket.yml @@ -0,0 +1,107 @@ +name: VCS Test (T1 w/ Rocket) +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + - labeled +env: + USER: runner + +# Cancel the current workflow when new commit pushed +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + gen-test-plan: + if: '! github.event.pull_request.draft' + name: "Generate test plan" + runs-on: [self-hosted, linux, nixos] + outputs: + testplan: ${{ steps.get-all-configs.outputs.out }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - id: "get-all-configs" + run: echo "out=$(nix run .#ci-helper -- generateTestPlan --testType t1rocket)" > $GITHUB_OUTPUT + + build-emulators: + name: "Build VCS Emulators w/ Rocket" + needs: [gen-test-plan] + runs-on: [self-hosted, linux, nixos, BIGRAM] + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.gen-test-plan.outputs.testplan) }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: "Build vcs emulator" + run: | + nix build '.#t1.${{ matrix.config }}.ip.vcs-emu' --impure --no-link --cores 64 + - name: "Build all testcases" + run: | + nix build ".#t1.${{ matrix.config }}.ip.vcs-emu.cases._all" --max-jobs auto --no-link --cores 64 + + gen-matrix: + name: "Prepare for running testcases" + needs: [build-emulators] + runs-on: [self-hosted, linux, nixos, BIGRAM] + env: + RUNNERS: 70 + outputs: + ci-tests: ${{ steps.gen-matrix.outputs.matrix }} + steps: + # actions/checkout will use the "event" commit to checkout repository, + # which will lead to an unexpected issue that the "event" commit doesn't belongs to the repository, + # and causing the derivation build output cannot be cache correctly. + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - id: gen-matrix + name: "Generate test matrix" + run: | + echo -n matrix= >> "$GITHUB_OUTPUT" + nix run ".#ci-helper" -- generateCiMatrix --caseDir t1rocket-cases --runnersAmount "$RUNNERS" >> "$GITHUB_OUTPUT" + + run-testcases: + name: "Run VCS w/ Rocket" + needs: [gen-matrix] + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.gen-matrix.outputs.ci-tests) }} + runs-on: [self-hosted, linux, nixos] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: "Run testcases" + run: | + nix run ".#ci-helper" -- runTests --jobs "${{ matrix.jobs }}" --testType "vcs" + + report: + name: "Report VCS (w/ Rocket) CI result" + # Don't run report when: + # - user cancel ( we don't need report at this case ) + # - PR from outside repository ( we don't have permission to push commit into fork repository ) + if: ${{ !cancelled() && github.event.pull_request.head.repo.full_name == github.repository }} + needs: [run-testcases] + runs-on: [self-hosted, linux, nixos] + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.head_ref }} + - name: "Print step summary" + run: | + nix run ".#ci-helper" -- postCI \ + --case-dir t1rocket-cases \ + --failed-tests-file-path ./failed-tests.md \ + --emu-type vcs + cat ./failed-tests.md >> $GITHUB_STEP_SUMMARY diff --git a/script/ci/src/Main.scala b/script/ci/src/Main.scala index f037e8ec26..8c52b98b5a 100644 --- a/script/ci/src/Main.scala +++ b/script/ci/src/Main.scala @@ -125,10 +125,11 @@ object Main: @main def generateCiMatrix( runnersAmount: Int, + caseDir: String = "cases", testPlanFile: String = "default.json" ) = { val testPlans = - os.walk(os.pwd / ".github" / "cases").filter(_.last == testPlanFile) + os.walk(os.pwd / ".github" / caseDir).filter(_.last == testPlanFile) println(toMatrixJson(scheduleTasks(testPlans, runnersAmount))) } @@ -217,7 +218,11 @@ object Main: @arg( name = "emu-type", doc = "Specify emulation type" - ) emuType: String = "verilator" + ) emuType: String = "verilator", + @arg( + name = "case-dir", + doc = "Specify case directory" + ) caseDir: String = "cases" ) = val failedTestsFile = os.Path(failedTestsFilePath, os.pwd) os.write.over(failedTestsFile, "## Failed Tests\n") @@ -228,24 +233,20 @@ object Main: "## Cycle Update\n" ) - os.walk(os.pwd / ".github" / "cases") + os.walk(os.pwd / ".github" / caseDir) .filter(_.last == "default.json") .foreach: file => val config = file.segments.toSeq.reverse.apply(1) var cycleRecord = ujson.read(os.read(file)) Logger.info("Fetching CI results") - val resultAttr = emuType.toLowerCase() match - case "verilator" => - s".#t1.$config.ip.verilator-emu.cases._allEmuResult" - case "vcs" => s".#t1.$config.ip.vcs-emu.cases._allVCSEmuResult" - case _ => Logger.fatal(s"Invalid test type ${emuType}") - val emuResultPath = os.Path(nixResolvePath( - resultAttr, - if emuType.toLowerCase() == "vcs" then - Seq("--impure") - else Seq() - )) + val emuResultPath = os.Path( + nixResolvePath( + s".#t1.$config.ip.$emuType-emu.cases._allEmuResult", + if emuType.toLowerCase() == "vcs" then Seq("--impure") + else Seq() + ) + ) Logger.info("Collecting failed tests") os.walk(emuResultPath) @@ -291,11 +292,17 @@ object Main: end postCI @main - def generateTestPlan() = - val allCases = - os.walk(os.pwd / ".github" / "cases").filter(_.last == "default.json") + def generateTestPlan(testType: String = "") = + val casePath = testType match + case "t1rocket" => os.pwd / ".github" / "t1rocket-cases" + case _ => os.pwd / ".github" / "cases" + + val allCases = os.walk(casePath).filter(_.last == "default.json") val testPlans = allCases.map: caseFilePath => - caseFilePath.segments.dropWhile(_ != "cases").drop(1).next + caseFilePath.segments + .dropWhile(!Seq("cases", "t1rocket-cases").contains(_)) + .drop(1) + .next println(ujson.write(Map("config" -> testPlans))) end generateTestPlan @@ -328,7 +335,8 @@ object Main: import scala.util.chaining._ val testPlans: Seq[String] = emulatorConfigs.flatMap: configName => - val allCasesPath = nixResolvePath(s".#t1.$configName.verilator-emu.ip.cases._all") + val allCasesPath = + nixResolvePath(s".#t1.$configName.verilator-emu.ip.cases._all") os.walk(os.Path(allCasesPath) / "configs") .filter: path => path.ext == "json" diff --git a/tests/default.nix b/tests/default.nix index afa6f46fcf..1f0428112b 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -120,7 +120,7 @@ let _allEmuResult = let testPlan = builtins.fromJSON - (lib.readFile ../.github/cases/${configName}/default.json); + (lib.readFile ../.github/${if configName == "t1rocket" then "t1rocket-cases" else "cases"}/${configName}/default.json); # flattern the attr set to a list of test case derivations # AttrSet (AttrSet Derivation) -> List Derivation allCases = lib.filter @@ -132,35 +132,16 @@ let (caseDrv: '' _caseOutDir=$out/${caseDrv.pname} mkdir -p "$_caseOutDir" - cp ${caseDrv.emu-result}/perf.txt "$_caseOutDir"/ - cp ${caseDrv.emu-result}/offline-check-status "$_caseOutDir"/ - cp ${caseDrv.emu-result}/offline-check-journal "$_caseOutDir"/ - '') - allCases); - in - runCommand - "catch-${configName}-all-emu-result-for-ci" - { } - script; - _allVCSEmuResult = - let - testPlan = builtins.fromJSON (lib.readFile ../.github/cases/${configName}/default.json); - # flattern the attr set to a list of test case derivations - # AttrSet (AttrSet Derivation) -> List Derivation - allCases = lib.filter (val: lib.isDerivation val && lib.hasAttr val.pname testPlan) - (lib.concatLists (map lib.attrValues (lib.attrValues scopeStripped))); - script = '' - mkdir -p $out - '' + (lib.concatMapStringsSep "\n" - (caseDrv: '' - _caseOutDir=$out/${caseDrv.pname} - mkdir -p "$_caseOutDir" - cp ${caseDrv.emu-result}/offline-check-* "$_caseOutDir"/ + if [ -r ${caseDrv.emu-result}/perf.txt ]; then + cp -v ${caseDrv.emu-result}/perf.txt "$_caseOutDir"/ + fi + + cp -v ${caseDrv.emu-result}/offline-check-* "$_caseOutDir"/ '') allCases); in - runCommand "catch-${configName}-all-vcs-emu-result-for-ci" { } script; + runCommand "catch-${configName}-all-emu-result-for-ci" { } script; _all = let @@ -182,4 +163,4 @@ let { } script; in -lib.recurseIntoAttrs (scopeStripped // { inherit _all _allEmuResult _allVCSEmuResult; }) +lib.recurseIntoAttrs (scopeStripped // { inherit _all _allEmuResult; })