Skip to content

Commit 7e41e45

Browse files
committed
ci: add CI and release workflows (trusted publishing)
1 parent d023599 commit 7e41e45

2 files changed

Lines changed: 162 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main, master ]
6+
pull_request:
7+
branches: [ main, master ]
8+
9+
# prevent overlapping runs on the same ref
10+
concurrency:
11+
group: ci-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
jobs:
15+
lint-typecheck:
16+
name: Lint & Type Check
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- name: Set up Python
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: "3.12"
25+
cache: pip
26+
27+
- name: Install dev tools
28+
run: |
29+
python -m pip install -U pip
30+
python -m pip install -e ".[dev]" # installs black, ruff, mypy, pytest, etc.
31+
32+
- name: Ruff (lint)
33+
run: ruff check .
34+
35+
- name: Black (format check)
36+
run: black --check .
37+
38+
- name: Mypy (type check)
39+
run: mypy spax
40+
41+
tests:
42+
name: Tests (py${{ matrix.python-version }})
43+
runs-on: ubuntu-latest
44+
strategy:
45+
fail-fast: false
46+
matrix:
47+
python-version: ["3.11", "3.12", "3.13", "3.14"]
48+
steps:
49+
- uses: actions/checkout@v4
50+
51+
- name: Set up Python
52+
uses: actions/setup-python@v5
53+
with:
54+
python-version: ${{ matrix.python-version }}
55+
cache: pip
56+
57+
- name: Install package (with test extras)
58+
run: |
59+
python -m pip install -U pip
60+
# install project in editable mode + dev deps + YAML/TOML extras used in serialization tests
61+
python -m pip install -e ".[dev,yaml,toml]"
62+
# (intentionally NOT installing optuna; TrialSampler tests work without it)
63+
64+
- name: Pytest
65+
run: |
66+
pytest -q --cov=spax --cov-report=xml --cov-report=term-missing
67+
68+
- name: Upload coverage.xml artifact
69+
uses: actions/upload-artifact@v4
70+
if: always()
71+
with:
72+
name: coverage-${{ matrix.python-version }}
73+
path: coverage.xml
74+
75+
build:
76+
name: Build dist & twine check
77+
runs-on: ubuntu-latest
78+
needs: [lint-typecheck, tests]
79+
steps:
80+
- uses: actions/checkout@v4
81+
82+
- name: Set up Python
83+
uses: actions/setup-python@v5
84+
with:
85+
python-version: "3.12"
86+
cache: pip
87+
88+
- name: Build
89+
run: |
90+
python -m pip install -U pip build twine
91+
python -m build
92+
twine check dist/*
93+
94+
- name: Upload dist artifacts
95+
uses: actions/upload-artifact@v4
96+
with:
97+
name: spax-dist
98+
path: dist/*

.github/workflows/release.yml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
workflow_dispatch:
8+
9+
concurrency:
10+
group: release-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
build-and-publish:
15+
name: Build & Publish to PyPI
16+
runs-on: ubuntu-latest
17+
permissions:
18+
id-token: write # required for OIDC / Trusted Publishing
19+
contents: read
20+
21+
environment:
22+
name: pypi
23+
url: https://pypi.org/project/spax/
24+
25+
steps:
26+
- uses: actions/checkout@v4
27+
28+
- name: Set up Python
29+
uses: actions/setup-python@v5
30+
with:
31+
python-version: "3.12"
32+
33+
- name: Verify tag matches project version
34+
run: |
35+
python - <<'PY'
36+
import tomllib, pathlib, os, sys
37+
tag = os.environ["GITHUB_REF_NAME"]
38+
if not tag.startswith("v"):
39+
sys.exit(f"Tag must start with 'v', got {tag}")
40+
expected = tag[1:]
41+
data = tomllib.loads(pathlib.Path("pyproject.toml").read_text())
42+
proj_ver = data["project"]["version"]
43+
if proj_ver != expected:
44+
sys.exit(f"Version mismatch: pyproject {proj_ver} vs tag {expected}")
45+
print(f"Version OK: {proj_ver}")
46+
PY
47+
48+
- name: Build dists
49+
run: |
50+
python -m pip install -U pip build twine
51+
python -m build
52+
twine check dist/*
53+
54+
- name: Publish to PyPI (Trusted Publishing)
55+
uses: pypa/gh-action-pypi-publish@v1.10.1
56+
with:
57+
verbose: true
58+
print-hash: true
59+
60+
- name: Upload dist artifacts
61+
uses: actions/upload-artifact@v4
62+
with:
63+
name: spax-${{ github.ref_name }}-dist
64+
path: dist/*

0 commit comments

Comments
 (0)