prepare-release-pr.py
Overview
`prepare-release-pr.py` is a utility script designed to automate part of the release process for the `pytest` project. It is intended to be run manually from the GitHub Actions interface but can also be executed locally. The script streamlines the creation of a release pull request (PR) by:
Checking out the specified base branch (e.g.,
main,6.1.x).Determining the next version number automatically based on the base branch, the kind of release (major/minor/patch), and whether it is a pre-release.
Creating a new release branch named
release-{version}.Running the release process using the
toxtool within a dedicated environment.Pushing the release branch to the remote repository.
Creating a pull request draft via the GitHub CLI (
gh).
This script requires the `gh` CLI tool and an environment variable `GH_TOKEN` set for authentication.
Detailed Explanation of Components
Exception Classes
InvalidFeatureRelease(Exception)
A custom exception raised when an invalid feature release condition occurs.
Usage is internal to the script, specifically in version calculation validation.
Constants
SLUG: The GitHub repository slug,"pytest-dev/pytest".PR_BODY: Template string for the body of the pull request created by this script. It includes instructions for maintainers on how to proceed with deployment after the PR is approved.
Functions
prepare_release_pr(base_branch: str, is_major: bool, prerelease: str) -> None
Primary function that orchestrates the release PR preparation.
**Parameters:**
base_branch(str): The Git branch to start the release from (e.g.,"main","6.1.x").is_major(bool): Whether this release is a major release.prerelease(str): Prerelease suffix, e.g.,"rc1","beta1". Empty string means no prerelease.
**Returns:** None
**Description:**
Checks out the remote base branch.
Scans the
changelogdirectory for.feature.rstand.breaking.rstfiles to detect if this is a feature release.Calls find_next_version() to calculate the next version string based on the release type.
Configures Git user information to a bot identity.
Creates a new release branch named
release-{version}.Decides on the release template depending on the release type:
Major release:
release.major.rstPrerelease:
release.pre.rstFeature (minor) release:
release.minor.rstPatch release:
release.patch.rst
Runs the
toxenvironment namedreleaseto perform the release tasks.Pushes the new release branch to origin.
Creates a draft pull request using the
ghCLI with the new release branch as the head and the base branch as the target.
**Usage Example:**
prepare_release_pr("main", is_major=False, prerelease="")
find_next_version(base_branch: str, is_major: bool, is_feature_release: bool, prerelease: str) -> str
Calculates the next semantic version string based on existing git tags and release type.
**Parameters:**
base_branch(str): The branch to base the release on (not directly used in this function).is_major(bool): Whether the next release is major.is_feature_release(bool): Whether the release includes features or breaking changes.prerelease(str): Prerelease suffix to append (e.g.,"rc1").
**Returns:** `str` - A string representing the next version number, e.g., `"7.0.0"`, `"6.2.0rc1"`, `"6.1.3"`.
**Description:**
Retrieves all git tags that match the semantic version pattern
X.Y.Z.Parses these tags to tuples of integers and sorts them.
Determines the next version:
If
is_majoris True, increments the major version and resets minor and patch to zero.Else if it is a feature release, increments the minor version and resets patch.
Otherwise, increments the patch version.
Appends the prerelease suffix if provided.
**Important Implementation Detail:**
The regex used for version tags is
\d.\d.\d+$which matches versions like6.1.2. It does not consider tags with prefixes likev(e.g.,v6.1.2would be ignored).The function assumes the latest tag is the last after sorting all valid versions.
**Example:**
If the latest tag is `6.1.3`:
Major release →
"7.0.0"Feature release →
"6.2.0"Patch release →
"6.1.4"Prerelease with patch →
"6.1.4rc1"
main() -> None
Entry point for command-line execution.
Initializes colorama for colored terminal output.
Parses command-line arguments:
base_branch(positional): Base git branch for the release.--major(flag): Whether the release is major.--prerelease(optional): Pre-release suffix.
Calls
prepare_release_prwith parsed options.
**CLI Usage Example:**
python prepare-release-pr.py main --major --prerelease rc1
Important Implementation Details and Algorithms
Version parsing and incrementing: The script uses git tags to determine the last released version. It then increments the version number based on the release type using simple semantic versioning rules.
Changelog-based feature detection: Presence of
*.feature.rstor*.breaking.rstfiles in thechangelogdirectory triggers a feature release (minor version bump).Use of
toxenvironment: The release process leverages a tox environment namedreleaseto handle the actual release tasks such as version bumping, changelog rendering, and packaging.Git and GitHub CLI integration: The script automates branch creation, pushing, and PR creation through shell commands, requiring
gitandghCLI tools to be installed and configured.Environment requirement:
GH_TOKENmust be set for the GitHub CLI to authenticate when creating PRs.
Interaction with Other Parts of the System
Changelog Files: Reads files from the
changelogdirectory to determine the release type.Git Repository: Operates directly on the git repository by checking out branches, creating release branches, and pushing them.
Tox Environment: Runs the
releasetox environment which is expected to be defined elsewhere in the project (likely intox.ini), encapsulating release build logic.GitHub Actions: The script is designed to be triggered as part of a GitHub Actions workflow (
prepare-release-pr.yml), and it creates a PR that triggers further workflows such as deployment.
Visual Diagram
flowchart TD
A[main()] --> B[parse command-line args]
B --> C[prepare_release_pr(base_branch, is_major, prerelease)]
subgraph prepare_release_pr
C --> D[git checkout origin/base_branch]
D --> E[scan changelog/*.feature.rst, *.breaking.rst]
E --> F{is_feature_release?}
F --> G[find_next_version(base_branch, is_major, is_feature_release, prerelease)]
G --> H[create release branch release-{version}]
H --> I[configure git user as pytest bot]
I --> J[determine release template]
J --> K[tox -e release -- ...]
K --> L[git push origin release branch]
L --> M[create draft PR with gh CLI]
end
Summary
`prepare-release-pr.py` automates the initial stages of the pytest project release process by:
Detecting the type of release and next semantic version.
Creating and pushing a release branch.
Running release steps in the tox environment.
Creating a draft pull request on GitHub for maintainers to review.
It tightly integrates with the git repository, changelog files, tox environments, and GitHub workflows, serving as a critical tool for managing releases smoothly and consistently.