## What - **`dotnet.yml`** (reusable): locked restore, zero-warning build, tests with a per-package line-coverage gate, the Kingsrook format check (`dotnet format --verify-no-changes --severity warn`), optional FlaUI UI tests and pack. Callers named `ci` get `ci / build-test`, `ci / format`, `ci / ui-tests`. - **`release-nuget.yml`** (reusable, tag-triggered by the caller): strict SemVer tag, Release build/test/coverage gates, `dotnet pack` with the tag version, a CycloneDX 1.6 SBOM per package from its `packages.lock.json` (Syft, digest-pinned), `SHA256SUMS`, SLSA build provenance and SBOM attestations, then a draft GitHub release that is published last. Builds run here, so provenance names `KofTwentyTwo/standards` as the builder (SLSA Build L3). - **nuget.org push stays in the caller.** nuget.org trusted publishing validates the token's `repository` and `job_workflow_ref` claims against the package's own repository ([source](https://github.com/NuGet/NuGetGallery/blob/main/src/NuGetGallery.Services/Authentication/Federated/GitHubTokenPolicyValidator.cs)), so a push inside a reusable workflow from this repo would always be rejected. The `release-nuget.yml` template's `publish` job downloads the packages, runs `gh attestation verify --signer-repo KofTwentyTwo/standards`, then pushes via `NuGet/login`. Policy fields documented in `standards/releases.md`. - Caller templates `dotnet-ci.yml` and `release-nuget.yml`; docs (ci-cd required checks and K22-CI-30, releases, README, configs/dotnet adoption steps). - Conformance checker: K22-CI-30 now requires a **SHA-pinned** `KofTwentyTwo/standards/.github/workflows/release-*.yml` call in every tag workflow; K22-CI-01 expects `ci / build-test` and `ci / format` when the repo has a solution. ## Why AppKit and the Windows app template need shared .NET gates and a release path that meets K22-CI-30/31 and K22-REL-01..07 without each repository re-implementing them. ## How tested - actionlint: clean. zizmor 1.30.1 (default and pedantic) on workflows and templates: no findings. - Syft 1.54.1 locally against an AppKit project with a lock file: CycloneDX 1.6 SBOM listing `Velopack 1.2.161` and the project reference. - Conformance `-SelfTest`: passed (new release-call and context assertions). Static run against a scratch repo built from the new templates: K22-CI-10/11/13/14/15/30 PASS; with the release call pinned to `@main` instead of a SHA, K22-CI-30 FAILs as intended. - markdownlint 0.23.3: 0 issues; internal links: 0 problems; gitleaks: no leaks. - Not yet run in GitHub Actions: the integration test is AppKit's compliance PR calling this branch's head SHA. Stacked on #2 (which is stacked on #1). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: James Maes <james@kof22.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
4.4 KiB
.NET
Drop-in files that implement the C# / .NET profile:
the Kingsrook layout plus the shared quality and supply-chain rules. With them in place,
dotnet build fails locally on exactly the same problems that fail CI.
| File | Copy to | Purpose |
|---|---|---|
.editorconfig |
repository root | Kingsrook layout (3-space indent, Allman braces, if(), naming, code-style rules at build-failing severity, Rider/ReSharper blank-line keys, justified analyzer adjustments |
Directory.Build.props |
repository root | Warnings as errors, analyzers, style in build, nullable, deterministic builds, NuGet audit (all) and lock files, Meziantou.Analyzer |
Directory.Packages.props.example |
repository root as Directory.Packages.props |
Central package versions, including the pinned analyzer |
A polyglot repository uses ../editorconfig/.editorconfig instead,
whose [*.cs] sections are identical to this file's.
No Rider/ReSharper .DotSettings layer is needed: Rider and ReSharper read the
resharper_* keys in .editorconfig, which carry the one Kingsrook rule the .NET
formatter cannot express (three blank lines between members).
Adopting in an existing repository
-
Copy the three files. Keep any repository-specific groups of an existing
Directory.Build.props(version, package metadata) and replace its quality settings. -
Set
* text=auto eol=lfin.gitattributes(K22-CODE-07). -
Add a
global.jsonpinning the SDK feature band ("rollForward": "latestFeature"); CI installs the SDK from it. -
Restore once so
packages.lock.jsonfiles are created, and commit them. CI restores with--locked-mode, which fails on any drift from the lock files, and the release workflow builds each package's SBOM from them. -
Reformat and fix:
dotnet format # layout, var, usings, naming, line endings dotnet build -warnaserror # remaining analyzer findings -
Commit the reformat on its own (
style: adopt Kingsrook layout) sogit blamecan skip it: add that commit's hash to.git-blame-ignore-revs. -
Add the CI and release callers from
templates/workflows/dotnet-ci.ymlandtemplates/workflows/release-nuget.yml.
IDEs
- Visual Studio 2026: reads
.editorconfignatively, including the formatting and naming rules; Code Cleanup applies them. Keep Tools → Options → Text Editor → C# → Code Style → General → "Analyze code style during build" on (it is the build's setting anyway). - Rider / ReSharper: reads
.editorconfig(including theresharper_*keys). Settings → Editor → Code Style shows the values as "from EditorConfig". Run Code → Reformat and Cleanup or enable cleanup on save. - VS Code (C# Dev Kit): reads
.editorconfig; see../vscode.
Command line
| Purpose | Command |
|---|---|
| Build with every rule | dotnet build -warnaserror |
| Fix layout and style | dotnet format |
| CI gate | dotnet format <solution> --verify-no-changes --severity warn --no-restore |
| Locked restore (automatic in CI) | dotnet restore --locked-mode |
What is deliberately relaxed
| Rule | Where | Why |
|---|---|---|
CA1716 |
everywhere | Flags member names that are VB keywords (Error); KofTwentyTwo code is C#-only |
MA0004 (ConfigureAwait) |
everywhere | App code resumes on UI threads; libraries opt in (K22-CODE-CS-13) |
MA0049 |
everywhere | Conflicts with the App / App.Core project layout |
CA1707, CA1861, CS1591, MA0048 |
tests/, test/ |
xUnit naming, inline test data, undocumented tests, one file per feature's tests |
CS1591 |
non-packable projects | Only shipped libraries must document their public API |
Verified
On .NET SDK 10.0.401 with Meziantou.Analyzer 3.0.296: a Kingsrook-style class library
and console app build with 0 warnings and pass dotnet format --verify-no-changes, and
the build fails on each of: an unused using (IDE0005), 4-space indentation, a
same-line (K&R) brace, foreach ( with a space (all IDE0055), and a Meziantou rule
(MA0006, MA0011). Locked restore rejects a version that differs from the lock file
(NU1004).