Skip to content

Commit 7e62abd

Browse files
jensensclaude
andcommitted
Add GitHub Actions workflows for CI, QA, tests, and release
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 57a2cb6 commit 7e62abd

File tree

4 files changed

+207
-0
lines changed

4 files changed

+207
-0
lines changed

.github/workflows/ci.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
name: CI
3+
4+
on:
5+
push:
6+
branches-ignore: [main]
7+
pull_request:
8+
9+
permissions:
10+
contents: read
11+
12+
concurrency:
13+
group: ci-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
qa:
18+
uses: "./.github/workflows/qa.yaml"
19+
20+
tests:
21+
uses: "./.github/workflows/tests.yaml"

.github/workflows/qa.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
name: QA
3+
4+
on:
5+
workflow_call:
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
lint:
12+
name: Ruff
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- uses: astral-sh/setup-uv@v6
18+
19+
- name: Run ruff check
20+
run: uvx ruff check .
21+
22+
- name: Run ruff format check
23+
run: uvx ruff format --check .

.github/workflows/release.yaml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
name: Build & upload PyPI package
3+
4+
on:
5+
push:
6+
branches: [main]
7+
release:
8+
types:
9+
- published
10+
workflow_dispatch:
11+
12+
concurrency:
13+
group: release-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
qa:
18+
uses: "./.github/workflows/qa.yaml"
19+
20+
tests:
21+
uses: "./.github/workflows/tests.yaml"
22+
23+
build-package:
24+
name: Build & verify package
25+
needs:
26+
- qa
27+
- tests
28+
runs-on: ubuntu-latest
29+
permissions:
30+
contents: read
31+
32+
steps:
33+
- uses: actions/checkout@v4
34+
with:
35+
fetch-depth: 0
36+
persist-credentials: false
37+
38+
- uses: hynek/build-and-inspect-python-package@v2
39+
40+
release-test-pypi:
41+
name: Publish in-dev package to test.pypi.org
42+
environment: release-test-pypi
43+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
44+
runs-on: ubuntu-latest
45+
needs:
46+
- build-package
47+
permissions:
48+
id-token: write
49+
50+
steps:
51+
- name: Download packages built by build-and-inspect-python-package
52+
uses: actions/download-artifact@v4
53+
with:
54+
name: Packages
55+
path: dist
56+
57+
- name: Upload package to Test PyPI
58+
uses: pypa/gh-action-pypi-publish@release/v1
59+
with:
60+
repository-url: https://test.pypi.org/legacy/
61+
62+
release-pypi:
63+
name: Publish released package to pypi.org
64+
environment: release-pypi
65+
if: github.event.action == 'published'
66+
runs-on: ubuntu-latest
67+
needs:
68+
- build-package
69+
permissions:
70+
id-token: write
71+
72+
steps:
73+
- name: Download packages built by build-and-inspect-python-package
74+
uses: actions/download-artifact@v4
75+
with:
76+
name: Packages
77+
path: dist
78+
79+
- name: Upload package to PyPI
80+
uses: pypa/gh-action-pypi-publish@release/v1

.github/workflows/tests.yaml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
name: Tests
3+
4+
on:
5+
workflow_call:
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
test:
12+
name: Python ${{ matrix.python-version }}
13+
runs-on: ubuntu-latest
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
python-version: ["3.12", "3.13", "3.14"]
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 0
23+
24+
- uses: astral-sh/setup-uv@v6
25+
with:
26+
enable-cache: true
27+
cache-dependency-glob: "pyproject.toml"
28+
29+
- name: Set up Python ${{ matrix.python-version }}
30+
run: uv python install ${{ matrix.python-version }}
31+
32+
- name: Install dependencies
33+
run: uv venv && uv pip install -e ".[test]"
34+
35+
- name: Run tests with coverage
36+
run: uv run pytest --cov --cov-report=
37+
38+
- name: Rename coverage data
39+
run: mv .coverage .coverage.${{ matrix.python-version }}
40+
41+
- name: Upload coverage data
42+
uses: actions/upload-artifact@v4
43+
with:
44+
name: coverage-data-${{ matrix.python-version }}
45+
path: .coverage.${{ matrix.python-version }}
46+
include-hidden-files: true
47+
if-no-files-found: ignore
48+
49+
coverage:
50+
name: Combine & check coverage
51+
if: always()
52+
needs: test
53+
runs-on: ubuntu-latest
54+
55+
steps:
56+
- uses: actions/checkout@v4
57+
58+
- uses: astral-sh/setup-uv@v6
59+
with:
60+
enable-cache: true
61+
cache-dependency-glob: "pyproject.toml"
62+
63+
- name: Install dependencies
64+
run: uv venv && uv pip install -e ".[test]"
65+
66+
- uses: actions/download-artifact@v4
67+
with:
68+
pattern: coverage-data-*
69+
merge-multiple: true
70+
71+
- name: Combine coverage & check threshold
72+
run: |
73+
uv run coverage combine
74+
uv run coverage html --skip-covered --skip-empty
75+
uv run coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
76+
uv run coverage report
77+
78+
- name: Upload HTML report if check failed
79+
uses: actions/upload-artifact@v4
80+
with:
81+
name: html-report
82+
path: htmlcov
83+
if: ${{ failure() }}

0 commit comments

Comments
 (0)