Speed up CI/CD runs, scope the developer CLI, and harden workflow hygiene#895
Merged
tjementum merged 15 commits intoMay 15, 2026
Merged
Conversation
0440bae to
1da4403
Compare
0440bae to
acacc4b
Compare
acacc4b to
69d9c50
Compare
0592515 to
719edf2
Compare
f80592d to
9587ec5
Compare
…w with scope detection
…detect-changes to detect-scope
9587ec5 to
3d75764
Compare
…ests so Features and Beta sections render on default seed
ac2ad19 to
a157c35
Compare
…per slnf, and drop leftover SonarScanner steps from account and main workflows
cc99d29 to
70c2a53
Compare
70c2a53 to
2f872a7
Compare
2f872a7 to
597bad9
Compare
…llers re-write the same deterministic value instead of throwing
52e32ce to
1bf55a9
Compare
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary & Motivation
A coordinated refresh of the CI/CD pipelines and developer CLI: faster runs, scoped commands, better observability, and consistent workflow conventions.
Test infrastructure
BackOfficeEndpointBaseTestandEndpointBaseTest<TContext>built a freshWebApplicationFactory<Program>per test instance. WithMeziantou.Xunit.ParallelTestFramework, every Account-API and BackOffice test paid a full ASP.NET Core cold-start. Both bases now share one host per test class viaIClassFixture<...>, routing per-test state (SqliteConnection, telemetry collector, MockStripeState,IEmailClient) throughAsyncLocal. New types:BackOfficeWebApplicationFactory+BackOfficeTestContext(26 derived classes) andAccountWebApplicationFactory+AccountTestContext(60 derived classes).MockStripeStatebecomes transient so per-request resolution reads the per-test instance;TestServer.PreserveExecutionContext = truekeeps the AsyncLocal flowing into request handling.Single Code Style workflow
A new
code-style.ymlreplaces the per-SCS code-style work inaccount.yml,main.yml,app-gateway.yml. Four jobs:detect-scope— classifies the diff via inlinegit diff, outputs the backend scope and format mode for the downstream jobs.code-linting— backend inspectcode + frontend build + frontend lint (oxlint).code-formatting— backend cleanupcode + frontend format check (oxfmt).sonarcloud— runs once per push (previously three times, once per SCS), sequentially per slnf to keep test assemblies in separate processes and avoid thePortAllocation.Load()race.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 fall back to the full solution. Code coverage is out of scope here — the dotCover path repeatedly exceeded 20 minutes against the new IClassFixture infrastructure and is tracked separately.AppGateway tests now run in CI
AppGateway.Testsexisted in the solution but was never executed — the slnf-scoped runs missed it, andapp-gateway.ymlhad no test step. The workflow now runsdotnet test AppGateway.Tests/AppGateway.Tests.csproj --no-buildwith the same user-secret bootstrap the other workflows use.Developer CLI:
--gateway/-gscope flagbuild,test,format, andlintaccept--gateway/-gto scope to AppGateway only (mutually exclusive with-s).pp test -gtargetsAppGateway.Tests/AppGateway.Tests.csproj; lint/format scope JetBrains tools toAppGateway/**+AppGateway.Tests/**. Shared logic inAppGatewayHelper.Faster format and lint
formatdefaults to changed-only (.csfiles diffed vsorigin/main);--all-filesfor full sweep. CI auto-flips to--all-fileswhenapplication/dotnet-tools.jsonchanges, so JetBrains tool upgrades catch latent drift.lint --changed-onlyis opt-in; CI lints full because inspectcode has cross-file rules..slnfworkaround forcleanupcode— JetBrains 2026.1 accepts.slnxdirectly.Workflow hygiene
cancel-in-progress: true(andfalsefor reusable deploy workflows so mid-deploy cancellations cannot leave a half-applied state).code-style.ymlanddeveloper-cli.ymldumpresult.jsonto the run console and$GITHUB_STEP_SUMMARY. Replaces the brittlegrep | teeexit-code contract.account.ymlandmain.yml(centralized incode-style.yml)._preview-migrations.ymltrigger-path references (file does not exist).Database Plan reuses Build and Test artifacts
build-and-testuploadsapplication/**/binandapplication/**/objas a<scs>-buildartifact (when staging is enabled)._migrate-database.ymldownloads it and restores NuGet, skipping the redundant checkout + setup + build chain.E2E test fix piggy-backed on this branch
Two e2e tests inherited from the recently-merged feature-flags work failed on a default-seeded database (
feature-flag-flows.spec.ts:262,user-management-flows.spec.ts:473). Root cause:account-overviewandcompact-vieware registered withisKillSwitchEnabled: true, so the startup reconciler creates them inactive (EnabledAt = null); the configurable-flags handlers filter inactive rows out, the API returns empty, andFeaturesSection/PreferencesFeatureFlagsSectionrendernull. The tests now activate the kill-switch flags via the back-office activate endpoint during setup — test-only fix, no production code, no seeder change.CI benchmark
The biggest CI win comes from the Database Staging migration-skip gate on
account.yml/main.yml— PRs that do not change EF migration files skip the Database Staging job entirely.AppGateway's delta is large because
code-lintingandcode-formattingmoved out ofapp-gateway.ymlinto the consolidatedcode-style.yml. On the no-migrations path the critical path now sits onCode Style(parallel lint/format/sonar jobs each paying setup); sharing the backend build artifact across them is an obvious follow-up. On the with-migrations path the critical path stays onaccount.yml.Downstream projects with a substantial Main SCS will see a bigger lift than this suggests — the slowest CI step used to be backend
cleanupcoderunning on every file; it now inspects only changed.csfiles. Main and Account now sit close in wall-clock despite Account having materially more code, because the npm + dotnet restore + build setup now dominates.Test-step benchmark (isolated)
Test-host refactor measured in isolation (Code Style and Database Staging disabled; 5 samples per side):
Δ -37% on the test step alone, stddev more than halves — the runs are markedly more stable too.
Checklist