## What Brings AppKit into conformance with [KofTwentyTwo/standards](https://github.com/KofTwentyTwo/standards). Reviewable commit by commit: | Commit | Change | | --- | --- | | build | Quality gate from `configs/dotnet` (analyzers incl. Meziantou, warnings as errors), `packages.lock.json` per project, locked-mode restore | | style | Kingsrook layout and LF line endings, produced mechanically by `dotnet format` (formatting only) | | docs | SPDX license header on every C# file | | refactor | Real code changes: analyzer findings fixed (one type per file, regex timeouts, async void, …) and header comments on every type and member | | ci | Old workflows replaced by callers of the shared standards workflows (PR gates, security, CodeQL, .NET CI, NuGet release with SBOM + attestation + trusted publishing), Scorecard | | docs | README, CONTRIBUTING (GitHub Flow, DCO, signing), SECURITY, CODEOWNERS, templates, Dependabot, threat model, ADRs, RELEASING | Also includes `dev`'s CI fix, so it supersedes #1; the `dev` branch goes away under GitHub Flow. ## Why AppKit is the first Product repository to adopt the standards. Static conformance before: 16 FAIL; after: 0 FAIL, 0 WARN (the remaining UNKNOWN rows are GitHub settings and rulesets, applied separately). ## How tested Locally with `CI=true` (lock files enforced): locked restore x64 and ARM64; zero-warning x64 build; 115 unit tests with 100% line coverage of `KofTwentyTwo.AppKit` and `KofTwentyTwo.AppKit.Updates`; 12 FlaUI UI tests (WinUI + WPF samples); `dotnet format --verify-no-changes --severity warn` clean; pack produces 4 packages + symbols; actionlint, zizmor (pedantic), gitleaks clean. The UI tests caught a regression introduced while fixing MA0147 (the WPF splash stopped dismissing because no UI context existed yet); fixed by starting the countdown through the dispatcher in both packages. ## Notes - `ci.yml` and `release.yml` are pinned to KofTwentyTwo/standards#3's head commit; they are repinned after that PR merges. - This pull request's new check names become required checks once the repository's rulesets are updated. 🤖 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>
3.8 KiB
Releasing AppKit
Releases follow the
KofTwentyTwo release standard.
Pushing a protected v* tag on main runs .github/workflows/release.yml,
which calls the shared release-nuget.yml workflow in KofTwentyTwo/standards. All four
packages always release together under one version.
Status: the shared workflows are pinned to a commit on KofTwentyTwo/standards
mainwhile the standards are pre-release; they move to a release tag's commit once KofTwentyTwo/standards publishesv1.0.0(Dependabot proposes the update).
Versioning
The version is the tag without the leading v, in strict semver.
| Tag | Version | GitHub Release | nuget.org |
|---|---|---|---|
v1.2.3 |
1.2.3 |
stable | stable |
v1.2.3-beta.1 |
1.2.3-beta.1 |
prerelease | prerelease |
AppKit is a library every app depends on, so semver is a promise:
- major: any breaking change to a public API
- minor: new capabilities, backward compatible
- patch: fixes only
Directory.Build.props holds VersionPrefix, the next expected release; local builds
are <prefix>-dev. Bump the prefix right after each release, in a pull request.
What a release does
The shared workflow (SLSA Build L3: the build definition lives in KofTwentyTwo/standards, not here):
- Validates the tag and re-runs every gate that guards
main: locked restore, zero-warning build, unit tests, and the 100% coverage gate. - Packs the four packages and their symbol packages.
- Generates a CycloneDX 1.6 SBOM per package (Syft, from
packages.lock.json) and attests it. - Writes
SHA256SUMSover every asset and attests build provenance. - Creates a draft GitHub Release with the assets and generated notes, then publishes it (releases are immutable).
Then the publish job in this repository's release.yml downloads the packages,
verifies their attestations were signed by the shared workflow, and pushes them to
nuget.org through trusted publishing (OIDC; no API key is stored anywhere).
One-time setup (owner)
- nuget.org trusted publishing policy: nuget.org → your profile → Trusted
Publishing → Add policy:
- Repository owner:
KofTwentyTwo - Repository:
AppKit - Workflow file:
release.yml - Environment:
release
- Repository owner:
- Repository variable
NUGET_USER(Settings → Secrets and variables → Actions → Variables): your nuget.org profile name. Without it thepublishjob is skipped and the release still succeeds on GitHub. - Environment
release(Settings → Environments) with a deployment rule that allows only tags matchingv*.
Cutting a release
-
Make sure
mainis green and the conformance check passes:pwsh ../standards/tools/Test-RepoConformance.ps1 -Repository KofTwentyTwo/AppKit -LocalPath . -
For a minor or major release, open a release checklist issue from the standards template and complete it (security assessment, threat model review, scan results).
-
Tag
mainand push the tag:git switch main git pull git tag -s v0.1.0 -m "v0.1.0" git push origin v0.1.0 -
Watch the release workflow, then verify the release as described in the README.
-
Open a pull request that bumps
VersionPrefixinDirectory.Build.props.
When something fails
- Before the release is published: nothing is public. Delete the draft
(
gh release delete v0.1.0 --yes), fix the cause, and re-run the workflow. - At
publish (nuget.org): the GitHub release is published and immutable; re-run only the failedpublishjob from the Actions page. - A published release is broken: never reuse its version. Fix forward with a new patch release, and unlist the bad version on nuget.org.