Skip to content

Speed up CI and format and lint CLI commands#895

Open
tjementum wants to merge 10 commits into
mainfrom
pp-1209-share-webapplicationfactory-across-tests
Open

Speed up CI and format and lint CLI commands#895
tjementum wants to merge 10 commits into
mainfrom
pp-1209-share-webapplicationfactory-across-tests

Conversation

@tjementum
Copy link
Copy Markdown
Member

@tjementum tjementum commented May 14, 2026

Summary & Motivation

Three coordinated changes that cut CI critical path roughly in half and speed up local format and lint runs.

Test infrastructure

BackOfficeEndpointBaseTest and EndpointBaseTest<TContext> each constructed a fresh WebApplicationFactory<Program> per test instance. Combined with Meziantou.Xunit.ParallelTestFramework, every account-API test booted a complete ASP.NET Core host: full DI container, all singletons, test server. With 27 BackOffice classes and ~60 Account API classes, every CI run paid hundreds of cold-starts, and the cost grew with every test added.

Both test bases now share one host per test class via xUnit's IClassFixture<...>:

  • BackOffice — new BackOfficeWebApplicationFactory + BackOfficeTestContext route per-test state (SqliteConnection, telemetry collector, MockStripeState) through an AsyncLocal. 26 derived test classes use the fixture via primary constructor + IClassFixture<BackOfficeWebApplicationFactory>. BackOfficeBlobProxyTests carries a derived factory to keep its IBlobStorageClient substitute.
  • Account API — new AccountWebApplicationFactory + AccountTestContext mirror the same pattern (adds per-test IEmailClient routing). 60 derived test classes converted. CompleteEmailSignupTests carries a derived factory for its logger override.
  • MockStripeState is re-registered as transient in the test host so per-request resolution reads the per-test instance from the accessor.
  • TestServer.PreserveExecutionContext enabled so the AsyncLocal flows from the calling test into request handling.
  • Env vars and the SPA-shell file copy moved into the fixture constructor (one-time setup).

Single Code Style workflow

A new code-style.yml replaces the per-SCS code-style work in account.yml, main.yml, app-gateway.yml. One workflow, four jobs:

  • detect-scope — small first job that classifies the diff and outputs the backend scope and format mode for the downstream jobs (inline git diff, no third-party action).
  • code-linting — backend inspectcode + frontend build + frontend lint (oxlint).
  • code-formatting — backend cleanupcode + frontend format check (oxfmt).
  • sonarcloud — runs once per push against application/PlatformPlatform.slnx (was previously running three times per push, once per SCS).

Backend lint and format are scoped to a single SCS via --self-contained-system <name> when the diff touches only that SCS; cross-cutting changes (shared-kernel, AppGateway, multi-SCS) fall back to the full solution.

Faster format and lint

  • The developer CLI format command defaults to changed-only. Cleanupcode runs against .cs files diffed vs origin/main; explicit --all-files for full sweep. CI auto-flips to --all-files when application/dotnet-tools.json changes (JetBrains tool upgrades reset the format ruleset, so accumulated drift in untouched files needs a full pass).
  • The developer CLI lint --changed-only flag is opt-in (default = full). Recommended for routine local runs; CI always lints the full solution because inspectcode has cross-file rules. The lint skill documents when to omit --changed-only (cross-cutting changes that affect untouched files).
  • Removed the workaround that generated a temporary .slnf from each .slnx to feed cleanupcode — JetBrains 2026.1 accepts .slnx directly.

Database Plan reuses Build and Test artifacts

build-and-test uploads application/**/bin and application/**/obj as a <scs>-build artifact (only when staging is enabled). _migrate-database.yml downloads it into application/ and runs dotnet restore for the NuGet cache, skipping the redundant checkout + setup + dotnet build chain.

CI benchmark

Comparing real PR-sync workflow durations on a comparable sister branch (PR #888, n=8 per workflow) against this branch (n=3 per workflow, mean):

Workflow BEFORE (PR #888 sync, median) AFTER (this branch) Δ
Account 9m00s 6m16s -30%
Main 6m41s 5m47s -13%
AppGateway 7m26s 1m07s -85%
Code Style - 4m40s new — does not extend critical path
Critical path per push 9m00s 6m16s -30%
Total CI minutes per push 23m07s 17m50s -23%

The AppGateway delta is large because code-linting and code-formatting were removed from app-gateway.yml entirely — they live in the consolidated code-style.yml now. AppGateway PR runs are just build + test.

Note for downstream projects

Downstream projects with a substantial Main SCS will see a bigger lift than this benchmark suggests. The slowest single CI step used to be backend cleanupcode; it now only inspects changed .cs files. Evidence: Main and Account workflows now sit at roughly the same wall-clock (5m47s vs 6m16s) even though Account has materially more code than Main. The fixed-cost setup (npm + dotnet restore + build) dominates once the format pass is changed-only, so SCS size matters less than it used to.

Test-step benchmark (isolated)

To isolate the impact of the test-host refactor alone, I temporarily disabled the Code Style and Database Staging jobs and measured just Run Tests with SonarScanner Analysis (5 samples per side):

Run 1 Run 2 Run 3 Run 4 Run 5 Mean Stddev
AFTER (BackOffice + Account shared host) 2m18s 2m26s 2m21s 2m21s 2m21s 2m21s 2.9s
BEFORE (per-test host, baseline) 3m46s 3m51s 3m38s 3m41s 3m54s 3m46s 6.7s

Δ −37% on the test step alone, and stddev more than halves — the runs are markedly more stable too.

Checklist

  • I have added tests, or done manual regression tests
  • I have updated the documentation, if necessary

@tjementum tjementum added the Enhancement New feature or request label May 14, 2026
@tjementum tjementum self-assigned this May 14, 2026
@linear
Copy link
Copy Markdown

linear Bot commented May 14, 2026

PP-1209

@tjementum tjementum closed this May 14, 2026
@tjementum tjementum force-pushed the pp-1209-share-webapplicationfactory-across-tests branch from 0440bae to 1da4403 Compare May 14, 2026 10:02
@tjementum tjementum reopened this May 14, 2026
@tjementum tjementum force-pushed the pp-1209-share-webapplicationfactory-across-tests branch from 0440bae to acacc4b Compare May 14, 2026 10:05
@tjementum tjementum moved this to 🏗 In Progress in Kanban board May 14, 2026
@tjementum tjementum force-pushed the pp-1209-share-webapplicationfactory-across-tests branch from acacc4b to 69d9c50 Compare May 14, 2026 10:20
@tjementum tjementum requested a review from a team as a code owner May 14, 2026 10:20
@tjementum tjementum force-pushed the pp-1209-share-webapplicationfactory-across-tests branch 2 times, most recently from 131e4f6 to 0592515 Compare May 14, 2026 10:53
@tjementum tjementum force-pushed the pp-1209-share-webapplicationfactory-across-tests branch from 0592515 to 719edf2 Compare May 14, 2026 10:56
@tjementum tjementum changed the title Share WebApplicationFactory across BackOffice tests via IClassFixture Share WebApplicationFactory across BackOffice and Account tests via IClassFixture May 14, 2026
@tjementum tjementum force-pushed the pp-1209-share-webapplicationfactory-across-tests branch from e9be7c9 to eeda671 Compare May 14, 2026 11:49
@tjementum tjementum force-pushed the pp-1209-share-webapplicationfactory-across-tests branch from 5633dc6 to cb4a829 Compare May 14, 2026 12:21
@tjementum tjementum force-pushed the pp-1209-share-webapplicationfactory-across-tests branch from 31d3be9 to f80592d Compare May 14, 2026 13:38
@tjementum tjementum force-pushed the pp-1209-share-webapplicationfactory-across-tests branch from f80592d to 9587ec5 Compare May 14, 2026 13:38
@tjementum tjementum changed the title Share WebApplicationFactory across BackOffice and Account tests via IClassFixture Share WebApplicationFactory across BackOffice and Account tests, and consolidate the CI code-style workflow May 14, 2026
@sonarqubecloud
Copy link
Copy Markdown

@tjementum tjementum changed the title Share WebApplicationFactory across BackOffice and Account tests, and consolidate the CI code-style workflow Speed up CI and local format and lint May 14, 2026
@tjementum tjementum changed the title Speed up CI and local format and lint Speed up CI and format and lint CLI commands May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement New feature or request

Projects

Status: 🏗 In Progress

Development

Successfully merging this pull request may close these issues.

1 participant