ci(TST-35): run gateway suite on windev nightly
ci / nightly-windev (push) Has been skipped
ci / java (push) Successful in 2m44s
ci / windows-x86 (push) Successful in 5m56s
ci / portable (push) Failing after 9m21s

This commit is contained in:
Joseph Doherty
2026-08-25 11:56:35 -04:00
parent ad79238c84
commit cc143b52cf
6 changed files with 80 additions and 16 deletions
+6 -6
View File
@@ -4,16 +4,16 @@
# .NET Framework 4.8 / x86 and need MXAccess COM installed, so they build ONLY on a Windows host.
# They are out of scope for this Linux `portable` job — the `windows-x86` job below builds and
# tests them on windev (10.100.0.48) over SSH (see scripts/ci/run-windev-ci.sh), and the nightly
# `nightly-windev` job additionally runs the live-MXAccess smoke, which is scheduled-only so it
# never gates a push.
# `nightly-windev` job additionally runs the full solution build, gateway suite, and live-MXAccess
# smoke, which are scheduled-only so they never gate a push.
name: ci
on:
push:
pull_request:
schedule:
# 06:00 UTC nightly: the `nightly-windev` job re-runs the x86 Worker build + full Worker.Tests on
# windev, then the live-MXAccess smoke (MXGATEWAY_RUN_LIVE_MXACCESS_TESTS=1) and a full-slnx build.
# 06:00 UTC nightly: x86 Worker build + Worker.Tests, full-slnx build, gateway tests, then the
# live-MXAccess smoke (MXGATEWAY_RUN_LIVE_MXACCESS_TESTS=1), serialized on windev's host lock.
# Push/PR runs skip it — the job is gated `if: github.event_name == 'schedule'`.
- cron: '0 6 * * *'
@@ -182,7 +182,7 @@ jobs:
run: ./scripts/ci/run-windev-ci.sh test
nightly-windev:
# TST-25: scheduled deep run — full Worker.Tests + live-MXAccess smoke + full-slnx build on windev.
# TST-35: scheduled deep run — Worker, full-slnx, gateway, and live-smoke tiers on windev.
# Gated to the schedule event via `if:` (not an unsatisfiable `runs-on`), so push/PR runs mark it
# skipped, not queued. Never gates a push. On failure it opens a Gitea issue so a red nightly is
# visible even though nobody watches the Actions page.
@@ -198,7 +198,7 @@ jobs:
PUBLIC_SERVER_URL: https://gitea.dohertylan.com
steps:
- uses: actions/checkout@v4
- name: Full Worker.Tests + live-MXAccess smoke on windev
- name: Worker + gateway tests + live-MXAccess smoke on windev
env:
# WINDEV_SSH_KEY is stored base64-encoded (single line) so Gitea's line-oriented secret
# masker redacts it in the step env echo; run-windev-ci.sh decodes it. A raw multiline PEM
@@ -111,7 +111,7 @@ The continuation runs serially in the isolated `.worktrees/c3-p2-followups` work
| J — secondary contracts | IPC-36/37 | `gpt-5.6-sol` high | Done | Shared launch constants and descriptor parity tests green |
| K — client alarm parity | CLI-47/48/49/50 | `gpt-5.6-terra` high | Done | All five client suites green |
| L — live watch-list/proto wave | watch-list refresh follow-up + WRK-32 proto comment | `gpt-5.6-sol` high | Done | Codegen clean; portable alarm/contract tests green; windev Worker.Tests green |
| M — Windows gateway CI | TST-35 | `gpt-5.6-terra` medium | Not started | windev `live` mode proves Worker, gateway, full-slnx, and live smoke tiers |
| M — Windows gateway CI | TST-35 | `gpt-5.6-terra` medium | In progress | windev `live` mode proves Worker, gateway, full-slnx, and live smoke tiers |
| N — integration and release | publish five clients + Contracts | `gpt-5.6-sol` high | Not started | Full local/windev gates; merged `main`; registry coordinates and Go tag verified |
### Continuation tasklist
+7 -5
View File
@@ -650,11 +650,13 @@ runtime because the x86 Worker cannot build on Linux:
the tier is down, not the change**: an unreachable windev fails the job (never skips), so
if it goes red without a related code change, check the tier — `ssh windev`, read
`C:\build\mxaccessgw-ci\ci.log` — before assuming a real test failure.
- **`nightly-windev`** (Linux runner, scheduled `0 6 * * *`) — re-runs the full x86 build +
Worker.Tests on windev, then the live-MXAccess smoke (`MXGATEWAY_RUN_LIVE_MXACCESS_TESTS=1`)
and a full `slnx` build (which surfaces Windows-only analyzer diagnostics such as
`xUnit1030`). Gated `if: github.event_name == 'schedule'`, so it never gates a push. On
failure it opens a Gitea issue via the Actions token, since nobody watches the Actions page.
- **`nightly-windev`** (Linux runner, scheduled `0 6 * * *`) — runs, in order, the x86 Worker
build, `Worker.Tests`, a full `slnx` build (which surfaces Windows-only analyzer diagnostics
such as `xUnit1030`), the net10 gateway suite, and the live-MXAccess smoke
(`MXGATEWAY_RUN_LIVE_MXACCESS_TESTS=1`). The checkout and all five tiers share the windev
host lock, and the first nonzero native exit stops the sequence and propagates to the CI job.
Gated `if: github.event_name == 'schedule'`, so it never gates a push. On failure it opens a
Gitea issue via the Actions token, since nobody watches the Actions page.
### Runner capacity is shared and finite
+6 -2
View File
@@ -11,11 +11,15 @@ code back so a regression turns the job red.
| File | Runs on | Role |
|---|---|---|
| `run-windev-ci.sh <build\|test\|live>` | Linux CI job | Writes the SSH key/known-hosts, base64-encodes a bootstrap, SSHes to windev, returns the remote exit code. |
| `windev-worker-ci.ps1 -Sha -Mode` | windev | Locks the CI clone, checks out the SHA, runs the x86 build / `Worker.Tests` / live smoke. |
| `windev-worker-ci.ps1 -Sha -Mode` | windev | Locks the CI clone, checks out the SHA, and runs the requested cumulative Windows tiers. |
| `windev.known_hosts` | committed | Pinned windev host keys so `StrictHostKeyChecking=yes` has no TOFU prompt. Host keys are public; committing is intentional. |
Modes are cumulative: `build` = x86 Worker build; `test` = build + `Worker.Tests`;
`live` = test + full-`slnx` build + live-MXAccess smoke (`MXGATEWAY_RUN_LIVE_MXACCESS_TESTS=1`).
`live` = test + full-`slnx` build + the net10 gateway suite + live-MXAccess smoke
(`MXGATEWAY_RUN_LIVE_MXACCESS_TESTS=1`). The `live` order is x86 Worker build,
`Worker.Tests`, full solution build, gateway tests, then live smoke. One host lock covers
checkout and every tier, so concurrent runs cannot overlap; each native command is checked
immediately and the first nonzero exit aborts the remaining tiers and propagates to CI.
CI jobs (`.gitea/workflows/ci.yml`): `windows-x86` runs `test` per push/PR; `nightly-windev`
runs `live` on the `0 6 * * *` schedule and opens a Gitea issue on failure.
+7 -2
View File
@@ -16,8 +16,8 @@
Modes (cumulative):
build x86 Worker build only (net48/CS0246/x86 compile guard — always fast).
test build + Worker.Tests (x86). The per-push default.
live test + the live-MXAccess smoke (MXGATEWAY_RUN_LIVE_MXACCESS_TESTS=1) and a full
slnx build (surfaces Windows-only analyzer diagnostics, e.g. xUnit1030). Nightly.
live test + full slnx build + the net10 gateway suite + the live-MXAccess smoke
(MXGATEWAY_RUN_LIVE_MXACCESS_TESTS=1). Nightly.
Runs under Windows PowerShell 5.1 (`powershell.exe`), so it avoids PS7-only syntax and
checks $LASTEXITCODE after every native command rather than relying on stderr-as-error
@@ -112,6 +112,7 @@ try {
$workerProj = 'src/ZB.MOM.WW.MxGateway.Worker/ZB.MOM.WW.MxGateway.Worker.csproj'
$workerTests = 'src/ZB.MOM.WW.MxGateway.Worker.Tests/ZB.MOM.WW.MxGateway.Worker.Tests.csproj'
$gatewayTests = 'src/ZB.MOM.WW.MxGateway.Tests/ZB.MOM.WW.MxGateway.Tests.csproj'
$integrationTests = 'src/ZB.MOM.WW.MxGateway.IntegrationTests/ZB.MOM.WW.MxGateway.IntegrationTests.csproj'
# build: always. The x86/net48 compile is the floor guard (catches CS0246 on
@@ -127,6 +128,10 @@ try {
# that never fire on the macOS/Linux NonWindows build.
Invoke-Native 'full slnx build' { dotnet build src/ZB.MOM.WW.MxGateway.slnx -c Release }
Invoke-Native 'gateway tests on Windows' {
dotnet test $gatewayTests -c Release --no-build
}
$env:MXGATEWAY_RUN_LIVE_MXACCESS_TESTS = '1'
try {
Invoke-Native 'live-MXAccess smoke' {
@@ -0,0 +1,53 @@
namespace ZB.MOM.WW.MxGateway.Tests.ProjectStructure;
public sealed class WindevCiContractTests
{
[Fact]
public void LiveMode_RunsWindowsTiersInDocumentedOrder()
{
DirectoryInfo repositoryRoot = FindRepositoryRoot();
string script = File.ReadAllText(
Path.Combine(repositoryRoot.FullName, "scripts", "ci", "windev-worker-ci.ps1"));
string[] orderedSteps =
[
"Invoke-Native 'x86 Worker build'",
"Invoke-Native 'x86 Worker.Tests'",
"Invoke-Native 'full slnx build'",
"Invoke-Native 'gateway tests on Windows'",
"Invoke-Native 'live-MXAccess smoke'",
];
int previousIndex = -1;
foreach (string step in orderedSteps)
{
int currentIndex = script.IndexOf(step, StringComparison.Ordinal);
Assert.True(currentIndex >= 0, $"Missing windev live-mode step: {step}");
Assert.True(currentIndex > previousIndex, $"Windev live-mode step is out of order: {step}");
previousIndex = currentIndex;
}
Assert.Contains(
"dotnet test $gatewayTests -c Release --no-build",
script,
StringComparison.Ordinal);
}
private static DirectoryInfo FindRepositoryRoot()
{
DirectoryInfo? current = new(AppContext.BaseDirectory);
while (current is not null)
{
if (File.Exists(Path.Combine(current.FullName, "CLAUDE.md"))
&& Directory.Exists(Path.Combine(current.FullName, "src"))
&& Directory.Exists(Path.Combine(current.FullName, "scripts")))
{
return current;
}
current = current.Parent;
}
throw new InvalidOperationException("Could not locate the repository root from the test output directory.");
}
}