diff --git a/.github/workflows/v2-ci.yml b/.github/workflows/v2-ci.yml index 0368f0a6..45abcef3 100644 --- a/.github/workflows/v2-ci.yml +++ b/.github/workflows/v2-ci.yml @@ -1,7 +1,6 @@ # CI for the v2 branch — runs on every push + PR to the v2-akka-fuse / master -# branches. Layered into two jobs: -# build dotnet restore + build (fast feedback on compile errors) -# unit-tests the WHOLE solution minus the env-gated tiers (self-maintaining) +# branches. One job restores and builds once, then tests the WHOLE solution +# minus the env-gated tiers (self-maintaining). # # Skips E2E (Category=E2E) and LiveIntegration (needs a real gateway/PLC/VPN) — both # are env-gated tiers with no hosted-runner fixtures. (The skip-gated *.IntegrationTests @@ -20,38 +19,33 @@ on: branches: [v2-akka-fuse, master] workflow_dispatch: {} +# #707: one active run per repository across push/PR triggers. Gitea 1.26 supports +# workflow concurrency; newer pending runs can supersede an older pending run. +concurrency: + group: lmxopcua-v2-ci + cancel-in-progress: false + env: DOTNET_NOLOGO: "1" DOTNET_CLI_TELEMETRY_OPTOUT: "1" jobs: - build: + unit-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v4 with: dotnet-version: 10.0.x - # #606: code-reviews/README.md must be regenerated from the per-module findings.md - # files; --check exits non-zero on drift without writing (see REVIEW-PROCESS.md section 5). + # #606: regenerated review summary must remain in sync with module findings. - name: code-reviews README drift check run: python3 code-reviews/regen-readme.py --check + # #707: bound project workers and avoid concurrent NuGet restore work. - name: dotnet restore - run: dotnet restore ZB.MOM.WW.OtOpcUa.slnx + run: dotnet restore ZB.MOM.WW.OtOpcUa.slnx --disable-parallel -m:2 - name: dotnet build - run: dotnet build ZB.MOM.WW.OtOpcUa.slnx --no-restore --configuration Release - - unit-tests: - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 10.0.x - - name: dotnet restore - run: dotnet restore ZB.MOM.WW.OtOpcUa.slnx + run: dotnet build ZB.MOM.WW.OtOpcUa.slnx --no-restore --configuration Release -m:2 # #606: the runner's size is the context every timing-sensitive failure needs and the log never # recorded it (load average included: the two Gitea runners may be running jobs side by side). - name: runner capacity @@ -69,14 +63,15 @@ jobs: # are unreachable, so they run harmlessly here (and are counted by the skip-gate below). - name: dotnet test (whole solution, minus E2E + LiveIntegration) # #606: Akka TestKit time dilation for the Runtime + ControlPlane actor suites (read by their - # harnesses, tests/Server/*/Harness/TestTimeFactor.cs). This leg runs every test assembly at once - # on the runner, and their 2–8 s presence budgets — sized on an idle dev box — failed in a long + # harnesses, tests/Server/*/Harness/TestTimeFactor.cs). Their 2–8 s presence budgets + # — sized on an idle dev box — failed in a long # tail, a different test per run. Dilation only stretches waits: a presence wait still fails if # the message never comes, and absence windows get longer (stricter). Local runs stay at 1. env: AKKA_TEST_TIMEFACTOR: "3" run: > - dotnet test ZB.MOM.WW.OtOpcUa.slnx --configuration Release --no-restore + dotnet test ZB.MOM.WW.OtOpcUa.slnx --configuration Release --no-build + -m:1 -p:TestTfmsInParallel=false --settings scripts/ci/ci.runsettings --filter "Category!=E2E&Category!=LiveIntegration" --logger "trx" --results-directory artifacts/trx # 07/S-2 fail-on-skip: a whole-solution run that executed ZERO tests is a masked outage diff --git a/scripts/ci/README.md b/scripts/ci/README.md new file mode 100644 index 00000000..c7f97d5c --- /dev/null +++ b/scripts/ci/README.md @@ -0,0 +1,30 @@ +# Whole-solution CI + +The `v2-ci` workflow restores, builds and tests in one job so the test step uses +that job's Release binaries. Restore disables parallel package work; restore and +build use at most two MSBuild workers. Testing uses one MSBuild worker, disables +parallel target-framework runs and loads `ci.runsettings`: one VSTest process and +two xUnit collection workers with conservative scheduling. Assemblies that disable +parallelization keep that setting. + +The workflow retains the E2E/LiveIntegration exclusions, includes SlowUnit, keeps +Akka's test time factor at three, and requires at least 12,000 executed tests. +Runner capacity and TRX files remain available for diagnosing failures. These +limits reduce contention; they do not prove every timing failure has one cause. +There are no automatic test retries or changed assertion deadlines. + +Gitea 1.26 supports the repository-wide `lmxopcua-v2-ci` concurrency group. Only +one run is active; an active run is not cancelled, but a newer pending run may +supersede an older pending run. The group does not serialize other repositories +using the same host. + +To reproduce the bounded test leg after restore and Release build: + +```bash +AKKA_TEST_TIMEFACTOR=3 dotnet test ZB.MOM.WW.OtOpcUa.slnx \ + --configuration Release --no-build -m:1 -p:TestTfmsInParallel=false \ + --settings scripts/ci/ci.runsettings \ + --filter "Category!=E2E&Category!=LiveIntegration" \ + --logger trx --results-directory artifacts/trx +MIN_EXECUTED=12000 bash scripts/ci/assert-not-all-skipped.sh artifacts/trx/*.trx +``` diff --git a/scripts/ci/ci.runsettings b/scripts/ci/ci.runsettings new file mode 100644 index 00000000..25f10d1e --- /dev/null +++ b/scripts/ci/ci.runsettings @@ -0,0 +1,12 @@ + + + + + 1 + + + + 2 + conservative + +