Files
lmxopcua/.github/workflows/v2-ci.yml
T
Joseph Doherty 94926eb0d7
v2-ci / unit-tests (push) Has been cancelled
ci: fixture-backed integration workflow and guarded fleet E2E workflow (lmxopcua#757)
v2-integration.yml runs the Sql, Historian.SqlServer, Historian.QuestDb and OpcUaClient
integration projects against throwaway SQL Server/PostgreSQL/QuestDB/opc-plc containers
started by scripts/ci/integration-fixtures.sh, with a MIN_EXECUTED=440 floor. v2-e2e.yml is
manual/weekly, probes the shared fleet and skips cleanly when unreachable. v2-ci.yml is
functionally unchanged. Unverified on a hosted runner until first run.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
2026-11-09 16:53:44 -05:00

120 lines
6.4 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CI for the v2 branch — runs on every push + PR to the v2-akka-fuse / master
# 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
# still run in the unit-tests leg and Assert.Skip when their fixtures are unreachable.)
#
# Compatible with both GitHub Actions and Gitea Actions (act_runner). The .NET 10
# SDK is pinned via global.json at the repo root; if no global.json exists, the
# setup-dotnet step falls back to dotnet-version below.
name: v2-ci
on:
push:
branches: [v2-akka-fuse, master]
pull_request:
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:
unit-tests:
runs-on: ubuntu-latest
# #718: run 959 sat silent for 3h12m (no log after 13:39) until the server's own ~3h endless-task
# reaper failed it, with no hung test named. Every healthy run is ~60 min end to end (test step
# ~53 min), so 120 min fails a stall in half the time and cancels the step rather than waiting
# for the server reaper.
timeout-minutes: 120
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
# #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
- name: TRX skip guard fixtures
run: python3 scripts/ci/test-assert-not-all-skipped.py
# #707: bound project workers and avoid concurrent NuGet restore work.
- name: dotnet restore
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 -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
run: |
echo "nproc=$(nproc)"
free -m || true
uptime || true
# 07/S-1: ONE whole-solution leg instead of a hand-maintained 5-project matrix that
# silently dropped Client (388 tests), Analyzers (31), and every driver + most Core suite.
# Self-maintaining — a new *.Tests project is covered automatically, no matrix to widen —
# and matches CLAUDE.md's own `dotnet test ZB.MOM.WW.OtOpcUa.slnx` guidance. Excludes only
# the env-gated tiers: E2E (nightly, needs the docker-dev fleet) and LiveIntegration (needs
# a real gateway/PLC/VPN). Category=SlowUnit (Mqtt socket-timeout tests, #606) is deliberately NOT
# excluded here — it is a local-dev-loop opt-out only. The skip-gated *.IntegrationTests Assert.Skip when their fixtures
# 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). 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.
# #718: --blame-hang kills a test host whose single test makes no progress for 20 min and
# NAMES that test in the log (no dump: the runner has no createdump handling), so a hang is a
# located failure instead of hours of silence. Healthy tests finish in seconds.
env:
AKKA_TEST_TIMEFACTOR: "3"
run: >
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
--blame-hang --blame-hang-timeout 20m --blame-hang-dump-type none
# 07/S-2 fail-on-skip: a whole-solution run that executed ZERO tests is a masked outage
# (bad filter, broken discovery), not a pass — fail loudly. Runs even on test failure so
# the diagnostic is always emitted.
- name: assert not-all-skipped
if: always()
# #606: a whole-solution run executes ~13,000 tests; 12000 catches a project silently dropping out
# of discovery, not just the all-skipped case. Raise it as the suite grows.
env:
MIN_EXECUTED: "12000"
run: bash scripts/ci/assert-not-all-skipped.sh artifacts/trx/*.trx
# #606: pinned to v3. Gitea's act_runner reports itself as GHES, and @actions/artifact v2+
# (upload-artifact@v4+) refuses GHES outright ("GHESNotSupportedError") — so on Gitea the v4
# step failed EVERY run and the job could never go green, independent of the tests. v3 speaks
# the artifact API Gitea implements. continue-on-error because the trx upload is evidence, not a
# gate: the test step and the skip-gate above decide the job, and an artifact-store hiccup must
# not turn a green run red.
- name: upload trx
if: always()
continue-on-error: true
uses: actions/upload-artifact@v3
with:
name: unit-trx
path: artifacts/trx/*.trx
if-no-files-found: warn
# 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 the MIN_EXECUTED floor. Its only unique output was a report-only skip tally the unit
# leg's trx already contains. The fixture-backed leg now lives in its own
# workflow, v2-integration.yml (#757), and the guarded fleet E2E in v2-e2e.yml — kept out of this file
# so this job's runtime and flakiness are unchanged.