Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 0 additions & 48 deletions .github/workflows/deploy.yml

This file was deleted.

79 changes: 79 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Release

on:
workflow_dispatch:
inputs:
bump:
description: "Version bump (ignored if version is set)"
required: false
type: choice
default: minor
options:
- major
- minor
- micro
- post
version:
description: "Exact version (e.g. 1.0rc1). Overrides bump."
required: false

jobs:
release:
runs-on: ubuntu-latest
environment: release
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

- name: Prepare changelog
id: version
run: |
if [ -n "${{ github.event.inputs.version }}" ]; then
version=$(python scripts/make_changelog.py "${{ github.event.inputs.version }}")
else
version=$(python scripts/make_changelog.py --${{ github.event.inputs.bump }})
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "tag=v$version" >> "$GITHUB_OUTPUT"

- name: Commit and tag
run: |
git commit -am "Prepare release ${{ steps.version.outputs.version }}"
git tag "${{ steps.version.outputs.tag }}"
git push origin "${{ steps.version.outputs.tag }}"

- name: Build
id: build
uses: hynek/build-and-inspect-python-package@v2.14
with:
upload-name-suffix: -release

- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python scripts/extract_changelog.py "${{ steps.version.outputs.version }}" --format gfm > /tmp/release-notes.md
gh release create "${{ steps.version.outputs.tag }}" \
--notes-file /tmp/release-notes.md \
${{ steps.build.outputs.dist }}/*

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@v1.13.0
with:
attestations: true
packages-dir: ${{ steps.build.outputs.dist }}

- name: Start next development cycle
run: |
python scripts/make_changelog.py UNRELEASED
git commit -am "Start next development cycle"
git push origin main
22 changes: 21 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
name: Test
name: CI

on:
push:
branches:
- main
- "test-me-*"
tags:
- "v*"

pull_request:
branches:
Expand All @@ -19,10 +21,28 @@ concurrency:
cancel-in-progress: true

jobs:
changelog:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Check changelog (tagged release)
if: github.ref_type == 'tag'
run: python scripts/check_changelog.py --tag "${{ github.ref_name }}"

- name: Check changelog (PR has new entries)
if: github.event_name == 'pull_request'
run: |
git fetch origin main --depth=1
python scripts/check_changelog.py

package:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Build and Check Package
uses: hynek/build-and-inspect-python-package@v2.17

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ Icon?
Thumbs.db
*.pid
._.**~
unittest2pytest/_version.py
24 changes: 24 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@ UNRELEASED

*UNRELEASED*

- Switch from lib2to3 to `fissix <https://github.com/amyreese/fissix>`_,
a maintained fork of lib2to3 (`#95`_).

- Add Python 3.13, 3.14, and 3.15 support.

- Migrate packaging from ``setup.py`` to ``pyproject.toml`` with
PEP 639 SPDX license metadata (``GPL-3.0-or-later``) (`#96`_).

- Use ``setuptools-scm`` for version management. Versions are now
derived from git tags (`#97`_).

- Add ``check_changelog.py`` CI check to enforce changelog entries
(`#97`_).

- Gate PyPI publishing on tests passing by merging the release
workflow into CI (`#97`_).

- Update installation instructions with ``uv tool install`` (`#92`_).

.. _#92: https://github.com/pytest-dev/unittest2pytest/pull/92
.. _#95: https://github.com/pytest-dev/unittest2pytest/pull/95
.. _#96: https://github.com/pytest-dev/unittest2pytest/pull/96
.. _#97: https://github.com/pytest-dev/unittest2pytest/pull/97


0.5
---
Expand Down
14 changes: 6 additions & 8 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
include CHANGELOG.rst
include COPYING-GPLv3.txt
include NEWLINE.rst
include README.rst

recursive-include tests *
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
exclude .gitignore
exclude DEVELOPER.rst
exclude RELEASING.rst
exclude tox.ini
prune .github
prune scripts
53 changes: 32 additions & 21 deletions RELEASING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,51 @@
Releasing unittest2pytest
=========================

This document describes the steps to make a new ``unittest2pytest`` release.
``unittest2pytest`` uses `setuptools-scm`_ for version management.
Versions are derived automatically from git tags.

Version
-------
.. _setuptools-scm: https://github.com/pypa/setuptools-scm

``main`` should always be green and a potential release candidate. ``unittest2pytest`` follows
semantic versioning, so given that the current version is ``X.Y.Z``, to find the next version number
one needs to look at the ``CHANGELOG.rst`` file:

- If there any new feature, then we must make a new **minor** release: next
release will be ``X.Y+1.0``.
Relative bump
-------------

- Otherwise it is just a **bug fix** release: ``X.Y.Z+1``.
Run the **Release** workflow, selecting the version bump type:

.. code-block:: console

Steps
-----
gh workflow run release.yml -R pytest-dev/unittest2pytest --field bump=minor

To publish a new release ``X.Y.Z``, the steps are as follows:
Options: ``major``, ``minor``, ``micro``, ``post``. The version is
computed automatically from the latest git tag.

#. Create a new branch named ``release-X.Y.Z`` from the latest ``main``.

#. Update the version in ``unittest2pytest/__init__.py``.
Absolute version
----------------

#. Update the ``CHANGELOG.rst`` file with the new release information.
To release a specific version (e.g. a release candidate):

#. Commit and push the branch to ``upstream`` and open a PR.
.. code-block:: console

#. Once the PR is **green** and **approved**, start the ``deploy`` workflow:
gh workflow run release.yml -R pytest-dev/unittest2pytest --field version=1.0rc1

.. code-block:: console

gh workflow run deploy.yml -R pytest-dev/unittest2pytest --ref release-VERSION --field version=VERSION
What the workflow does
----------------------

The PR will be automatically merged.
#. Runs ``scripts/make_changelog.py`` to replace the ``UNRELEASED`` section
with the version number and today's date.
#. Commits, tags, and pushes.
#. Builds the package.
#. Creates a GitHub Release with the built artifacts.
#. Publishes to PyPI (requires the ``release`` environment).
#. Runs ``scripts/make_changelog.py UNRELEASED`` and pushes a follow-up commit.

#. Update the version in ``unittest2pytest/__init__.py`` and ``CHANGELOG.rst`` for the next release (usually use "minor+1" with the ``.dev0`` suffix).

How versioning works
--------------------

- Tagged commits (e.g. ``v0.6``) produce version ``0.6``.
- Commits after a tag produce dev versions like ``0.7.dev3+gabcdef``.
- The version is written to ``unittest2pytest/_version.py`` at build
time. This file is git-ignored and should not be committed.
11 changes: 3 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["setuptools>=77"]
requires = ["setuptools>=77", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"

[project]
Expand Down Expand Up @@ -43,14 +43,9 @@ include-package-data = false

[tool.setuptools.dynamic]
readme = {file = ["README.rst", "NEWLINE.rst", "CHANGELOG.rst"], content-type = "text/x-rst"}
version = {attr = "unittest2pytest.__version__"}

[tool.zest-releaser]
python-file-with-version = "unittest2pytest/__init__.py"
push-changes = false
tag-format = "v{version}"
tag-message = "unittest2pytest {version}"
tag-signing = true
[tool.setuptools_scm]
version_file = "unittest2pytest/_version.py"

[tool.ruff]
target-version = "py39"
Expand Down
Loading