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
4 changes: 4 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
labels:
- dependencies
- github_actions
- skip news
schedule:
interval: "weekly"
day: "tuesday"
Expand Down
34 changes: 33 additions & 1 deletion .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches: ["main"]
tags-ignore: ["**"]
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]
schedule:
- cron: "0 8 * * *"

Expand Down Expand Up @@ -46,7 +47,7 @@ jobs:
fetch-depth: 0
persist-credentials: false
- name: Install the latest version of uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
python-version: "3.15"
enable-cache: false
Expand All @@ -71,3 +72,34 @@ jobs:
PYTEST_ADDOPTS: "-vv --durations=20"
DIFF_AGAINST: HEAD
UV_PYTHON_PREFERENCE: only-managed

changelog:
if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'skip news')
runs-on: ubuntu-26.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
python-version: "3.15"
enable-cache: false
- run: uvx towncrier check --compare-with "origin/${GITHUB_BASE_REF}"

gate:
name: Required checks pass
if: always()
needs: [test, changelog]
runs-on: ubuntu-26.04
steps:
- env:
NEEDS_JSON: ${{ toJSON(needs) }}
run: |
jq -e '
all(
to_entries[];
.value.result == "success" or
(.key == "changelog" and .value.result == "skipped")
)
' <<< "$NEEDS_JSON"
109 changes: 109 additions & 0 deletions .github/workflows/prepare-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Prepare release
on:
workflow_dispatch:
inputs:
version:
description: Version to release, without a v prefix
required: true

permissions: {}

concurrency:
group: prepare-release
cancel-in-progress: false

jobs:
assemble:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-26.04
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
python-version: "3.15"
enable-cache: false
- name: Build release patch
env:
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::expected a major.minor.patch version"
exit 1
fi
latest=$(git tag --list '[0-9]*' | sort -V | tail -n 1)
if [[ "$(printf '%s\n' "$latest" "$VERSION" | sort -V | tail -n 1)" != "$VERSION" || "$latest" == "$VERSION" ]]; then
echo "::error::$VERSION must be newer than $latest"
exit 1
fi
if ! compgen -G 'docs/changelog.d/*.rst' > /dev/null; then
echo "::error::no changelog fragments to release"
exit 1
fi
uvx towncrier build --yes --version "$VERSION"
git diff HEAD --binary > "$RUNNER_TEMP/release.patch"
test -s "$RUNNER_TEMP/release.patch"
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-patch
path: ${{ runner.temp }}/release.patch
if-no-files-found: error
push:
needs: assemble
runs-on: ubuntu-26.04
environment: release-auth
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: release-patch
path: ${{ runner.temp }}/release-patch
- name: Validate release patch
env:
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
git fetch origin main
git reset --hard origin/main
git apply --check "$RUNNER_TEMP/release-patch/release.patch"
git apply --index "$RUNNER_TEMP/release-patch/release.patch"
while IFS= read -r path; do
case "$path" in
docs/changelog.rst|docs/changelog.d/*.rst) ;;
*) echo "::error::unexpected release path: $path"; exit 1 ;;
esac
done < <(git diff --cached --name-only)
grep -Fq "v$VERSION (" docs/changelog.rst
git diff --cached --check
- id: token
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
with:
client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: ${{ github.event.repository.name }}
permission-contents: write
- name: Commit and tag the release
env:
VERSION: ${{ inputs.version }}
GH_TOKEN: ${{ steps.token.outputs.token }}
APP_SLUG: ${{ steps.token.outputs.app-slug }}
run: |
set -euo pipefail
app_user_id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id)
git config user.name "${APP_SLUG}[bot]"
git config user.email "${app_user_id}+${APP_SLUG}[bot]@users.noreply.github.com"
git commit -m "chore: prepare $VERSION"
git tag "$VERSION"
gh auth setup-git --hostname github.com --force
git push --atomic origin HEAD:main "refs/tags/$VERSION"
44 changes: 43 additions & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,20 @@ jobs:
with:
fetch-depth: 0
persist-credentials: false
- name: Require a changelog section for the tag
env:
TAG: ${{ github.ref_name }}
run: |
if [[ ! "$TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::unexpected release tag $TAG"
exit 1
fi
if ! grep -qF "v$TAG (" docs/changelog.rst; then
echo "::error::docs/changelog.rst has no section for $TAG"
exit 1
fi
- name: Install the latest version of uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
python-version: "3.15"
enable-cache: false
Expand Down Expand Up @@ -51,3 +63,33 @@ jobs:
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
attestations: true
github-release:
needs: release
runs-on: ubuntu-26.04
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Publish GitHub Release
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
awk -v tag="$TAG" '
index($0, "v" tag " (") == 1 { found = 1; next }
found && /^v[0-9]+\.[0-9]+\.[0-9]+ \(/ { exit }
found && $0 !~ /^-+$/ { print }
' docs/changelog.rst > "$RUNNER_TEMP/release-notes.md"
test -s "$RUNNER_TEMP/release-notes.md"
printf '\n[PyPI release](https://pypi.org/project/pyproject-api/%s/)\n' "$TAG" >> "$RUNNER_TEMP/release-notes.md"
previous=$(git tag --list '[0-9]*' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | awk -v tag="$TAG" '$0 == tag { print previous; exit } { previous = $0 }')
if [[ -n "$previous" ]]; then
printf '\n**Full Changelog**: https://github.com/%s/compare/%s...%s\n' "$GITHUB_REPOSITORY" "$previous" "$TAG" >> "$RUNNER_TEMP/release-notes.md"
else
printf '\n**Full Changelog**: https://github.com/%s/commits/%s\n' "$GITHUB_REPOSITORY" "$TAG" >> "$RUNNER_TEMP/release-notes.md"
fi
gh release create "$TAG" --verify-tag --title "$TAG" --notes-file "$RUNNER_TEMP/release-notes.md"
Empty file added docs/changelog.d/.gitkeep
Empty file.
148 changes: 148 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
Release History
===============

.. towncrier release notes start

v1.12.0 (2026-10-18)
--------------------
- Validate in-tree backend paths and reject metadata directories that contain the project root.
- Contain response serialization failures.

v1.11.7 (2026-10-15)
--------------------
- Resolve dotted backend object paths.

v1.11.6 (2026-10-14)
--------------------
- Resolve output directories before invoking backends.

v1.11.5 (2026-10-10)
--------------------
- Require Python 3.11, default to Python 3.15, and import in-tree backends from relative roots.

v1.11.4 (2026-10-07)
--------------------
- Stop hanging on undecodable backend output.

v1.11.3 (2026-10-03)
--------------------
- Validate ``build-system`` value types when reading a project folder.

v1.11.2 (2026-09-18)
--------------------
- Avoid pipe deadlocks when sending large backend requests.

v1.11.1 (2026-09-15)
--------------------
- Remove directory symlinks in ``ensure_empty_dir``.

v1.11.0 (2026-07-21)
--------------------
- Add Python 3.15 to the test matrix.

v1.10.1 (2026-05-28)
--------------------
- Move development tooling to ``tox.toml``, dependency groups, and ty.

v1.10.0 (2025-10-09)
--------------------
- Add Python 3.14 support and end support for Python 3.9.

v1.9.1 (2025-05-12)
-------------------
- Remove ``wheel`` from the default requirements.

v1.9.0 (2025-01-21)
-------------------
- Update project maintenance metadata.

v1.8.0 (2024-09-18)
-------------------
- Finish dropping Python 2 support.

v1.7.2 (2024-09-17)
-------------------
- Improve CI.

v1.7.1 (2024-06-22)
-------------------
- Move release notes from the documentation site to GitHub Releases.

v1.7.0 (2024-06-22)
-------------------
- Correct the documentation homepage URL and update build dependencies.

v1.6.1 - (2023-08-29)
---------------------
- Fix :meth:`pyproject_api.Frontend.metadata_from_built` only extracts one of the dist info files.

v1.6.0 - (2023-08-29)
---------------------
- Remove ``build_<wheel|editable>`` from ``prepare_metadata_for_build_<wheel|editable>`` to allow separate config
parametrization and instead add :meth:`pyproject_api.Frontend.metadata_from_built` the user can call when the prepare
fails. Pass ``None`` for ``metadata_directory`` for such temporary wheel builds.

v1.5.4 - (2023-08-17)
---------------------
- Make sure that the order of Requires-Dist does not matter

v1.5.3 - (2023-07-06)
---------------------
- Fix ``read_line`` to raise ``EOFError`` if nothing was read

v1.5.2 - (2023-06-14)
---------------------
- Use ruff for linting.
- Drop 2.7 test run.

v1.5.1 - (2023-03-12)
---------------------
- docs: set html_last_updated_fmt to format string

v1.5.0 - (2023-01-17)
---------------------
- When getting metadata from a built wheel, do not pass ``metadata_directory``
to ``build_wheel``, which forces the backend to generate the metadata - by :user:`masenf`.
(`#47 <https://github.com/tox-dev/pyproject-api/issues/47>`_)

v1.4.0 - (2023-01-04)
---------------------
- Add minimal CLI for debugging

v1.3.0 - (2023-01-03)
---------------------
- Do not allow exceptions to propagate in backend

v1.2.1 - (2022-12-04)
---------------------
- Fix Python 2 incompatibility on the backend
- Allow skipping prepare metadata for the full build by returning None as basename

v1.2.0 - (2022-12-04)
---------------------
- Expose which optional hooks are present or missing via :meth:`pyproject_api.Frontend.optional_hooks`

v1.1.2 - (2022-10-30)
---------------------
- Fix editable classes not exported at root level

v1.1.1 - (2022-09-10)
---------------------
- Add missed ``wheel`` as test dependency

v1.1.0 - (2022-09-10)
---------------------
- PEP-660 support

v1.0.0 - (2022-09-10)
---------------------
- Use hatchling as build backend
- 3.11 support

v0.1.1 - (2021-12-30)
---------------------
- Drop Python 3.6 support

v0.1.0 - (2021-10-21)
---------------------
- first version
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"sphinx.ext.intersphinx",
]
master_doc, source_suffix = "index", ".rst"
exclude_patterns = ["changelog.d/*"]

html_theme = "furo"
html_title, html_last_updated_fmt = "pyproject-api docs", "%Y-%m-%dT%H:%M:%S"
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@

self
api
changelog
Loading
Loading