Files
lmxopcua/.github/workflows/v2-integration.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

98 lines
4.7 KiB
YAML

# Fixture-backed integration leg (#757 item b). UNVERIFIED on a hosted runner until its first run.
#
# Separate from v2-ci.yml on purpose: the 60-minute whole-solution unit-tests job is untouched, so
# it gets no slower or flakier. This workflow builds ONLY the five fixture-backed *.IntegrationTests
# projects and runs them against THROWAWAY containers that the job itself creates and removes
# (scripts/ci/integration-fixtures.sh): SQL Server 2022, PostgreSQL 17 (seeded), QuestDB and the public
# opc-plc image. Nothing here touches the shared 10.100.0.35 host, so CI does not depend on that box.
#
# Explicit `docker run` steps rather than a `services:` block: whether the Gitea act_runner honours
# `services:` (and makes service ports reachable from the job) is not documented in infra/README.md §10,
# and the Sql/Postgres fixtures need a post-start seed step anyway. The script needs only a reachable
# docker daemon on the runner.
#
# Gate: MIN_EXECUTED turns a fixture outage (every test Assert.Skip-ing) into a RED job instead of a
# silent green, which is the whole point of this leg. Not covered here (no public/pullable image or
# needs credentials/TLS): Modbus/S7/AB/FOCAS/TwinCAT sims, Mqtt, MTConnect, Oracle, Host real-infra mode.
name: v2-integration
# Triggers start CONSERVATIVE (manual + nightly) because the shared runner is already heavily loaded
# (#718: load avg ~35-51 on 22 cores during unit-tests) and this leg is unverified on it. Once the first
# hosted runs are green and the runner has headroom, widen to push/PR on master (paths below).
# push: { branches: [master] }
# pull_request: { branches: [master], paths: ["src/Drivers/**", "src/Core/**", "tests/Drivers/**", "scripts/ci/**", ".github/workflows/v2-integration.yml"] }
on:
workflow_dispatch: {}
schedule:
- cron: "41 2 * * *"
# Own group (not lmxopcua-v2-ci): sharing it would let a pending integration run supersede a pending
# unit-tests run (Gitea supersedes pending runs per group). Same semantics as v2-ci: one active run,
# an active run is never cancelled.
concurrency:
group: lmxopcua-v2-integration
cancel-in-progress: false
env:
DOTNET_NOLOGO: "1"
DOTNET_CLI_TELEMETRY_OPTOUT: "1"
jobs:
integration-tests:
runs-on: ubuntu-latest
# #718: bound a stall. Expected runtime is well under an hour (image pulls + 5 small projects);
# the per-test --blame-hang below names a hung test, this cancels the job if even that fails.
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
- name: docker available
run: docker version --format '{{.Server.Version}}'
- name: start throwaway fixtures
run: bash scripts/ci/integration-fixtures.sh up
- name: dotnet test (fixture-backed integration projects)
env:
# Mirrors the unit-tests leg: one worker, bounded xUnit parallelism, hang killer.
INTEGRATION_PROJECTS: >-
Driver.Sql Driver.Historian.SqlServer Driver.Historian.QuestDb
Driver.OpcUaClient Driver.OpcUaClient.Browser
run: |
set -euo pipefail
for p in $INTEGRATION_PROJECTS; do
dotnet test "tests/Drivers/ZB.MOM.WW.OtOpcUa.$p.IntegrationTests/ZB.MOM.WW.OtOpcUa.$p.IntegrationTests.csproj" \
--configuration Release -m:1 --settings scripts/ci/ci.runsettings \
--filter "Category!=E2E&Category!=LiveIntegration" \
--logger "trx;LogFileName=$p.trx" --results-directory artifacts/trx \
--blame-hang --blame-hang-timeout 20m --blame-hang-dump-type none
done
# A fixture that never came up Assert.Skip()s every test and would otherwise pass. The floor is set
# from a local run against the same containers (see scripts/ci/README.md); raise it as suites grow.
- name: assert not-all-skipped
if: always()
env:
MIN_EXECUTED: "440"
run: bash scripts/ci/assert-not-all-skipped.sh artifacts/trx/*.trx
- name: fixture logs on failure
if: failure()
continue-on-error: true
run: |
for c in otopcua-ci-mssql otopcua-ci-pg otopcua-ci-questdb otopcua-ci-opcplc; do
echo "=== $c ==="; docker logs --tail 40 "$c" 2>&1 || true
done
- name: stop fixtures
if: always()
continue-on-error: true
run: bash scripts/ci/integration-fixtures.sh down
# v3 on purpose — see v2-ci.yml (act_runner reports as GHES; upload-artifact@v4+ refuses it).
- name: upload trx
if: always()
continue-on-error: true
uses: actions/upload-artifact@v3
with:
name: integration-trx
path: artifacts/trx/*.trx
if-no-files-found: warn