Merge b647-ci: Gitea-compatible artifact upload + deterministic CI-flaky tests (#606)

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-08 20:45:50 -04:00
36 changed files with 476 additions and 132 deletions
+28
View File
@@ -217,3 +217,31 @@ and a real directory (LDAP) — never the dev values in this doc.
> The legacy Wonderware TCP/ArchestrA sidecar was retired; the historian backend is now the
> `ZB.MOM.WW.HistorianGateway` sidecar (see §6 and `docs/Historian.md`).
## 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
`tea api --login <login> /repos/dohertj2/lmxopcua/actions/runs` (then `…/runs/<id>/jobs`,
`…/jobs/<id>/logs`).
Things that are not obvious (#606):
- **`actions/upload-artifact` is pinned to `@v3` and `continue-on-error`.** act_runner reports as GHES,
and `upload-artifact@v4+` refuses GHES outright (`GHESNotSupportedError`), which failed every run
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.
- **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
assertion with a poll for the condition.
- **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).