diff --git a/.github/workflows/v2-ci.yml b/.github/workflows/v2-ci.yml index 2c1bd1b5..b9e801e8 100644 --- a/.github/workflows/v2-ci.yml +++ b/.github/workflows/v2-ci.yml @@ -104,10 +104,10 @@ jobs: # NOTE (07/P-5): the former `integration` matrix job (Host.IntegrationTests + # OpcUaServer.IntegrationTests) was removed as fully redundant — the unit-tests leg # above already runs BOTH projects under the identical filter, fixtureless, and gates - # them at MIN_EXECUTED=1. Its only unique output was a report-only skip tally the unit + # them at the MIN_EXECUTED floor. Its only unique output was a report-only skip tally the unit # leg's trx already contains. FOLLOW-UP (S-2 option #2): if a fixture-backed integration # leg is wanted, add it as a NEW job that starts the one public-image fixture as a # `services:` block (mcr.microsoft.com/iotedge/opc-plc; the modbus/S7/AB/FOCAS sims are # locally-built `otopcua-*` images not pullable here), sets OPCUA_SIM_ENDPOINT, and gates - # at MIN_EXECUTED=1 so a fixture outage turns the job red — covering something the unit + # at a MIN_EXECUTED floor so a fixture outage turns the job red — covering something the unit # leg cannot, rather than re-running the same fixtureless tests. diff --git a/infra/README.md b/infra/README.md index dc0c7e93..65b3d6af 100644 --- a/infra/README.md +++ b/infra/README.md @@ -221,9 +221,13 @@ and a real directory (LDAP) — never the dev values in this doc. ## 10. CI — Gitea Actions (`.github/workflows/v2-ci.yml`) The one workflow (there is no `.gitea/workflows/`) runs on the Gitea act_runners `gitea-runner` / -`gitea-runner-2`: a `build` job (restore, Release build, `code-reviews/regen-readme.py --check`) and a -`unit-tests` job (the whole solution minus `Category=E2E|LiveIntegration`, trx → -`scripts/ci/assert-not-all-skipped.sh` → trx upload). Read run logs read-only with +`gitea-runner-2`. It has a single `unit-tests` job that restores and builds once (`-m:2`, restore with +`--disable-parallel`) and then tests the whole solution minus `Category=E2E|LiveIntegration` (SlowUnit +is included): the `code-reviews` README drift check, the TRX-guard fixtures, restore, Release build, a +runner-capacity log, `dotnet test` (trx), `scripts/ci/assert-not-all-skipped.sh`, then the trx upload. +A repo-wide `concurrency` group (`lmxopcua-v2-ci`, `cancel-in-progress: false`, #707) allows one active +run; an active run is never cancelled. The authoritative description of the worker model, test floor +and skip diagnostic is [`scripts/ci/README.md`](../scripts/ci/README.md). Read run logs read-only with `tea api --login /repos/dohertj2/lmxopcua/actions/runs` (then `…/runs//jobs`, `…/jobs//logs`). @@ -234,8 +238,11 @@ Things that are not obvious (#606): regardless of the tests. Do not "upgrade" it back to v4. - **`AKKA_TEST_TIMEFACTOR=3` on the test step.** The Runtime/ControlPlane actor-test harnesses (`tests/Server/*/Harness/TestTimeFactor.cs`) feed it to `akka.test.timefactor`, which dilates every - TestKit wait (explicit durations included). The leg runs every assembly at once on the runner; a long - tail of 2–8 s presence budgets each failed about one run in eight. Local runs stay at 1. + TestKit wait (explicit durations included). The test step is also serialized (`-m:1`, + `-p:TestTfmsInParallel=false`, `scripts/ci/ci.runsettings` caps xUnit at 2 collection workers, one + VSTest process) to reduce runner contention. The timefactor was added because a long tail of 2–8 s + presence budgets once each failed about one run in eight (a dated observation, not a current rate). + Local runs stay at 1. - **Presence vs absence.** A presence wait (`ExpectMsg`, `AwaitAssert`, a poll-until) is a ceiling and is sized from the suites' `PresenceBudget` (15 s); an absence window (`ExpectNoMsg`, settle-then- assert) is the assertion itself and keeps its short literal. Replace a fixed `Task.Delay` before an @@ -243,5 +250,9 @@ Things that are not obvious (#606): - **Never leave a script spinning.** A timed-out script is abandoned, not stopped (`TimedScriptEvaluator`), so `while(true){}` pinned a core for the rest of the test process. Timeout tests use a bounded wall-clock spin (`System.DateTime.UtcNow` is sandbox-allowed). -- **`MIN_EXECUTED`** (`assert-not-all-skipped.sh`) is still the default `1`; raise it once a green run - is recorded (a full run executes ~12.7k tests across ~57 trx files). +- **`MIN_EXECUTED`.** `assert-not-all-skipped.sh` defaults to `1` when the variable is unset (so a + local invocation only catches the zero-executed case), but the workflow's `assert not-all-skipped` + step overrides it with `MIN_EXECUTED: "12000"`, so the hosted gate is 12000. As a dated observation, + the verified baseline run 975 (2026-10-13) counted 14,630 executed tests across 62 trx files. The + step also prints an individual-skip diagnostic (`Results/UnitTestResult` records with outcome + `NotExecuted`); it does not affect the floor. Raise the floor as the suite grows.