Skip to content

Release v0.8.0

Release v0.8.0 #17

Workflow file for this run

name: Publish to PyPI
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run (build but do not publish)'
required: false
default: false
type: boolean
permissions:
contents: read
id-token: write # Required for trusted publishing
jobs:
quality:
name: Quality Checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --dev
- name: Run ruff check
run: uv run ruff check .
- name: Run ruff format check
run: uv run ruff format --check .
- name: Run tests
run: uv run pytest -m "not e2e and not network and not slow"
build:
name: Build Package
needs: quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Set up Python
run: uv python install 3.12
- name: Build package
run: uv build
- name: Verify package
run: |
uv venv .venv
uv pip install dist/*.whl
.venv/bin/python -c "import agr; print(f'Built version: {agr.__version__}')"
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
publish:
name: Publish to PyPI
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'push' || !inputs.dry_run
environment:
name: pypi
url: https://pypi.org/project/agr/
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
# Uses trusted publishing (OIDC) - no API token needed
# Configure at: https://pypi.org/manage/project/agr/settings/publishing/
release:
name: Create GitHub Release
needs: publish
runs-on: ubuntu-latest
if: github.event_name == 'push' || !inputs.dry_run
permissions:
contents: write # Only this job needs write access
env:
TAG_NAME: ${{ github.ref_name }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- name: Validate tag format
run: |
if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([ab][0-9]+)?$ ]]; then
echo "Error: Invalid tag format '$TAG_NAME'"
echo "Expected format: vX.Y.Z or vX.Y.Za1/vX.Y.Zb1 (e.g., v0.6.5, v0.7.1b1)"
exit 1
fi
- name: Extract release notes from CHANGELOG
run: |
if [ ! -f CHANGELOG.md ]; then
echo "Error: CHANGELOG.md not found"
exit 1
fi
VERSION_NUM="${TAG_NAME#v}" # Remove 'v' prefix
# Extract section for this version from CHANGELOG.md
# Matches from [X.Y.Z] until the next [X.Y.Z] or end of file
NOTES=$(awk -v ver="$VERSION_NUM" '
/^## \[/ {
if (found) exit
if ($0 ~ "\\[" ver "\\]") found=1
next
}
found { print }
' CHANGELOG.md)
if [ -z "$NOTES" ]; then
echo "Error: Version $VERSION_NUM not found in CHANGELOG.md"
echo "Make sure CHANGELOG.md has a section like: ## [$VERSION_NUM] - YYYY-MM-DD"
exit 1
fi
# Write to file for gh release
{
echo "## What's New in $TAG_NAME"
echo ""
echo "$NOTES"
echo ""
echo "---"
echo ""
echo "**Full changelog**: ${{ github.server_url }}/${{ github.repository }}/blob/main/CHANGELOG.md"
} > "${RUNNER_TEMP}/release_notes.md"
echo "Release notes extracted successfully"
cat "${RUNNER_TEMP}/release_notes.md"
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
if gh release view "$TAG_NAME" > /dev/null 2>&1; then
echo "::warning::Release $TAG_NAME already exists, skipping creation"
else
gh release create "$TAG_NAME" \
--title "$TAG_NAME" \
--notes-file "${RUNNER_TEMP}/release_notes.md"
fi