Tests and Coverage went red on the master push that merged spikersoft-backend PR #462 (run 17749). All 8,535+ unit tests pass, but the job exits 1 on 3 failures buried in the parallel test output, all in SpikerSoft.Common.Tests/Deployment/:
DockerMonitorSmokeTestUsesInitTests.TheSmokeTestRunLine_IsActuallyFound — expected 1 docker run … dm-smoke in spikersoft-docker-monitor.yml, found 0
DockerMonitorSmokeTestUsesInitTests.DockerMonitorSmokeTest_RunsTheContainerWithInit — smoke run line was ""
InfrastructureCheckoutIsPulledTests.TheDeployWorkflows_AreActuallyFound — expected >20 workflows containing cd /mnt/infrastructure/, found 8
Root cause
Not a deploy-safety regression. The workflows were refactored to a reusable pipeline (.gitea/workflows/_build-deploy-service.yml, a Gitea 1.27 workflow_call). The thin spikersoft-*.yml callers now delegate build→smoke→deploy→notify to it. The invariants these guard tests protect are intact but relocated:
The --init startup smoke test now lives in _build-deploy-service.yml as a generic svc-smoke container (not dm-smoke in docker-monitor.yml); docker-monitor just opts in via startup_smoke_seconds: '15'.
The pre-deploy sudo git -C /mnt/infrastructure pull + deploying from: echo + cd /mnt/infrastructure/<stack> also moved into the reusable pipeline. Only the ~8 unmigrated standalone deployers (api + single-arch group) plus the reusable file itself still inline cd /mnt/infrastructure/, so discovery dropped from ~29 to 8.
The guards were left pointing at the old per-service layout after the refactor had already landed, so they tripped their own "if I find nothing I'm vacuous → fail" tripwires on the next master merge.
Fix
Re-point the guards at the invariant's new home (the reusable pipeline), preserving AGENTS.md non-negotiable #4:
Smoke tests read _build-deploy-service.yml and match svc-smoke, keep the --init check, and add a guard that docker-monitor still opts into the smoke step.
TheDeployWorkflows_AreActuallyFound asserts the reusable pipeline is discovered (the invariant that never shrinks as more callers migrate) instead of a brittle >20 count.
Known follow-up (not in this fix)
A new inline deployer that skips the pull is still caught (it lands in DeployWorkflows() and the theory fails). What nothing catches is a thin caller wired to a different, unguarded reusable file — mis-routing has no test. Worth a follow-up guard that every thin caller's uses: points at _build-deploy-service.yml.
## Symptom
`Tests and Coverage` went red on the master push that merged spikersoft-backend PR #462 (run [17749](https://git.spikersoft.com/spikerj/spikersoft-backend/actions/runs/17749/jobs/68529)). All 8,535+ unit tests pass, but the job exits 1 on **3 failures** buried in the parallel test output, all in `SpikerSoft.Common.Tests/Deployment/`:
- `DockerMonitorSmokeTestUsesInitTests.TheSmokeTestRunLine_IsActuallyFound` — expected 1 `docker run … dm-smoke` in `spikersoft-docker-monitor.yml`, found **0**
- `DockerMonitorSmokeTestUsesInitTests.DockerMonitorSmokeTest_RunsTheContainerWithInit` — smoke run line was `""`
- `InfrastructureCheckoutIsPulledTests.TheDeployWorkflows_AreActuallyFound` — expected >20 workflows containing `cd /mnt/infrastructure/`, found **8**
## Root cause
Not a deploy-safety regression. The workflows were refactored to a **reusable pipeline** (`.gitea/workflows/_build-deploy-service.yml`, a Gitea 1.27 `workflow_call`). The thin `spikersoft-*.yml` callers now delegate build→smoke→deploy→notify to it. The invariants these guard tests protect are **intact but relocated**:
- The `--init` startup smoke test now lives in `_build-deploy-service.yml` as a generic `svc-smoke` container (not `dm-smoke` in `docker-monitor.yml`); docker-monitor just opts in via `startup_smoke_seconds: '15'`.
- The pre-deploy `sudo git -C /mnt/infrastructure pull` + `deploying from:` echo + `cd /mnt/infrastructure/<stack>` also moved into the reusable pipeline. Only the ~8 unmigrated standalone deployers (api + single-arch group) plus the reusable file itself still inline `cd /mnt/infrastructure/`, so discovery dropped from ~29 to 8.
The guards were left pointing at the old per-service layout after the refactor had already landed, so they tripped their own "if I find nothing I'm vacuous → fail" tripwires on the next master merge.
## Fix
Re-point the guards at the invariant's new home (the reusable pipeline), preserving AGENTS.md non-negotiable #4:
- Smoke tests read `_build-deploy-service.yml` and match `svc-smoke`, keep the `--init` check, and add a guard that docker-monitor still opts into the smoke step.
- `TheDeployWorkflows_AreActuallyFound` asserts the reusable pipeline is discovered (the invariant that never shrinks as more callers migrate) instead of a brittle `>20` count.
## Known follow-up (not in this fix)
A new *inline* deployer that skips the pull is still caught (it lands in `DeployWorkflows()` and the theory fails). What nothing catches is a thin caller wired to a *different, unguarded* reusable file — mis-routing has no test. Worth a follow-up guard that every thin caller's `uses:` points at `_build-deploy-service.yml`.
Fixed and verified. spikersoft-backend commit 09a555b1 — "test(deploy-guards): re-point at reusable pipeline after workflow refactor (#815)" — is on master.
Verified on master today: the guards now target the reusable pipeline (DockerMonitorSmokeTestUsesInitTests matches docker run … svc-smoke in _build-deploy-service.yml, and InfrastructureCheckoutIsPulledTests accounts for the ~8 unmigrated standalone deployers plus the reusable file itself via a ReusablePipeline constant). Ran them locally:
Backend master CI is green. The invariants the guards protect (the --init startup smoke container and the pre-deploy /mnt/infrastructure pull) are still asserted — just at their new home — so this was resolved without weakening the tripwires. Closing.
— Opus 5 Agent
Fixed and verified. spikersoft-backend commit `09a555b1` — "test(deploy-guards): re-point at reusable pipeline after workflow refactor (#815)" — is on master.
Verified on master today: the guards now target the reusable pipeline (`DockerMonitorSmokeTestUsesInitTests` matches `docker run … svc-smoke` in `_build-deploy-service.yml`, and `InfrastructureCheckoutIsPulledTests` accounts for the ~8 unmigrated standalone deployers plus the reusable file itself via a `ReusablePipeline` constant). Ran them locally:
```
dotnet test SpikerSoft.Common.Tests --filter FullyQualifiedName~Deployment
Passed! - Failed: 0, Passed: 53, Skipped: 0, Total: 53
```
Backend master CI is green. The invariants the guards protect (the `--init` startup smoke container and the pre-deploy `/mnt/infrastructure` pull) are still asserted — just at their new home — so this was resolved without weakening the tripwires. Closing.
— Opus 5 Agent
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Symptom
Tests and Coveragewent red on the master push that merged spikersoft-backend PR #462 (run 17749). All 8,535+ unit tests pass, but the job exits 1 on 3 failures buried in the parallel test output, all inSpikerSoft.Common.Tests/Deployment/:DockerMonitorSmokeTestUsesInitTests.TheSmokeTestRunLine_IsActuallyFound— expected 1docker run … dm-smokeinspikersoft-docker-monitor.yml, found 0DockerMonitorSmokeTestUsesInitTests.DockerMonitorSmokeTest_RunsTheContainerWithInit— smoke run line was""InfrastructureCheckoutIsPulledTests.TheDeployWorkflows_AreActuallyFound— expected >20 workflows containingcd /mnt/infrastructure/, found 8Root cause
Not a deploy-safety regression. The workflows were refactored to a reusable pipeline (
.gitea/workflows/_build-deploy-service.yml, a Gitea 1.27workflow_call). The thinspikersoft-*.ymlcallers now delegate build→smoke→deploy→notify to it. The invariants these guard tests protect are intact but relocated:--initstartup smoke test now lives in_build-deploy-service.ymlas a genericsvc-smokecontainer (notdm-smokeindocker-monitor.yml); docker-monitor just opts in viastartup_smoke_seconds: '15'.sudo git -C /mnt/infrastructure pull+deploying from:echo +cd /mnt/infrastructure/<stack>also moved into the reusable pipeline. Only the ~8 unmigrated standalone deployers (api + single-arch group) plus the reusable file itself still inlinecd /mnt/infrastructure/, so discovery dropped from ~29 to 8.The guards were left pointing at the old per-service layout after the refactor had already landed, so they tripped their own "if I find nothing I'm vacuous → fail" tripwires on the next master merge.
Fix
Re-point the guards at the invariant's new home (the reusable pipeline), preserving AGENTS.md non-negotiable #4:
_build-deploy-service.ymland matchsvc-smoke, keep the--initcheck, and add a guard that docker-monitor still opts into the smoke step.TheDeployWorkflows_AreActuallyFoundasserts the reusable pipeline is discovered (the invariant that never shrinks as more callers migrate) instead of a brittle>20count.Known follow-up (not in this fix)
A new inline deployer that skips the pull is still caught (it lands in
DeployWorkflows()and the theory fails). What nothing catches is a thin caller wired to a different, unguarded reusable file — mis-routing has no test. Worth a follow-up guard that every thin caller'suses:points at_build-deploy-service.yml.Fixed and verified. spikersoft-backend commit
09a555b1— "test(deploy-guards): re-point at reusable pipeline after workflow refactor (#815)" — is on master.Verified on master today: the guards now target the reusable pipeline (
DockerMonitorSmokeTestUsesInitTestsmatchesdocker run … svc-smokein_build-deploy-service.yml, andInfrastructureCheckoutIsPulledTestsaccounts for the ~8 unmigrated standalone deployers plus the reusable file itself via aReusablePipelineconstant). Ran them locally:Backend master CI is green. The invariants the guards protect (the
--initstartup smoke container and the pre-deploy/mnt/infrastructurepull) are still asserted — just at their new home — so this was resolved without weakening the tripwires. Closing.— Opus 5 Agent