Skip to content

Commit

Permalink
chore(ci): automate release process
Browse files Browse the repository at this point in the history
This PR significant changes the release process, by mostly automating it
all. The docs on creating releases has been updated and moved into the
`docs/` folder (anticipating that we will use MkDocs eventually).

The check step in the build pipeline has been removed, as it is
redundant given that cibuildwheel already does checks.

Signed-off-by: JP-Ellis <[email protected]>
  • Loading branch information
JP-Ellis committed Mar 4, 2024
1 parent e9898fa commit 9604839
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 128 deletions.
19 changes: 19 additions & 0 deletions .github/CHANGELOG.md.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{% for entry in tree %}

## {{ entry.version }}{% if entry.date %} ({{ entry.date }}){% endif %}

{% for change_key, changes in entry.changes.items() %}

{% if change_key %}
### {{ change_key }}
{% endif %}

{% for change in changes %}
{% if change.scope %}
- **{{ change.scope }}**: {{ change.message }}
{% elif change.message %}
- {{ change.message }}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
57 changes: 53 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ env:
CIBW_BUILD_FRONTEND: build

jobs:
build-sdit:
build-sdist:
name: Build source distribution

if: github.event_name == 'push' || ! github.event.pull_request.draft
Expand Down Expand Up @@ -114,7 +114,7 @@ jobs:
build-arm64:
name: Build wheels on ${{ matrix.os }} (arm64)

# As this requires emulation, it's not worth running on PRs
# As this requires emulation, it's not worth running on PRs or master
if: >-
github.event_name == 'push' &&
startsWith(github.event.ref, 'refs/tags')
Expand Down Expand Up @@ -189,26 +189,75 @@ jobs:
pipx run twine check --strict wheelhouse/*
publish:
name: Publish wheels
name: Publish wheels and sdist

if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v')
runs-on: ubuntu-latest
environment: pypi

needs: [check]
needs:
- build-sdist
- build-x86_64
- build-arm64

permissions:
# Required for trusted publishing
id-token: write
# Required for release creation
contents: write

steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4
with:
path: wheels
merge-multiple: true

- name: Setup Python
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5
with:
python-version: ${{ env.STABLE_PYTHON_VERSION }}

- name: Update changelog
id: changelog
run: |
pip install --upgrade commitizen
cz changelog \
--incremental \
--template .github/CHANGELOG.md.j2 \
--dry-run \
| tail -n+2 \
> ${{ runner.temp }}/changelog
echo -e "\n\n## Pull Requests\n\n" >> ${{ runner.temp }}/changelog
cz changelog \
--incremental \
--template .github/CHANGELOG.md.j2
- name: Generate release
id: release
uses: softprops/action-gh-release@v1
with:
files: wheels/*
body_path: ${{ runner.temp }}/changelog
draft: false
prerelease: false
generate_release_notes: true

- name: Push build artifacts to PyPI
uses: pypa/gh-action-pypi-publish@e53eb8b103ffcb59469888563dc324e3c8ba6f06 # v1.8.12
with:
skip-existing: true
password: ${{ secrets.PYPI_TOKEN }}
packages-dir: wheels

- name: Create PR for changelog update
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GH_TOKEN }}
commit-message: "chore: update changelog ${{ github.ref_name }}"
title: "chore: update changelog"
body: |
This PR updates the changelog for ${{ github.ref_name }}.
branch: chore/update-changelog
base: master
54 changes: 0 additions & 54 deletions RELEASING.md

This file was deleted.

49 changes: 49 additions & 0 deletions docs/releases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Releases

Pact Python is made available through both GitHub releases and PyPI. The GitHub releases also come with a summary of changes and contributions since the last release.

The entire process is automated through the [build](https://github.com/pact-foundation/pact-python/actions?query=workflow%3Abuild) GitHub Action. A description of the process is provided [below](#build-pipeline).

## Versioning

Pact Python follows [semantic versioning](https://semver.org/). Breaking changes are indicated by a major version bump, new features by a minor version bump, and bug fixes by a patch version bump.

There are a couple of exceptions to the [semantic versioning](https://semver.org/) rules:

- Dropping support for a Python version is not considered a breaking change and is not necessarily accompanied by a major version bump.
- Private APIs are not considered part of the public API and are not subject to the same rules as the public API. They can be changed at any time without a major version bump. Private APIs are denoted by a leading underscore in the name. Please be aware that the distinction between public and private APIs will be made concrete from version 3 onwards, and best judgement is used in the meantime to determine what is public and what is private.
- Deprecations are not considered breaking changes and are not necessarily accompanied by a major version bump. Their removal is considered a breaking change and is accompanied by a major version bump.

Any deviation from the the standard semantic versioning rules will be clearly documented in the release notes.

The version is stored in `pact/__version__.py`. This file is automatically generated by [`hatch-vcs`](https://pypi.org/project/hatch-vcs/) and generates a version based on the latest version tag and the number of commits since that tag. Specifically:

- If the latest tag is `v1.2.3` and there have been no commits since then and the repository is clean, the version will be `1.2.3`.
- Otherwise, the version will take the form of `1.2.3.dev{N}+g{hash}` (or `1.2.3.dev{N}+g{hash}.d{date}` if there's a dirty repository) where `N` is the number of commits since the latest tag, `hash` is the short hash of the latest commit.

## Build Pipeline

The build pipeline is defined in `.github/workflows/build.yml`. It is triggered on PRs targeting `master`, pushes to the `master` branch, and on every new tag. The pipeline is responsible for building the package (both as source distribution, and compiled wheels), creating the GitHub release, and uploading artifacts to PyPI.

### Build Steps

The build steps generates the source distribution and wheels. This is done using [cibuildwheel](https://cibuildwheel.readthedocs.io/) to ensure that the wheels are compatible with a wide range of Python versions and platforms.

In order to reduce the build time, the pipeline builds different sets of wheels depending on the trigger:

| Trigger | Platforms | Wheels |
| ------------ | ----------------- | --------- |
| Tag | `x86_64`, `arm64` | all |
| `master` | `x86_64` | all |
| Pull Request | `x86_64` | `cp312-*` |

### Publish Step

The publish step uses the `pypi` GitHub environment, and is gated behind a manual approval. The publish step is responsible for the following:

- Generating a changelog based on the conventional commits since the latest release.
- Generating a new GitHub release with the changelog.
- Uploading the source distribution and wheels to PyPI.
- Creating a PR to update the `CHANGELOD.md` file with the new release notes.

While the generated changelog should be accurate, it may require some manual adjustments on the release page and in the PR.
40 changes: 0 additions & 40 deletions script/commit_message.py

This file was deleted.

30 changes: 0 additions & 30 deletions script/release_prep.sh

This file was deleted.

0 comments on commit 9604839

Please sign in to comment.