# Preparing a release QuestionBankToolkit uses Towncrier for release notes and Bump My Version to keep the package versions synchronized. The release tools are installed by the `release` dependency group and are also included in `dev`. ## Record changes during development Add a news fragment for each user-visible change instead of editing `CHANGELOG.md` directly. For issue 42, for example: ```bash towncrier create --content "Describe the change for users." 42.feature.md ``` Use `feature`, `bugfix`, `doc`, `removal`, or `misc` as the fragment type. For a change without an issue, prefix a unique name with `+`, such as `+clear-error.bugfix.md`. See the [`newsfragments` guide](https://codeberg.org/ddmarshall/QuestionBankToolkit/src/branch/main/newsfragments/README.md) for the naming rules. Preview the next release notes without modifying files: ```bash towncrier build --draft --version 0.1.0 ``` ## Prepare the release candidate Begin from the intended release commit with a clean Git working tree. Use `current` to prepare the first public release at the version already declared in the project. For later releases, choose `patch` for compatible fixes, `minor` for compatible features, or `major` for incompatible changes: ```bash QBT_PYTHON=.venv/bin/python ./scripts/prepare_release.sh current ``` The script validates the current release metadata and moves the fragments into `CHANGELOG.md`. For later releases, it also computes the next version and updates both version declarations. It then runs the complete code-quality suite and tests both distribution formats in clean environments. The script does not create a commit, tag, or upload so the prepared files and generated release notes can be reviewed first. If a check fails after files are updated, fix the cause and rerun the reported check directly. Do not run the preparation script a second time unless the prepared changes have first been restored or committed, because that would request another version increment. ## Commit and tag after review Check the version, date, changelog text, and Git diff. Then commit all prepared release files and create an annotated tag that matches the version: ```bash git add CHANGELOG.md pyproject.toml src/coursebanks/__init__.py newsfragments git commit -m "Release 0.1.0" git tag -a v0.1.0 -m "QuestionBankToolkit 0.1.0" ``` Replace `0.1.0` with the version prepared by the script for later releases. Push the release commit and tag only after the local review is complete and the remote repository is ready to receive the release. ## Publish the documentation site Build and review the site before publishing it: ```bash QBT_PYTHON=.venv/bin/python ./scripts/build_docs.sh ``` The local entry point is `site/index.html`. After the release commit is clean and pushed, publish the generated site to the repository's `pages` branch: ```bash QBT_PYTHON=.venv/bin/python ./scripts/publish_docs.sh ``` For the first deployment, open the repository settings on Codeberg, add a Forgejo webhook, set its target URL to `https://ddmarshall.codeberg.page/QuestionBankToolkit/`, and restrict it to the `pages` branch. Codeberg documents that its webhook test button is expected to fail; publish another documentation commit instead when testing the completed setup. ## Publish to PyPI PyPI Trusted Publishing does not currently list Codeberg Woodpecker as a supported identity provider, so this project uses a PyPI API token for manual publication. Do not commit the token or place it in a command argument. The first upload creates the PyPI project and therefore requires an account-scoped token. After the project exists, replace that token with a token scoped only to `QuestionBankToolkit` for later releases. Store the project-scoped token under a `QuestionBankToolkit` repository section in `~/.pypirc`, and restrict that file to the current user with `chmod 600 ~/.pypirc`. From the clean, tagged release commit, build and validate the final files: ```bash rm -rf dist python -m build python -m twine check dist/* ``` Inspect the wheel and source archive names and confirm their version before uploading. Upload through the named repository configuration so the token is not included in the command: ```bash .venv/bin/python -m twine upload --repository QuestionBankToolkit dist/* ``` PyPI does not permit replacing a file or reusing a published version after deletion. Confirm the project page, installation command, metadata links, and a clean-environment installation immediately after publication.