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: 2 additions & 2 deletions .ci/gate
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ set -euo pipefail
# - Opt in with: GATE_REAL=1 gate
# - Or pass custom args: GATE_PYTEST_ARGS='-m real' gate

uvx ruff format --check .
uvx ruff check .
uv run --locked --group dev ruff format --check .
uv run --locked --group dev ruff check .

py_versions=(3.10 3.11 3.12 3.13 3.14)

Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Lint

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
lint:
name: Lint and format check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Run ruff formatter check
run: uv run --locked --group dev ruff format --check .

- name: Run ruff linter
run: uv run --locked --group dev ruff check .

- name: Validate pyproject.toml
run: uvx validate-pyproject pyproject.toml

- name: Validate changelog fragments
run: |
set -euo pipefail
if uv run --locked --group dev scriv print; then
exit 0
else
status=$?
if [ "$status" -eq 2 ]; then
echo "::notice::No changelog fragments to collect"
exit 0
fi
exit "$status"
fi
117 changes: 117 additions & 0 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: Prepare Release

on:
workflow_dispatch:
inputs:
version:
description: "Version to prepare (e.g., 1.0.0)"
required: true
type: string

permissions:
contents: write
pull-requests: write

jobs:
prepare:
name: Collect changelog and prepare release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Collect changelog fragments
env:
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
if uv run --locked --group dev scriv collect --version "$VERSION"; then
echo "Changelog fragments collected"
else
status=$?
if [ "$status" -eq 2 ]; then
echo "::notice::No changelog fragments to collect"
exit 0
fi
exit "$status"
fi

- name: Commit, push branch, and open PR
env:
BASE_BRANCH: ${{ github.ref_name }}
GH_TOKEN: ${{ github.token }}
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail

if git diff --quiet; then
echo "::notice::No changes to commit"
exit 0
fi

branch="release-prep/${BASE_BRANCH}/v${VERSION}"
title="Collect changelog for v${VERSION}"
body_file="$(mktemp)"
{
printf '%s\n' "## What changed"
printf '%s\n' "* Collect changelog fragments for \`v${VERSION}\`."
printf '\n'
printf '%s\n' "## Why"
printf '%s\n' "* Prepare the release changelog in a reviewable pull request."
printf '%s\n' "* Avoid pushing an unsigned automation commit to the protected"
printf '%s\n' " base branch."
printf '\n'
printf '%s\n' "## How to test"
printf '%s\n' "* Inspect the generated \`CHANGELOG.md\` update and removed fragments."
printf '%s\n' "* Run \`uv run --locked --group dev scriv collect --version ${VERSION}\`"
printf '%s\n' " locally to reproduce."
printf '\n'
printf '%s\n' "## Risk/comp notes"
printf '%s\n' "* Scope is limited to the generated \`CHANGELOG.md\` update and"
printf '%s\n' " removal of collected fragments."
printf '%s\n' "* Review the collected release notes before merge."
printf '\n'
printf '%s\n' "## Changelog fragment"
printf '%s\n' "* No. This PR consumes existing fragments for \`v${VERSION}\`."
} >"$body_file"

git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git fetch origin "$branch" || true
git switch -C "$branch"
git add -u CHANGELOG.md changelog.d/
git commit -m "$title"
git push --force-with-lease --set-upstream origin "$branch"

existing_pr_number="$(gh pr list \
--repo "$GITHUB_REPOSITORY" \
--base "$BASE_BRANCH" \
--head "$branch" \
--state open \
--json number \
--jq '.[0].number // empty')"

if [ -n "$existing_pr_number" ]; then
gh pr edit "$existing_pr_number" \
--repo "$GITHUB_REPOSITORY" \
--title "$title" \
--body-file "$body_file"
exit 0
fi

gh pr create \
--repo "$GITHUB_REPOSITORY" \
--base "$BASE_BRANCH" \
--head "$branch" \
--title "$title" \
--body-file "$body_file"
33 changes: 33 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
tests:
name: Run tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Install dependencies
run: uv sync --locked --group dev

- name: Run pytest
run: uv run --locked --group dev pytest -q tests/ -m "not real"
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Repository = "https://github.com/sderev/shellgenius"
[dependency-groups]
dev = [
"pytest>=8,<9",
"ruff==0.15.8",
"scriv[toml]>=1.8,<2",
]

Expand All @@ -48,6 +49,9 @@ markers = [
]
testpaths = ["tests"]

[tool.ruff]
line-length = 100

[tool.scriv]
changelog = "CHANGELOG.md"
format = "md"
Expand Down
27 changes: 27 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading