This checklist is for project maintainers. Releases use Semantic Versioning and
the MAJOR.MINOR.PATCH tag convention described in
VERSIONING.md.
- Choose the version from the user-visible changes since the previous release.
- Confirm that the release commit will come from
main, the worktree is clean, and required GitHub checks are green. - Resolve or explicitly defer every release-blocking bug and private security advisory. Never expose embargoed details in a public release pull request.
- Update every version source listed in
VERSIONING.mdand search the tree for stale copies of the previous version. - Move the accumulated
Unreleasedchangelog entries into a heading for the new version and UTC release date. Leave a freshUnreleasedheading above it. Verify all changelog links.
The release preparation should be reviewed as a pull request. Avoid unrelated changes in that pull request so the release diff is auditable.
Run the repository's complete local verification from the release commit:
./build.sh --all --autoVerify that every distributed file has complete, valid SPDX metadata and that all referenced license texts are present:
python3 -m pip install --disable-pip-version-check reuse==6.2.0
reuse lintThe full sweep covers compilation, registered tests, formatting, sanitizers,
benchmarks, clang-tidy, documentation generation, package checks, and bounded
fuzz corpus replay when supported. The --package phase validates relocatable
static and shared installs through both CMake-package and pkg-config consumers.
The sweep offers to fetch both pinned conformance corpora; --auto accepts them
without prompting. An explicit fuzz run is required on a release machine with
Clang and libFuzzer so a missing runtime cannot be treated as an optional
full-sweep skip:
./build.sh --fuzz --autoFetch the separately pinned official JSON Schema corpus and run its supported draft-07 manifest against the release candidate:
./scripts/fetch-json-schema-test-suite.sh
PJSON_JSON_SCHEMA_TEST_SUITE_DIR="$PWD/.test-corpora/JSON-Schema-Test-Suite" \
ctest --test-dir out/build-debug --output-on-failure \
-R '^pjson\.schema_official_draft7_optional$'The full sweep already builds and validates the release API reference. To rerun that focused check (which requires Doxygen and Python 3):
cmake -S . -B out/build-docs \
-DPJSON_BUILD_TESTS=OFF \
-DPJSON_BUILD_EXAMPLES=OFF \
-DPJSON_BUILD_BENCHMARKS=OFF \
-DPJSON_BUILD_DOCS=ON
cmake --build out/build-docs --target pjson-docs-check
PJSON_RELEASE_TMP_DIR="$(mktemp -d)"
tar -C out/build-docs/docs/reference/html \
-czf "${PJSON_RELEASE_TMP_DIR}/pjson-api-reference.tar.gz" .
tar -tzf "${PJSON_RELEASE_TMP_DIR}/pjson-api-reference.tar.gz" |
grep -q '^./index.html$'Verify both static and shared relocatable installs through external CMake and pkg-config consumers, including the CMake config/version/targets metadata and the installed header and library. Requiring pkg-config here prevents that consumer path from being silently skipped. Run the package smoke tests from a clean working directory:
PJSON_RELEASE_TMP_DIR="$(mktemp -d)"
cmake -DPJSON_SOURCE_DIR="$PWD" \
-DPJSON_WORK_DIR="${PJSON_RELEASE_TMP_DIR}/package-smoke/static" \
-DPJSON_INSTALL_LIBDIR=lib64 \
-DPJSON_REQUIRE_PKG_CONFIG=ON \
-P cmake/RunInstallConsumer.cmake
cmake -DPJSON_SOURCE_DIR="$PWD" \
-DPJSON_WORK_DIR="${PJSON_RELEASE_TMP_DIR}/package-smoke/shared" \
-DPJSON_BUILD_SHARED_LIBS=ON \
-DPJSON_INSTALL_LIBDIR=lib64 \
-DPJSON_REQUIRE_PKG_CONFIG=ON \
-P cmake/RunInstallConsumer.cmake
test -f "${PJSON_RELEASE_TMP_DIR}/package-smoke/static/relocated/share/licenses/pjson/LICENSE"
test -f "${PJSON_RELEASE_TMP_DIR}/package-smoke/shared/relocated/share/licenses/pjson/LICENSE"Run the package-manager checks with Conan 2 and a current vcpkg checkout. These
are release checks, not optional contributor-tool discovery; install the tools
on the release machine before continuing. Use an empty disposable directory for
CONAN_HOME; mktemp -d is portable across the supported Unix release hosts:
python3 -m py_compile conanfile.py test_package/conanfile.py
export CONAN_HOME="$(mktemp -d)"
conan profile detect --force
conan create . -s build_type=Release --build=missing
python3 -m json.tool packaging/vcpkg/ports/pjson/vcpkg.json >/dev/null
"$VCPKG_ROOT/vcpkg" install pjson \
--overlay-ports="$PWD/packaging/vcpkg/ports"
PJSON_RELEASE_TMP_DIR="$(mktemp -d)"
cmake -S tests/install-consumer \
-B "${PJSON_RELEASE_TMP_DIR}/vcpkg-consumer" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"
cmake --build "${PJSON_RELEASE_TMP_DIR}/vcpkg-consumer" \
--config Release --parallel
ctest --test-dir "${PJSON_RELEASE_TMP_DIR}/vcpkg-consumer" \
-C Release --output-on-failureThe Conan test package and vcpkg overlay must build the release checkout and
consume the installed pjson::pjson target. Treat any recipe, consumer,
relocation, metadata, or documentation failure as a release blocker. Record the
commands, tool versions, platforms, and results in the release pull request.
Review the candidate diff and provenance before continuing:
git status --short
git diff <previous-release-tag>...HEAD
git log --oneline <previous-release-tag>..HEADAfter the release pull request is merged and the exact release commit is checked out, create an annotated tag. Sign it when the maintainer has a configured, project-recognized signing key.
git tag -a X.Y.Z -m "pjson X.Y.Z"
git push origin X.Y.ZCreate a GitHub release from that exact tag. Use pjson X.Y.Z as the title and
copy the matching changelog section into the release notes. The documentation
workflow builds and attaches pjson-api-reference.tar.gz from the release tag;
wait for that workflow and treat a missing or failed archive as a release
failure. Attach SHA-256 checksums for any additional downloadable artifacts. Do
not rebuild or replace artifacts from a different commit.
- Confirm the tag resolves to the reviewed commit.
- Download each published artifact and verify its checksum and version.
- Build or consume at least one downloaded artifact in a clean directory.
- Open the downloaded API reference's
index.htmland confirm its version and migration pages match the tag. - Check that changelog comparison links and package metadata resolve correctly.
- Announce the release only after these checks pass.
Confirm that main has an empty Unreleased changelog section ready for future
work. Monitor installation and compatibility reports, and publish a patch release
for release-specific defects.
Never move or silently replace a published tag or artifact. If a release is unsafe, mark it clearly in GitHub, notify users through the security advisory or release notes, and publish a corrected version with a new tag.