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), 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-pinnedKofTwentyTwo/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.
## 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)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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 namedcigetci / 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 packwith the tag version, a CycloneDX 1.6 SBOM per package from itspackages.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 namesKofTwentyTwo/standardsas the builder (SLSA Build L3).repositoryandjob_workflow_refclaims against the package's own repository (source), so a push inside a reusable workflow from this repo would always be rejected. Therelease-nuget.ymltemplate'spublishjob downloads the packages, runsgh attestation verify --signer-repo KofTwentyTwo/standards, then pushes viaNuGet/login. Policy fields documented instandards/releases.md.dotnet-ci.ymlandrelease-nuget.yml; docs (ci-cd required checks and K22-CI-30, releases, README, configs/dotnet adoption steps).KofTwentyTwo/standards/.github/workflows/release-*.ymlcall in every tag workflow; K22-CI-01 expectsci / build-testandci / formatwhen 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
Velopack 1.2.161and the project reference.-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@maininstead of a SHA, K22-CI-30 FAILs as intended.Stacked on #2 (which is stacked on #1).
Generated with Claude Code