.. SPDX-FileCopyrightText: 2026 calendaring-sync contributors .. SPDX-License-Identifier: AGPL-3.0-or-later ======= Release ======= .. meta:: :description: How calendaring-sync is versioned, how a maintainer cuts a release, and the access a release needs. This page is for maintainers cutting a release. Versioning ========== Versions follow `Semantic Versioning 2.0.0 `_. While the major version is 0, a release with new features or with changes that break the public API bumps the minor version, and a release with only fixes bumps the patch version. From 1.0.0 on, a breaking change bumps the major version. A public name that's renamed or removed keeps working, with a :exc:`DeprecationWarning`, for at least one release first. calendaring-sync has no release branches: every release ships from ``main``. The version number comes entirely from the git tag, read at build time by ``hatch-vcs``; nothing in the source tree stores it. ``src/calendaring_sync/_version.py`` is generated during the build and isn't tracked in git. Cut a release ============= #. Confirm ``main`` is up to date and its CI is green. .. code-block:: bash git checkout main git pull #. Build the :ref:`change log ` from the pending fragments in ``news/``, replacing ``1.2.0`` with the real version: .. code-block:: bash uv run towncrier build --yes --version 1.2.0 This writes the new section into ``docs/changelog.rst`` and deletes the fragments it consumed. Review the diff: towncrier orders the entries in each category by issue number, not in the order the fragments were added. #. Commit directly to ``main``, the one exception :ref:`commits-and-prs` makes to going through a pull request: the commit is mechanical, with nothing for a reviewer to review. .. code-block:: bash git add docs/changelog.rst news/ git commit -m "chore: build 1.2.0 changelog" git push #. Tag the commit you pushed, and push the tag: .. code-block:: bash git tag v1.2.0 git push origin v1.2.0 Pushing the tag triggers the ``release`` GitHub Actions workflow: it runs the unit tests, the integration tests against every server, and the docs build, and only if all of them pass, builds the package, publishes to PyPI through trusted publishing, and creates a GitHub release that links this release's change log on Read the Docs. Nothing past the tag push is manual. Read the Docs builds the new version from the same tag push. Dependency maintenance ====================== Whenever you add or drop a supported Python version, check which dependencies have newer compatible versions with ``uv tree``: .. code-block:: bash uv tree --all-groups --depth=2 --python-version 3.11 Run it once for each supported Python version, from ``requires-python`` in :file:`pyproject.toml` to the newest in the ``python-version`` matrix of :file:`.github/workflows/tests.yml`. ``--depth=2`` shows each direct dependency and its own dependencies, enough to spot an outdated lower bound without the whole tree. Check each adapter's client library first: an adapter tracks its library, so read a new release of one against its change log. After changing a bound, run ``uv lock`` so :file:`uv.lock` follows. Maintainer access ================= Releasing calendaring-sync requires: ``Admin`` access to the `GitHub repository `_ Needed to push directly to ``main`` and push tags. ``Owner`` or ``Maintainer`` access to the `PyPI project `_ PyPI publishing uses `trusted publishing `_ (OIDC), configured against this repository's ``release`` workflow and its ``pypi`` environment; no PyPI API token is stored anywhere. A PyPI account with access can revoke or reconfigure this. ``Maintainer`` access to the `Read the Docs project `_ Needed only to manage the Read the Docs build configuration.