Skip to content
Merged
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
81 changes: 53 additions & 28 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,54 +1,79 @@
name: Release

# release-please keeps a release PR open on main from the conventional commit messages. Merging
# it tags vX.Y.Z, updates CHANGELOG.md and the version, and the publish job uploads the package
# to PyPI with trusted publishing (OIDC). A tag pushed by hand (git tag v1.2.3 && git push --tags)
# publishes too.

on:
push:
branches: ["main"]
tags: ["v*"]
workflow_dispatch:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

permissions:
contents: write
pull-requests: write
contents: read

jobs:
release-please:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
steps:
- id: release
uses: googleapis/release-please-action@v4
with:
config-file: release-please-config.json
manifest-file: .release-please-manifest.json

publish:
needs: release-please
if: >-
always() &&
(needs.release-please.outputs.release_created == 'true' || startsWith(github.ref, 'refs/tags/v'))
release:
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/template-python/
permissions:
contents: write
id-token: write
contents: read
steps:
- uses: actions/checkout@v4

- uses: astral-sh/setup-uv@v6
with:
python-version: "3.12"

- name: Read package version
id: version
run: |
VERSION="$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"

- name: Check if version is already published to PyPI
id: pypi-check
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
if curl --fail --silent --show-error "https://pypi.org/pypi/template-python/$VERSION/json" >/dev/null; then
echo "template-python==$VERSION is already on PyPI; skipping package upload"
echo "published=true" >> "$GITHUB_OUTPUT"
else
echo "published=false" >> "$GITHUB_OUTPUT"
fi

- name: Build the package
if: steps.pypi-check.outputs.published != 'true'
run: uv build

- name: Check if GitHub release already exists
id: github-release-check
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.version.outputs.tag }}
run: |
if gh api "repos/$GITHUB_REPOSITORY/releases/tags/$TAG" >/dev/null 2>&1; then
echo "GitHub release $TAG already exists; skipping release creation"
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi

- name: Create GitHub release and tag
if: steps.github-release-check.outputs.exists != 'true'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.tag }}
target_commitish: ${{ github.sha }}
name: ${{ steps.version.outputs.tag }}
generate_release_notes: true

- name: Publish to PyPI
if: steps.pypi-check.outputs.published != 'true'
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist
3 changes: 0 additions & 3 deletions .release-please-manifest.json

This file was deleted.

6 changes: 2 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# Changelog

All notable changes to this project are documented in this file. It is maintained by
[release-please](https://github.com/googleapis/release-please) from the commit messages, which
follow [Conventional Commits](https://www.conventionalcommits.org/), and the format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
All notable changes to this project are documented in this file and maintained manually. The
format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [0.1.0] - 2026-10-05

Expand Down
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: template-python
authors:
- family-names: Lindqvist
given-names: Max
version: 0.1.0 # x-release-please-version
version: 0.1.0
date-released: "2026-10-05"
repository-code: https://github.com/max-models/template-python
url: https://max-models.github.io/template-python/
Expand Down
10 changes: 6 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ pre-commit install

Commits follow [Conventional Commits](https://www.conventionalcommits.org/):
`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`, `ci:`. A `feat!:` or a
`BREAKING CHANGE:` footer marks a breaking change. release-please reads these to write the
changelog and choose the next version.
`BREAKING CHANGE:` footer marks a breaking change. Before a release, update the package version
and changelog manually.

## Pull requests

Expand All @@ -42,5 +42,7 @@ the tutorials and the documentation build. One approving review is required to m

## Releases

Merging to `main` lets release-please open or update a release PR. Merging that PR tags the
release, updates `CHANGELOG.md` and publishes the package to PyPI.
Before merging a release to `main`, update the versions in `pyproject.toml`,
`src/app/__init__.py` and `CITATION.cff` (including its release date), and add the release
notes to `CHANGELOG.md`. The push creates a GitHub release with a version tag and publishes the
package to PyPI.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,10 @@ make readme

## Releases

[release-please](https://github.com/googleapis/release-please) keeps a
release PR open on `main` from the commit messages. Merging it tags the
release, updates `CHANGELOG.md` and publishes the package to PyPI with
trusted publishing (OIDC). The one-time PyPI and GitHub configuration is
described in the [publishing
Before merging a release to `main`, update the version in
`pyproject.toml`, `src/app/__init__.py` and `CITATION.cff` (including
its release date), and add the release notes to `CHANGELOG.md`. The push
to `main` creates a GitHub release with a `vX.Y.Z` tag and publishes the
package to PyPI with trusted publishing (OIDC). The one-time PyPI and
GitHub configuration is described in the [publishing
guide](https://max-models.github.io/template-python/development/publishing/).
5 changes: 3 additions & 2 deletions README.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ make readme

## Releases

[release-please](https://github.com/googleapis/release-please) keeps a release PR open on
`main` from the commit messages. Merging it tags the release, updates `CHANGELOG.md` and
Before merging a release to `main`, update the version in `pyproject.toml`,
`src/app/__init__.py` and `CITATION.cff` (including its release date), and add the release
notes to `CHANGELOG.md`. The push to `main` creates a GitHub release with a `vX.Y.Z` tag and
publishes the package to PyPI with trusted publishing (OIDC). The one-time PyPI and GitHub
configuration is described in the
[publishing guide](https://max-models.github.io/template-python/development/publishing/).
13 changes: 5 additions & 8 deletions docs/src/content/docs/development/publishing.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,13 @@ Enable GitHub Pages once in the repository settings, with "GitHub Actions" as th

## Releases and PyPI

The `Release` workflow uses [release-please](https://github.com/googleapis/release-please).
On every push to `main` it opens or updates a release pull request from the
[Conventional Commits](https://www.conventionalcommits.org/) since the last release, with the
next version and the changelog entry. Merging that pull request:
Before merging a release to `main`, update the version in `pyproject.toml`,
`src/app/__init__.py` and `CITATION.cff` (including its release date), and add the release notes
to `CHANGELOG.md`. On every push to `main`, the `Release` workflow:

1. tags the release `vX.Y.Z` and creates the GitHub release,
2. updates `CHANGELOG.md`, the version in `pyproject.toml` and `__version__` in the package,
3. builds the package with `uv build` and publishes it to PyPI with trusted publishing (OIDC).

A tag pushed by hand (`git tag v1.2.3 && git push --tags`) also publishes.
2. builds the package with `uv build` and publishes it to PyPI with trusted publishing (OIDC),
if that version is not already on PyPI.

### One-time configuration

Expand Down
15 changes: 0 additions & 15 deletions release-please-config.json

This file was deleted.

2 changes: 1 addition & 1 deletion src/app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Template python package."""

__version__ = "0.1.0" # x-release-please-version
__version__ = "0.1.0"
Loading