# 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