Skip to content

Commit ffd20ae

Browse files
committed
🚀 Add GitHub Actions workflows and release scripts
1 parent df14dcd commit ffd20ae

File tree

4 files changed

+580
-0
lines changed

4 files changed

+580
-0
lines changed

.github/workflows/pypi-publish.yml

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
name: Publish Python Package
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
strategy:
12+
matrix:
13+
python-version: ['3.10', '3.11', '3.12', '3.13']
14+
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Install uv
19+
uses: astral-sh/setup-uv@v2
20+
21+
- name: Set up Python ${{ matrix.python-version }}
22+
run: uv python install ${{ matrix.python-version }}
23+
24+
- name: Install dependencies
25+
run: uv sync --all-extras
26+
27+
- name: Run tests
28+
run: uv run pytest --cov=src/structured_output_cookbook --cov-report=xml
29+
30+
- name: Upload coverage
31+
uses: codecov/codecov-action@v3
32+
with:
33+
file: ./coverage.xml
34+
fail_ci_if_error: false
35+
36+
build:
37+
needs: test
38+
runs-on: ubuntu-latest
39+
40+
steps:
41+
- uses: actions/checkout@v4
42+
43+
- name: Install uv
44+
uses: astral-sh/setup-uv@v2
45+
46+
- name: Set up Python
47+
run: uv python install 3.11
48+
49+
- name: Build package
50+
run: uv build
51+
52+
- name: Check package
53+
run: uvx twine check dist/*
54+
55+
- name: Upload artifacts
56+
uses: actions/upload-artifact@v4
57+
with:
58+
name: python-package-distributions
59+
path: dist/
60+
61+
publish-to-pypi:
62+
name: Publish to PyPI
63+
needs: build
64+
runs-on: ubuntu-latest
65+
environment:
66+
name: pypi
67+
url: https://pypi.org/p/structured-output-cookbook
68+
permissions:
69+
id-token: write # IMPORTANT: mandatory for trusted publishing
70+
71+
steps:
72+
- name: Download distributions
73+
uses: actions/download-artifact@v4
74+
with:
75+
name: python-package-distributions
76+
path: dist/
77+
78+
- name: Publish to PyPI
79+
uses: pypa/gh-action-pypi-publish@release/v1
80+
81+
publish-to-testpypi:
82+
name: Publish to TestPyPI
83+
needs: build
84+
runs-on: ubuntu-latest
85+
if: github.event_name == 'workflow_dispatch'
86+
environment:
87+
name: testpypi
88+
url: https://test.pypi.org/p/structured-output-cookbook
89+
permissions:
90+
id-token: write
91+
92+
steps:
93+
- name: Download distributions
94+
uses: actions/download-artifact@v4
95+
with:
96+
name: python-package-distributions
97+
path: dist/
98+
99+
- name: Publish to TestPyPI
100+
uses: pypa/gh-action-pypi-publish@release/v1
101+
with:
102+
repository-url: https://test.pypi.org/legacy/

.github/workflows/release.yml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
name: Release to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
workflow_dispatch:
8+
inputs:
9+
version:
10+
description: 'Version to release (e.g., 0.1.0)'
11+
required: true
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
strategy:
17+
matrix:
18+
python-version: ['3.10', '3.11', '3.12', '3.13']
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- name: Install uv
24+
uses: astral-sh/setup-uv@v2
25+
with:
26+
version: "latest"
27+
28+
- name: Set up Python ${{ matrix.python-version }}
29+
run: uv python install ${{ matrix.python-version }}
30+
31+
- name: Install dependencies
32+
run: |
33+
uv sync --all-extras
34+
35+
- name: Run tests
36+
run: |
37+
uv run pytest tests/ -v --cov=src/structured_output_cookbook --cov-report=xml
38+
39+
- name: Run linting
40+
run: |
41+
uv run black --check src/ tests/
42+
uv run ruff check src/ tests/
43+
44+
build:
45+
needs: test
46+
runs-on: ubuntu-latest
47+
48+
steps:
49+
- uses: actions/checkout@v4
50+
with:
51+
fetch-depth: 0
52+
53+
- name: Install uv
54+
uses: astral-sh/setup-uv@v2
55+
with:
56+
version: "latest"
57+
58+
- name: Set up Python
59+
run: uv python install 3.11
60+
61+
- name: Install build dependencies
62+
run: |
63+
uv tool install build
64+
uv tool install twine
65+
66+
- name: Build package
67+
run: |
68+
uvx build
69+
70+
- name: Check package
71+
run: |
72+
uvx twine check dist/*
73+
74+
- name: Upload build artifacts
75+
uses: actions/upload-artifact@v4
76+
with:
77+
name: dist
78+
path: dist/
79+
80+
publish:
81+
needs: build
82+
runs-on: ubuntu-latest
83+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
84+
environment: pypi
85+
permissions:
86+
id-token: write # For trusted publishing
87+
88+
steps:
89+
- name: Download build artifacts
90+
uses: actions/download-artifact@v4
91+
with:
92+
name: dist
93+
path: dist/
94+
95+
- name: Publish to PyPI
96+
uses: pypa/gh-action-pypi-publish@release/v1
97+
with:
98+
skip-existing: true
99+
100+
create-release:
101+
needs: publish
102+
runs-on: ubuntu-latest
103+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
104+
permissions:
105+
contents: write
106+
107+
steps:
108+
- uses: actions/checkout@v4
109+
with:
110+
fetch-depth: 0
111+
112+
- name: Generate release notes
113+
id: release_notes
114+
run: |
115+
# Extract version from tag
116+
VERSION=${GITHUB_REF#refs/tags/v}
117+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
118+
119+
# Extract changelog section for this version
120+
if grep -q "## \[${VERSION}\]" CHANGELOG.md; then
121+
sed -n "/## \[${VERSION}\]/,/## \[/p" CHANGELOG.md | sed '$d' > release_notes.md
122+
else
123+
echo "Release ${VERSION}" > release_notes.md
124+
echo "" >> release_notes.md
125+
echo "See [CHANGELOG.md](CHANGELOG.md) for details." >> release_notes.md
126+
fi
127+
128+
- name: Create GitHub Release
129+
uses: actions/create-release@v1
130+
env:
131+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
132+
with:
133+
tag_name: ${{ github.ref }}
134+
release_name: Release v${{ steps.release_notes.outputs.version }}
135+
body_path: release_notes.md
136+
draft: false
137+
prerelease: false

0 commit comments

Comments
 (0)