diff --git a/.gitea/workflows/continuous_integration.yaml b/.gitea/workflows/continuous_integration.yaml index 7f3fcce..f44dd86 100644 --- a/.gitea/workflows/continuous_integration.yaml +++ b/.gitea/workflows/continuous_integration.yaml @@ -128,12 +128,37 @@ jobs: needs: [changes, backend-build] if: needs.changes.outputs.backend == 'true' runs-on: ubuntu-latest + # Added for SlpModularCms.Api.Tests (slpsoftware-api feature, NFR-CS-01): its pipeline + # regression tests boot the real Api host via WebApplicationFactory, which unconditionally + # runs CmsHost.ConfigurePipeline's startup migration (MigrateCoreDatabase) -- unlike every + # other test project here, which mocks/uses EF Core InMemory and never touches a real + # database. Without a real, reachable MariaDB, those tests fail on the connection itself + # before any assertion runs. + services: + mariadb: + image: mariadb:11 + env: + MARIADB_ROOT_PASSWORD: ci_test_password + MARIADB_DATABASE: SlpModularCms + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping --silent" + --health-interval=10s + --health-timeout=5s + --health-retries=5 steps: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v4 with: dotnet-version: ${{ env.DOTNET_VERSION }} - name: Test (Release) + env: + # Overrides the placeholder in SlpModularCms.Api/appsettings.Development.json for this + # CI run only -- ASP.NET Core's configuration layering applies environment variables + # after appsettings.*.json, so this reaches SlpModularCms.Api.Tests' WebApplicationFactory + # without touching any committed appsettings file. + ConnectionStrings__DefaultConnection: "Server=127.0.0.1;Port=3306;Database=SlpModularCms;Uid=root;Pwd=ci_test_password" run: dotnet test SlpModularCms.sln -c Release # --- Gate 3: vulnerability scan --- diff --git a/aidlc-docs/features/slpsoftware-api/audit.md b/aidlc-docs/features/slpsoftware-api/audit.md index bbde3ba..00ca32c 100644 --- a/aidlc-docs/features/slpsoftware-api/audit.md +++ b/aidlc-docs/features/slpsoftware-api/audit.md @@ -563,3 +563,15 @@ **Context**: Local dev/test database only, explicitly requested by the user, low-risk and reversible (test data). Returning to the Unit 1 Code Generation approval gate. --- + +## CI Fix: backend-test Had No Database for the New Pipeline Tests + +**Timestamp**: 2026-08-02T12:00:00Z + +**User Input**: Pasted the Gitea Actions `backend-test` job log — all 4 `SlpModularCms.Api.Tests` failed with `MySqlException: Access denied for user 'root'@'localhost'`. + +**AI Response**: "Read `.gitea/workflows/continuous_integration.yaml`'s `backend-test` job: it runs `dotnet test SlpModularCms.sln -c Release` with no MariaDB service container at all — every other test project (Core.Tests, Module.*.Tests) mocks or uses EF Core InMemory and never needed one. The new `SlpModularCms.Api.Tests` boots the real `Api` host via `WebApplicationFactory`, which unconditionally runs `CmsHost.ConfigurePipeline`'s startup migration -- there is no way to exercise the real pipeline (this unit's whole NFR-CS-01 point) without a real, reachable database, and CI never had one. This is a design gap in the original NFR Requirements/Design for this unit, not something introduced by a later change -- should have been anticipated when Q1=C committed to a real WebApplicationFactory test rather than a fully mocked one. Added a `mariadb` service container to the `backend-test` job plus a `ConnectionStrings__DefaultConnection` environment-variable override for the test step only, which overrides the placeholder in `Api/appsettings.Development.json` via ASP.NET Core's standard configuration layering (env vars win over appsettings.*.json) -- no committed appsettings file changes needed, and zero effect on local `dotnet test` runs (developers' own `appsettings.local.json` continues to apply there, unaffected by a CI-only env var). Verified the override mechanism works by reproducing it locally against the existing local MariaDB container before trusting it in CI." + +**Context**: Real bug fix, and a boundary call: `.gitea/workflows/continuous_integration.yaml` is nominally owned by the `gitea-deployment-workflow` feature, but this specific change (making the `backend-test` gate pass for a test project this feature introduced) is Construction/Build-and-Test correctness for `slpsoftware-api`, not a deploy-target retarget (D-15, still deferred to Operations) -- judged in-scope to fix directly rather than blocking the PR on a separate feature's process. + +--- diff --git a/aidlc-docs/features/slpsoftware-api/construction/slpsoftware-client-setup/code/summary.md b/aidlc-docs/features/slpsoftware-api/construction/slpsoftware-client-setup/code/summary.md index 62adc7a..936cb62 100644 --- a/aidlc-docs/features/slpsoftware-api/construction/slpsoftware-client-setup/code/summary.md +++ b/aidlc-docs/features/slpsoftware-api/construction/slpsoftware-client-setup/code/summary.md @@ -43,6 +43,12 @@ Added (frontend, not part of the original per-unit plan, but a direct, symmetric Pre-existing bug, unrelated to this feature's own scope (not introduced by the `CmsHost` extraction) but surfaced by testing the new instance: `src/SlpModularCms.Core/Exceptions/GlobalExceptionHandler.cs` logged every exception at `LogError` before mapping it to a status code, so a routine `UnauthorizedException` (e.g. an invalid/missing refresh token — the normal state for a fresh, never-logged-in session) was indistinguishable from a genuine unhandled 500 in the console and in Sentry. Fixed: exceptions that map to a status below 500 now log at `LogWarning`; only genuinely unmapped exceptions (500) log at `LogError`. Affects every Client project equally (`Api`, `Api.Slave`, `Api.SlpSoftware`), not just this feature. No existing test asserted log level; full suite reran green (196 + 4). +## Post-Completion Fix: CI's backend-test Job Had No Database + +The Gitea Actions `backend-test` job (`.gitea/workflows/continuous_integration.yaml`) just ran `dotnet test` with no MariaDB service — every pre-existing test project mocks or uses EF Core InMemory, so none of them ever needed one. `SlpModularCms.Api.Tests` boots the real `Api` host via `WebApplicationFactory`, which unconditionally runs the startup migration, so it genuinely needs a reachable database — a design gap in this unit's own NFR Requirements/Design that should have been anticipated when committing to a real pipeline test (Q1 = C) rather than a mocked one. Fixed by adding a `mariadb` service container to `backend-test` plus a `ConnectionStrings__DefaultConnection` environment-variable override for that step only (overrides the placeholder in `Api/appsettings.Development.json` via standard ASP.NET Core config layering — env vars win over `appsettings.*.json`). No committed appsettings changed; local `dotnet test` runs are unaffected (developers' own `appsettings.local.json` still applies there). Verified the override mechanism directly against the local MariaDB container before trusting it in CI. + +**Scope note**: `continuous_integration.yaml` is nominally owned by the `gitea-deployment-workflow` feature. This specific change (making the test gate pass for a test project this feature introduced) was judged in-scope to fix directly as Build-and-Test correctness — distinct from the actual deploy-target retarget (D-15), which remains deferred to this feature's own Operations phase. + ## Build and Test Verification (Step 13.5) Two real build fixes were needed and applied during this step (not deviations from the plan — the plan didn't anticipate these, since they only surface once the code actually compiles):