I need to make a release

CNA snapshot 009d40f5  ·  Development › Maintainer Handbook  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Read at 009d40f5 from CMakeLists.txt, cmake/Version.cmake, docs/releasing.md, CHANGELOG.md, the workflows and the local tag list; no step was executed and CNA has cut only one tagged release.

This page is a checklist for a human maintainer cutting a CNA release, grounded in what the TARGET tree at 009d40f5 actually contains: where the version lives, what is generated from it, what a release entry has to record, and which numbers are deliberately not the product version. It marks each step as automated by the repository, manual, or not established in the source. CNA has a documented tag-and-changelog procedure and no release automation; nothing here was run, and no step below should be read as a process CNA has proven end to end. The user-facing account of the one existing tag is on Releases & versioning.

⚠

TARGET is not a release. The snapshot is 2,877 commits after v0.1.0-alpha.1 on the next branch, its product version string is still 0.1.0-alpha.1, and no newer tag exists. CNA::getVersionString() therefore cannot tell the tag from the snapshot; identify a build by its Git commit. Nothing on this page has been used to publish a release after the first tag.

Owner and read first

The version is decided in exactly one place, the root CMakeLists.txt: project(CNA VERSION 0.1.0 LANGUAGES CXX) supplies the numeric components (CMake's VERSION accepts numbers only) and set(CNA_VERSION_PRERELEASE "alpha.1") supplies the pre-release identifier, joined into CNA_VERSION_STRING. The pre-release identifier is deliberately a normal variable, not a cache entry, so an existing build directory cannot keep reporting the previous release after a bump. Read, in order:

  1. docs/releasing.md: the procedure, dated to the first tag; it is the only written process and this page follows it, extended where TARGET shows more.
  2. cmake/Version.cmake and Version.hpp.in: how the single decision becomes <build>/generated/include/CNA/Version.hpp.
  3. CHANGELOG.md: its format, the [Unreleased] section and the link definitions at the bottom.
  4. abi.h, ABI_VERSIONING.md and RELEASE_GATE.md: the independent C ABI version and its own gate.

Four numbers that are not one number

IdentityValue at TARGETWhere decidedMoves when
CNA product version0.1.0-alpha.1, unchangedRoot CMakeLists.txtA release is cut, by hand
Native C ABI version0.29.0, experimentalmodules/c-api/include/CNA/C/abi.h (three macros)The ABI changes, independently of any product release; see Update the C API
struct_version fieldsPer structureThe C headersOne C structure changes
XNA API levelXNA 4.0, fixedNot a CNA versionNever

The sibling sharp-runtime and every external language binding have their own versions and cadence. The generated header exposes CNA_VERSION_MAJOR/MINOR/PATCH (preprocessor-testable literals), CNA_VERSION_PRERELEASE (without the leading -, empty on a final release), CNA_VERSION_STRING, and the constexpr functions CNA::getVersionMajor(), getVersionMinor(), getVersionPatch(), getVersionPreRelease(), getVersionString() and isPreReleaseVersion(). Consumers that derive from it: CMake consumers through CNA_VERSION, Apple bundles through CNA_APPLE_BUNDLE_VERSION (the numeric components only, because a bundle version cannot carry -alpha.1), the configure banner (CNA: version …) and the Inspector's hello message (cnaVersion).

What a release promises, and what it does not

  • Semantic Versioning, pre-1.0. CHANGELOG.md and docs/releasing.md state that while the major version is 0, a minor bump may change the public API; pre-release identifiers run alpha.N, beta.N, rc.N, ordered as SemVer orders them, and 0.1.0-alpha.1 precedes 0.1.0.
  • A release is a Git tag plus a changelog entry. There is no separate release branch and nothing is published to a package registry. The repository has no GitHub Release object for the one tag, only two Git tags (v0.1.0-alpha.1 and an audit marker), and no workflow triggers on tags or uploads a release artifact.
  • Uneven by design. The alpha.1 entry's known limitations say interfaces are expected to change before 1.0 and renderer coverage is uneven; the same holds for the snapshot. A release does not promise that every renderer, platform or binding works. The same known-limitations list also says “Content has no general .xnb reader by design, and 14 of the Media types are shells”. The first half is out of date at this snapshot (CNA registers 61 canonical built-in XNB reader names; see XNB content) and the count in the second half names no method, so neither half should be copied into new release notes (read from CHANGELOG.md at 009d40f5; not executed).
  • No promise about the C ABI. The C ABI has its own gate, which currently reads “Not ready”, and its 0.x minors have been incompatible twice since the tag (version history). Bindings are separate projects that each target one ABI generation and are not qualified against the snapshot (C API internals).
  • What is not established. The sources say nothing about a support window, a deprecation policy, signed or binary artifacts, or which configurations must pass before a tag. Do not add such claims to release notes.

Checklist

“Repo” means the repository automates or checks it; “manual” means a person edits or runs it; “not established” means the source does not say.

#StepWhat to do and checkStatus
0Choose the branchThe tag in docs/releasing.md is pushed from develop and GitHub's default branch is develop, which still points at the tag commit; the snapshot is on next. Which branch carries the next tag is not written anywhereNot established
1Choose the versionEdit project(CNA VERSION …) and/or CNA_VERSION_PRERELEASE (empty on a final release); no other file may hard-code the numberManual
2Update the hand-kept copiesDoxyfile PROJECT_NUMBER (currently 0.1.0-alpha.1) and CHANGELOG.md, as docs/releasing.md requires. The README's “Current release” line is a third hand-kept copy that the procedure does not listManual
3Write the changelog entryMove [Unreleased] into ## [x.y.z] — YYYY-MM-DD and add the two link definitions at the bottom. Before trusting [Unreleased], note that at TARGET it names the Win32 backend, the renderer curation and a few C ABI steps, but a text search finds no mention of Wayland, ALSA, the Inspector, Diagnostics, OpenGL4, SDL_GPU or cna-content among the 2,877 commits; a release entry would have to be reconstructed from the commit range, not renamedManual; completeness not established
4Record dependency pinsThe alpha.1 entry records submodule revisions (fixed by the gitlinks a tag selects) and the GIT_TAG values in cmake/ThirdParty*.cmake, plus the sharp-runtime revision, because it is a sibling checkout consumed by add_subdirectory and the tag alone does not select it. The procedure names only sharp-runtime; easy-gl, meta-gl and free-direct are siblings too and are not pinned or recordedManual; an enforcing check is described as planned
5C ABIConfirm abi.h matches the baseline and the release-gate record (version discipline); the gate verdict governs publishing an experimental C ABI and is independent of the product tagRepo (build-free workflows on push); a publishing step is not established
6Build and testdocs/releasing.md shows one configuration (OPENGLES3, target CnaTests, ctest --output-on-failure) and asks that the configure banner version match. Twenty workflow files exist (17 trigger automatically on push or pull request; D3D and GDI Windows lanes are manual; no workflow builds the C library or the oracle corpus). Which set must be green before a tag is not establishedRepo for the CI it runs; requirement not established
7Version testsVersionTest.* in VersionTests.cpp are structural on purpose (components non-negative, string starts with the numeric components and ends with -<prerelease> exactly when there is one, no v prefix), so a bump needs no test editRepo
8CommitAdd the version-bearing files by explicit name, never git add -AManual
9TagAn annotated tag vX.Y.Z[-pre] with message CNA X.Y.Z[-pre]; the tag string has the v, the version string never doesManual
10PushOnly when the project owner asks; push the branch and the tag explicitlyManual
11Open the next cycleRestore an empty ## [Unreleased] section if step 3 consumed itManual
12Publish artifacts or release notesNo GitHub Release, package, binary or signature procedure exists in the source. A July 2026 note in docs/devices-build.md states that the project had no release process to attach an artifact to; docs/releasing.md (August 2026) is the later and only written procedureNot established
13DownstreamBindings, samples and this site pin CNA revisions independently; after a release, update the site's pinned snapshot (Update libcna.com) and expect each binding to need its own ABI migrationManual; owned outside the CNA repository

Anatomy of a changelog entry

The format follows Keep a Changelog. The single existing release entry (CHANGELOG.md, ## [0.1.0-alpha.1] — 2026-08-20) is the only template and has these parts, in order:

  1. A one-paragraph statement of what the entry describes. The first tag says it “names a state of develop rather than introducing new work”, so its lists describe the release's contents, not a delta from a previous tag. A later entry would be a delta and should say so.
  2. Added, with concrete surface and counts that were true of the tagged tree, and links to the documents that define them.
  3. Dependency pins: the submodule commits, where the GIT_TAG values live, and the sharp-runtime revision as a git log -1 --format='%H (%D, %ad)' line with the acknowledgement that recording it does not enforce it.
  4. Known limitations, stated as limits rather than as a roadmap.
  5. Link definitions at the bottom: [Unreleased] as a compare against the latest tag, and one releases/tag link per version. They point at the repository's original owner path, which GitHub redirects to libcna/cna.

The [Unreleased] section uses Added, Removed, Changed and Fixed. Several of its entries are written as records of why a decision was made (for instance the route removed from the C ABI, with the export and layout deltas), which is the level of evidence a release entry should keep.

Verify the tagged tree

None of these were run for this page. They are the checks the sources imply once a tag exists:

git describe --tags                         # the tag name, or tag-N-g<hash> after it
git rev-parse 'vX.Y.Z^{commit}'             # the commit the tag names
cmake -S . -B <build> ...                    # the banner prints "CNA: version X.Y.Z[-pre]"
grep CNA_VERSION_STRING <build>/generated/include/CNA/Version.hpp

Then run the structural VersionTest.* cases through the core test binary and, if the C API is part of the claim, build it in a separate CNA_BUILD_C_API=ON tree and run ctest -R '^CApi'. The CMake package for the C API takes its version from abi.h, not from the product version, so find_package(CNA 0.1 CONFIG) compares against the C ABI (0.29.0 at TARGET) and a request written as “0.1” is not a statement about the product release.

Traps

  • Two revisions, one string. Until step 1 is done, every snapshot reports 0.1.0-alpha.1. Record git rev-parse HEAD in bug reports and evidence, not the version.
  • Numbers you cannot bump together. Raising the product version does not touch the ABI version, and a C ABI step does not need a product release. Do not describe either as implying the other.
  • An unpinned sibling. A tag selects submodules and fetched sources but not sharp-runtime or the other siblings; on a fresh clone the default branch of a sibling may lack components CNA requires (next of sharp-runtime is the working one at the snapshot). Record revisions or the release is not reproducible.
  • Pointing links at a moving branch. GitHub's default branch shows the tag, not the snapshot; release notes and documentation should link a tag or a commit permalink.
  • Pre-release identifiers and Apple. A bundle version cannot contain -alpha.1, which is why CNA_APPLE_BUNDLE_VERSION defaults to the numeric components.
  • A reconstructed changelog is a claim. State counts and capabilities from the tree at the tag, not from the previous entry; see Known uncertainty and history.

Review checklist

  • One source of truth edited; Doxyfile, changelog and README copies agree with it; the configure banner prints the intended string.
  • The changelog entry describes the tagged tree, records the sharp-runtime revision and mentions the C ABI version and any ABI step since the previous release.
  • The evidence run is named (configuration, tests, what was not run); steps marked not established are stated as such in the release notes rather than implied.
  • The tag is annotated, on the intended branch, and pushed explicitly, with owner approval.
  • Bindings, samples and the documentation pin are told which revision to expect.

Related: Maintenance and pin policy, Blast radius and readiness and Change build configuration.

The same subsystem is explained at four altitudes. These are the neighbouring pages at each one.

Tests and validation
Test architecture