The kit ships two GitHub Actions workflows in .github/workflows/:
ci.yml— build, test, and publish the application (API container + NuGet packages).template-smoke.yml— guards the distribution path: scaffolding from thedotnet newtemplate must always build.
ci.yml — build, test, publish
Triggers on pushes to main/develop, v* tags, and PRs to those branches (scoped to src/**), plus manual workflow_dispatch (with an optional version input). PR runs cancel in-progress duplicates.
| Job | Depends on | Runs when | What it does |
|---|---|---|---|
| Build | — | always | dotnet build -c Release -warnaserror, scans for vulnerable packages, uploads build output as an artifact. |
| Test (matrix) | Build | always | 12 unit/architecture test projects in parallel (fail-fast: false), reusing the build artifact (--no-build). |
| DbMigrator Container Smoke | Build | always | Publishes the fsh-db-migrator image (Dockerfile-less SDK publish) and runs apply --catalog-only against an ephemeral Postgres 17 — asserts it finishes successfully. Catches container-publish and DI-graph regressions. |
| Integration Tests | Build | always | Integration.Tests + Integration.Middleware.Tests via WebApplicationFactory + Testcontainers (Docker on the runner). Builds from source. |
| Coverage Gate | Build | always | Whole-solution coverage via ReportGenerator; fails if line coverage drops below 80% (a ratchet — raise MIN_LINE as coverage grows). |
| Publish Dev Containers | Test, Integration | push to develop | Publishes the API image to GHCR tagged dev-<sha> and dev-latest. |
| Publish Release | Test, Integration | v* tag, or workflow_dispatch on main | Packs NuGet packages + the template, pushes to NuGet.org, and publishes the API image to GHCR tagged <version> and latest. |
Releasing
A release publishes both NuGet packages (the BuildingBlocks, selected module Contracts, the fsh CLI, and the dotnet new template) and the API container image. Two ways to trigger it:
# Tag-driven (recommended): the tag name is the versiongit tag v10.0.0 && git push origin v10.0.0…or run the CI/CD Pipeline workflow manually from the Actions tab on main with a version input (e.g. 10.0.0-rc.1).
template-smoke.yml — distribution guard
Runs on changes to .template.config/**, templates/**, clients/**, or src/**. It proves a freshly scaffolded project actually builds:
- Scaffold (Aspire + React) — packs the template, installs the
.nupkg, runsdotnet new fsh ... --aspire true --frontend true, builds the backend (-warnaserror), builds both React apps (npm ci && npm run build), and runs the Architecture tests on the scaffolded output. - Scaffold (minimal) — scaffolds backend-only (
--aspire false --frontend false) and builds it, guarding the//#if (frontend)/(!aspire)conditional gating inAppHost.csand the solution.
How CI feeds deployment
The image CI publishes is what you deploy. Reference it by its immutable tag in your environment’s terraform.tfvars:
container_image_tag = "v10.0.0" # or a dev-<sha> tag from the develop branchThen deploy — see Deploy to AWS with Terraform. For a fully automated path, run the one-command deploy from your own deploy workflow after the image is published.
Local parity
Every CI check has a local equivalent, so you can reproduce a red build before pushing:
dotnet build src/FSH.Starter.slnx -c Release -warnaserror # Build jobdotnet test src/FSH.Starter.slnx -c Release # Test + Integration (needs Docker)