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/pr-types.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"all": ["feat!", "fix!", "revert!", "feat", "fix", "revert", "perf", "docs", "refactor", "test", "ci", "chore"],
"release": ["feat!", "fix!", "revert!", "feat", "fix", "revert", "perf", "docs"]
}
33 changes: 17 additions & 16 deletions .github/scripts/write_release_notes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
import os
import subprocess
import sys

PREFIXES = ["feat:", "fix:", "revert:", "perf:", "docs:"]
from pathlib import Path


def gh(*args: str) -> str:
Expand All @@ -14,14 +13,19 @@ def gh(*args: str) -> str:
return result.stdout.strip()


def latest_tag() -> str:
return gh("release", "list", "-L", "1", "--json", "tagName", "-q", ".[0].tagName")
LATEST_TAG = gh("release", "list", "-L", "1", "--json", "tagName", "-q", ".[0].tagName")


def release_types() -> list[str]:
"""Return the PR types that appear in release notes."""
pr_types_file = Path(__file__).parent.parent / "pr-types.json"
return json.loads(pr_types_file.read_text())["release"]


def merged_prs() -> list[dict]:
"""Return the number and title of PRs merged since the latest release."""
repo = os.environ["GITHUB_REPOSITORY"]
release_date = gh("api", f"repos/{repo}/releases/tags/{latest_tag()}", "--jq", ".created_at")
release_date = gh("api", f"repos/{repo}/releases/tags/{LATEST_TAG}", "--jq", ".created_at")
prs = gh(
"pr",
"list",
Expand All @@ -36,27 +40,24 @@ def merged_prs() -> list[dict]:
"--limit",
"50",
)
return json.loads(prs)
return json.loads(prs)[::-1] # Put oldest merged first.


def release_notes(prs: list[dict], new_tag: str) -> str:
"""Return the release notes body for the given PRs.

Groups PRs by title prefix then breaking/non-breaking.
Groups PRs by title prefix, in the order given by pr-types.json.
"""
entries = ""
for prefix in PREFIXES:
breaking_prefix = f"{prefix.removesuffix(':')}!:"
group = sorted(
(pr for pr in prs if pr["title"].startswith((prefix, breaking_prefix))),
key=lambda pr: (not pr["title"].startswith(breaking_prefix), pr["number"]),
)
for pr in group:
entries += f"- {pr['title']} (#{pr['number']})\n"
for pr_type in release_types():
prefix = f"{pr_type}:"
for pr in prs:
if pr["title"].startswith(prefix):
entries += f"- {pr['title']} (#{pr['number']})\n"
if not entries:
entries = "This is a maintenance release with no fixes or new features.\n"
repo = os.environ["GITHUB_REPOSITORY"]
return f"{entries}\nChangelog: https://github.com/{repo}/compare/{latest_tag()}...{new_tag}"
return f"{entries}\nChangelog: https://github.com/{repo}/compare/{LATEST_TAG}...{new_tag}"


if __name__ == "__main__":
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/deps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Check Python deps

on:
pull_request:
push:
branches:
- main

permissions: {}

jobs:
deps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
- name: Check uv.lock
run: uv lock --check
28 changes: 28 additions & 0 deletions .github/workflows/pr-title.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Check PR title

on:
pull_request:
types:
- opened
- edited

permissions: {}

jobs:
pr-title:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check PR title
env:
TITLE: ${{ github.event.pull_request.title }}
run: |
set -euo pipefail
types="$(jq -r '.all | join(", ")' .github/pr-types.json)"
pattern="^(${types//, /|}): "
if [[ ! "$TITLE" =~ $pattern ]]; then
echo "PR title must start with one of: ${types}." >&2
exit 1
fi
3 changes: 1 addition & 2 deletions .github/workflows/zizmor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ jobs:
permissions:
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install uv
Expand Down
Loading