Skip to content

Commit 68af736

Browse files
kasperjungeclaude
andcommitted
Restore release workflows
Reinstate docs and publish workflows required for tag releases and docs deployment. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a2646f0 commit 68af736

2 files changed

Lines changed: 227 additions & 0 deletions

File tree

.github/workflows/docs.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Build and Deploy Docs
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- 'docs/**'
9+
- '.github/workflows/docs.yml'
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
pages: write
15+
id-token: write
16+
17+
concurrency:
18+
group: pages
19+
cancel-in-progress: false
20+
21+
jobs:
22+
build:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- name: Set up Python
28+
uses: actions/setup-python@v5
29+
with:
30+
python-version: '3.12'
31+
32+
- name: Install dependencies
33+
run: pip install mkdocs-material
34+
35+
- name: Build docs
36+
working-directory: docs
37+
run: mkdocs build
38+
39+
- name: Prepare deploy directory
40+
run: |
41+
mkdir -p deploy/site
42+
cp docs/index.html deploy/
43+
cp -r docs/site/* deploy/site/
44+
45+
- name: Upload artifact
46+
uses: actions/upload-pages-artifact@v3
47+
with:
48+
path: ./deploy
49+
50+
deploy:
51+
environment:
52+
name: github-pages
53+
url: ${{ steps.deployment.outputs.page_url }}
54+
runs-on: ubuntu-latest
55+
needs: build
56+
steps:
57+
- name: Deploy to GitHub Pages
58+
id: deployment
59+
uses: actions/deploy-pages@v4

.github/workflows/publish.yml

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
workflow_dispatch:
8+
inputs:
9+
dry_run:
10+
description: 'Dry run (build but do not publish)'
11+
required: false
12+
default: false
13+
type: boolean
14+
15+
permissions:
16+
contents: read
17+
id-token: write # Required for trusted publishing
18+
19+
jobs:
20+
quality:
21+
name: Quality Checks
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
with:
26+
ref: ${{ github.ref_name }}
27+
28+
- name: Install uv
29+
uses: astral-sh/setup-uv@v5
30+
31+
- name: Set up Python
32+
run: uv python install 3.12
33+
34+
- name: Install dependencies
35+
run: uv sync --dev
36+
37+
- name: Run ruff check
38+
run: uv run ruff check .
39+
40+
- name: Run ruff format check
41+
run: uv run ruff format --check .
42+
43+
- name: Run tests
44+
run: uv run pytest -m "not e2e and not network and not slow"
45+
46+
build:
47+
name: Build Package
48+
needs: quality
49+
runs-on: ubuntu-latest
50+
steps:
51+
- uses: actions/checkout@v4
52+
with:
53+
ref: ${{ github.ref_name }}
54+
55+
- name: Install uv
56+
uses: astral-sh/setup-uv@v5
57+
58+
- name: Set up Python
59+
run: uv python install 3.12
60+
61+
- name: Build package
62+
run: uv build
63+
64+
- name: Verify package
65+
run: |
66+
uv venv .venv
67+
uv pip install dist/*.whl
68+
.venv/bin/python -c "import agr; print(f'Built version: {agr.__version__}')"
69+
70+
- name: Upload artifacts
71+
uses: actions/upload-artifact@v4
72+
with:
73+
name: dist
74+
path: dist/
75+
76+
publish:
77+
name: Publish to PyPI
78+
needs: build
79+
runs-on: ubuntu-latest
80+
if: github.event_name == 'push' || !inputs.dry_run
81+
environment:
82+
name: pypi
83+
url: https://pypi.org/project/agr/
84+
steps:
85+
- name: Download artifacts
86+
uses: actions/download-artifact@v4
87+
with:
88+
name: dist
89+
path: dist/
90+
91+
- name: Publish to PyPI
92+
uses: pypa/gh-action-pypi-publish@release/v1
93+
# Uses trusted publishing (OIDC) - no API token needed
94+
# Configure at: https://pypi.org/manage/project/agr/settings/publishing/
95+
96+
release:
97+
name: Create GitHub Release
98+
needs: publish
99+
runs-on: ubuntu-latest
100+
if: github.event_name == 'push' || !inputs.dry_run
101+
permissions:
102+
contents: write # Only this job needs write access
103+
env:
104+
TAG_NAME: ${{ github.ref_name }}
105+
steps:
106+
- uses: actions/checkout@v4
107+
with:
108+
ref: ${{ github.ref_name }}
109+
110+
- name: Validate tag format
111+
run: |
112+
if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([ab][0-9]+)?$ ]]; then
113+
echo "Error: Invalid tag format '$TAG_NAME'"
114+
echo "Expected format: vX.Y.Z or vX.Y.Za1/vX.Y.Zb1 (e.g., v0.6.5, v0.7.1b1)"
115+
exit 1
116+
fi
117+
118+
- name: Extract release notes from CHANGELOG
119+
run: |
120+
if [ ! -f CHANGELOG.md ]; then
121+
echo "Error: CHANGELOG.md not found"
122+
exit 1
123+
fi
124+
125+
VERSION_NUM="${TAG_NAME#v}" # Remove 'v' prefix
126+
127+
# Extract section for this version from CHANGELOG.md
128+
# Matches from [X.Y.Z] until the next [X.Y.Z] or end of file
129+
NOTES=$(awk -v ver="$VERSION_NUM" '
130+
/^## \[/ {
131+
if (found) exit
132+
if ($0 ~ "\\[" ver "\\]") found=1
133+
next
134+
}
135+
found { print }
136+
' CHANGELOG.md)
137+
138+
if [ -z "$NOTES" ]; then
139+
echo "Error: Version $VERSION_NUM not found in CHANGELOG.md"
140+
echo "Make sure CHANGELOG.md has a section like: ## [$VERSION_NUM] - YYYY-MM-DD"
141+
exit 1
142+
fi
143+
144+
# Write to file for gh release
145+
{
146+
echo "## What's New in $TAG_NAME"
147+
echo ""
148+
echo "$NOTES"
149+
echo ""
150+
echo "---"
151+
echo ""
152+
echo "**Full changelog**: ${{ github.server_url }}/${{ github.repository }}/blob/main/CHANGELOG.md"
153+
} > "${RUNNER_TEMP}/release_notes.md"
154+
155+
echo "Release notes extracted successfully"
156+
cat "${RUNNER_TEMP}/release_notes.md"
157+
158+
- name: Create GitHub Release
159+
env:
160+
GH_TOKEN: ${{ github.token }}
161+
run: |
162+
if gh release view "$TAG_NAME" > /dev/null 2>&1; then
163+
echo "::warning::Release $TAG_NAME already exists, skipping creation"
164+
else
165+
gh release create "$TAG_NAME" \
166+
--title "$TAG_NAME" \
167+
--notes-file "${RUNNER_TEMP}/release_notes.md"
168+
fi

0 commit comments

Comments
 (0)