144 lines
5.1 KiB
YAML
144 lines
5.1 KiB
YAML
name: Create release PR
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
version:
|
|
description: "Version to release (e.g., 0.6.6)"
|
|
required: true
|
|
|
|
permissions:
|
|
contents: write
|
|
pull-requests: write
|
|
|
|
jobs:
|
|
release-pr:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
|
|
with:
|
|
fetch-depth: 0
|
|
ref: main
|
|
- name: Setup uv
|
|
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # setup-uv v8.1.0; uv 0.11.14
|
|
with:
|
|
version: "0.11.14"
|
|
enable-cache: true
|
|
- name: Fetch tags
|
|
run: git fetch origin --tags --prune
|
|
- name: Ensure release branch does not exist
|
|
env:
|
|
RELEASE_VERSION: ${{ inputs.version }}
|
|
run: |
|
|
branch="release/v${RELEASE_VERSION}"
|
|
if git ls-remote --exit-code --heads origin "$branch" >/dev/null 2>&1; then
|
|
echo "Branch $branch already exists on origin." >&2
|
|
exit 1
|
|
fi
|
|
- name: Update version
|
|
env:
|
|
RELEASE_VERSION: ${{ inputs.version }}
|
|
run: |
|
|
python - <<'PY'
|
|
import os
|
|
import pathlib
|
|
import re
|
|
import sys
|
|
|
|
version = os.environ["RELEASE_VERSION"]
|
|
if version.startswith("v"):
|
|
print("Version must not start with 'v' (use x.y.z...).", file=sys.stderr)
|
|
sys.exit(1)
|
|
if ".." in version:
|
|
print("Version contains consecutive dots (use x.y.z...).", file=sys.stderr)
|
|
sys.exit(1)
|
|
if not re.match(r"^\d+\.\d+(\.\d+)*([a-zA-Z0-9\.-]+)?$", version):
|
|
print(
|
|
"Version must be semver-like (e.g., 0.6.6, 0.6.6-rc1, 0.6.6.dev1).",
|
|
file=sys.stderr,
|
|
)
|
|
sys.exit(1)
|
|
path = pathlib.Path("pyproject.toml")
|
|
text = path.read_text()
|
|
updated, count = re.subn(
|
|
r'(?m)^version\s*=\s*"[^\"]+"',
|
|
f'version = "{version}"',
|
|
text,
|
|
)
|
|
if count != 1:
|
|
print("Expected to update exactly one version line.", file=sys.stderr)
|
|
sys.exit(1)
|
|
if updated == text:
|
|
print("Version already set; no changes made.", file=sys.stderr)
|
|
sys.exit(1)
|
|
path.write_text(updated)
|
|
PY
|
|
- name: Sync dependencies
|
|
run: make sync
|
|
- name: Configure git
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
- name: Create release branch and commit
|
|
env:
|
|
RELEASE_VERSION: ${{ inputs.version }}
|
|
run: |
|
|
branch="release/v${RELEASE_VERSION}"
|
|
git checkout -b "$branch"
|
|
git add pyproject.toml uv.lock
|
|
if git diff --cached --quiet; then
|
|
echo "No changes to commit." >&2
|
|
exit 1
|
|
fi
|
|
git commit -m "Bump version to ${RELEASE_VERSION}"
|
|
git push --set-upstream origin "$branch"
|
|
- name: Build PR body
|
|
env:
|
|
RELEASE_VERSION: ${{ inputs.version }}
|
|
run: |
|
|
printf 'Release PR for %s.\n\nThe release readiness report will be prepared manually.\n' "$RELEASE_VERSION" > pr-body.md
|
|
- name: Create or update PR
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
RELEASE_VERSION: ${{ inputs.version }}
|
|
run: |
|
|
set -euo pipefail
|
|
head_branch="release/v${RELEASE_VERSION}"
|
|
milestone_name="$(python .github/scripts/select-release-milestone.py --version "$RELEASE_VERSION")"
|
|
pr_number="$(gh pr list --head "$head_branch" --base "main" --json number --jq '.[0].number // empty')"
|
|
if [ -z "$pr_number" ]; then
|
|
create_args=(
|
|
--title "Release ${RELEASE_VERSION}"
|
|
--body-file pr-body.md
|
|
--base "main"
|
|
--head "$head_branch"
|
|
--label "project"
|
|
)
|
|
if [ -n "$milestone_name" ]; then
|
|
create_args+=(--milestone "$milestone_name")
|
|
fi
|
|
if ! gh pr create "${create_args[@]}"; then
|
|
echo "PR create with label/milestone failed; retrying without them." >&2
|
|
gh pr create \
|
|
--title "Release ${RELEASE_VERSION}" \
|
|
--body-file pr-body.md \
|
|
--base "main" \
|
|
--head "$head_branch"
|
|
fi
|
|
else
|
|
edit_args=(
|
|
--title "Release ${RELEASE_VERSION}"
|
|
--body-file pr-body.md
|
|
--add-label "project"
|
|
)
|
|
if [ -n "$milestone_name" ]; then
|
|
edit_args+=(--milestone "$milestone_name")
|
|
fi
|
|
if ! gh pr edit "$pr_number" "${edit_args[@]}"; then
|
|
echo "PR edit with label/milestone failed; retrying without them." >&2
|
|
gh pr edit "$pr_number" --title "Release ${RELEASE_VERSION}" --body-file pr-body.md
|
|
fi
|
|
fi
|