Skip to content

Commit b8eb704

Browse files
ci(release): add release-please CD workflow with PyPI trusted publisher
1 parent c07eb08 commit b8eb704

4 files changed

Lines changed: 129 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
12+
jobs:
13+
release-please:
14+
name: Open / update release PR
15+
runs-on: ubuntu-latest
16+
outputs:
17+
release_created: ${{ steps.release.outputs.release_created }}
18+
tag_name: ${{ steps.release.outputs.tag_name }}
19+
steps:
20+
- uses: googleapis/release-please-action@v4
21+
id: release
22+
with:
23+
token: ${{ secrets.GITHUB_TOKEN }}
24+
config-file: release-please-config.json
25+
manifest-file: .release-please-manifest.json
26+
27+
publish:
28+
name: Build, smoke test & publish to PyPI
29+
needs: release-please
30+
if: needs.release-please.outputs.release_created == 'true'
31+
runs-on: ubuntu-latest
32+
environment: pypi
33+
34+
permissions:
35+
contents: read
36+
id-token: write
37+
38+
steps:
39+
- uses: actions/checkout@v6
40+
with:
41+
ref: ${{ needs.release-please.outputs.tag_name }}
42+
43+
- name: Install uv
44+
uses: astral-sh/setup-uv@v8.0.0
45+
with:
46+
enable-cache: true
47+
48+
- name: Set up Python
49+
uses: actions/setup-python@v6
50+
with:
51+
python-version-file: .python-version
52+
53+
- name: Build distributions
54+
run: uv build
55+
56+
- name: Smoke test (wheel)
57+
run: uv run --isolated --no-project --with "dist/*.whl" tests/smoke_test.py
58+
59+
- name: Smoke test (sdist)
60+
run: uv run --isolated --no-project --with "dist/*.tar.gz" tests/smoke_test.py
61+
62+
- name: Publish to PyPI
63+
run: uv publish

.release-please-manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
".": "0.1.0"
3+
}

release-please-config.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
3+
"release-type": "python",
4+
"packages": {
5+
".": {}
6+
}
7+
}

tests/smoke_test.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""Smoke test — run against the built wheel and sdist before publishing.
2+
3+
Checks that the package installs cleanly, all public names are importable,
4+
and the CLI entry point is reachable. Intentionally has no external
5+
dependencies beyond the package itself.
6+
"""
7+
8+
import importlib
9+
import subprocess
10+
11+
12+
def test_public_api() -> None:
13+
import evalwire
14+
15+
required = [
16+
"DatasetUploader",
17+
"ExperimentRunner",
18+
"make_membership_evaluator",
19+
"make_top_k_evaluator",
20+
"setup_observability",
21+
]
22+
missing = [name for name in required if not hasattr(evalwire, name)]
23+
assert not missing, f"Missing public names: {missing}"
24+
25+
26+
def test_submodules_importable() -> None:
27+
for module in [
28+
"evalwire.evaluators",
29+
"evalwire.uploader",
30+
"evalwire.runner",
31+
"evalwire.observability",
32+
"evalwire.config",
33+
"evalwire.cli",
34+
]:
35+
importlib.import_module(module)
36+
37+
38+
def test_cli_entry_point() -> None:
39+
import shutil
40+
41+
evalwire_bin = shutil.which("evalwire")
42+
assert evalwire_bin is not None, "evalwire CLI entry point not found on PATH"
43+
result = subprocess.run(
44+
[evalwire_bin, "--help"],
45+
capture_output=True,
46+
text=True,
47+
)
48+
assert result.returncode == 0, f"CLI --help failed:\n{result.stderr}"
49+
assert "evalwire" in result.stdout.lower()
50+
51+
52+
if __name__ == "__main__":
53+
test_public_api()
54+
test_submodules_importable()
55+
test_cli_entry_point()
56+
print("Smoke test passed.")

0 commit comments

Comments
 (0)