Skip to content

Commit 5f2f289

Browse files
correct behavior for publishing dev builds to test.pypi. add test dependency to main publish workflow so we are less likely to publish a broken build
1 parent 2da959e commit 5f2f289

3 files changed

Lines changed: 113 additions & 81 deletions

File tree

.github/workflows/publish-test.yml

Lines changed: 0 additions & 74 deletions
This file was deleted.

.github/workflows/publish.yml

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,67 @@
1-
name: publish.yml
1+
name: Publish (PyPI)
2+
3+
# Publishes any tag starting with 'v' (e.g. v1.0, v0.5.1a0) to PyPI via OIDC
4+
# trusted publishing. The publish job is gated on the full pytest matrix
5+
# passing on the tagged commit — we don't ship a release that fails CI.
26
on:
37
push:
48
tags:
5-
# publishes any tag starting with 'v' as in 'v1.0'
69
- v*
710

11+
permissions: {}
12+
813
jobs:
9-
run:
14+
# Re-run the full test matrix on the tagged commit. Yes, this is similar
15+
# to tests.yaml — but a release deserves an explicit, self-contained gate
16+
# rather than a `workflow_run` dependency on another workflow's run (which
17+
# would only work if tests.yaml was on the default branch at the time of
18+
# the tag, a footgun).
19+
tests:
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
strategy:
24+
fail-fast: true
25+
matrix:
26+
python-version: [ "3.12", "3.13", "3.14" ]
27+
name: pytest (Python ${{ matrix.python-version }})
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@v5
31+
32+
- name: Install uv
33+
uses: astral-sh/setup-uv@v6
34+
35+
- name: Install Python ${{ matrix.python-version }}
36+
run: uv python install ${{ matrix.python-version }}
37+
38+
- name: Install dependencies
39+
run: uv sync --all-extras --python ${{ matrix.python-version }}
40+
41+
- name: Run pytest
42+
run: |
43+
uv run --python ${{ matrix.python-version }} pytest -v -m "not network"
44+
45+
publish:
46+
needs: tests
1047
runs-on: ubuntu-latest
1148
environment:
1249
name: publish
1350
permissions:
14-
id-token: write
51+
id-token: write # OIDC trusted publishing
1552
contents: read
1653
steps:
1754
- name: Checkout
1855
uses: actions/checkout@v5
56+
1957
- name: Install uv
2058
uses: astral-sh/setup-uv@v6
59+
2160
- name: Install Python 3.13
2261
run: uv python install 3.13
62+
2363
- name: Build
2464
run: uv build
25-
# Need to add a test that verifies the builds
26-
- name: Publish
65+
66+
- name: Publish to PyPI
2767
run: uv publish

.github/workflows/tests.yaml

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
name: Tests
22
on:
33
push:
4+
# Tag pushes (v*) are handled by publish.yml, which runs the same matrix
5+
# before publishing — skip here to avoid running the suite twice.
6+
tags-ignore:
7+
- '**'
48
paths-ignore:
59
- 'docs/**'
610
- 'README.md'
@@ -61,4 +65,66 @@ jobs:
6165
name: coverage-${{ matrix.python-version }}
6266
path: coverage.xml
6367
if-no-files-found: warn
64-
retention-days: 7
68+
retention-days: 7
69+
70+
# Publish a `.devN` pre-release wheel to TestPyPI on every push to dev,
71+
# gated on the full pytest matrix passing. Lives in this workflow (rather
72+
# than a separate `workflow_run`-triggered file) so that the gate is a
73+
# plain `needs:` dependency — `workflow_run` only fires from workflows
74+
# that exist on the default branch, which is a maintenance footgun.
75+
#
76+
# One-time setup required at https://test.pypi.org/manage/account/publishing/
77+
# Owner: Botts-Innovative-Research
78+
# Repo: OSHConnect-Python
79+
# Workflow: tests.yaml
80+
# Environment: publish-test
81+
# And in this repo's Settings -> Environments, create env `publish-test`.
82+
publish-test:
83+
needs: pytest
84+
if: github.event_name == 'push' && github.ref == 'refs/heads/dev'
85+
runs-on: ubuntu-latest
86+
environment:
87+
name: publish-test
88+
url: https://test.pypi.org/project/oshconnect/
89+
permissions:
90+
id-token: write # OIDC trusted publishing
91+
contents: read
92+
steps:
93+
- name: Checkout
94+
uses: actions/checkout@v5
95+
96+
- name: Install uv
97+
uses: astral-sh/setup-uv@v6
98+
99+
- name: Install Python 3.13
100+
run: uv python install 3.13
101+
102+
# Append `.dev<run_number>` to the version in pyproject.toml so each
103+
# dev push gets a fresh PEP 440-compliant pre-release (e.g.
104+
# 0.5.1a0 -> 0.5.1a0.dev42). The change lives only on the runner.
105+
- name: Auto-bump version with .devN suffix
106+
run: |
107+
python - <<'PY'
108+
import os, pathlib, re
109+
run = os.environ['GITHUB_RUN_NUMBER']
110+
p = pathlib.Path('pyproject.toml')
111+
src = p.read_text()
112+
new = re.sub(
113+
r'^(version\s*=\s*")([^"]+)(")',
114+
lambda m: f'{m.group(1)}{m.group(2)}.dev{run}{m.group(3)}',
115+
src, count=1, flags=re.M,
116+
)
117+
if new == src:
118+
raise SystemExit('No `version = "..."` line found in pyproject.toml')
119+
p.write_text(new)
120+
for line in new.splitlines():
121+
if line.startswith('version'):
122+
print(f'Bumped {line}')
123+
break
124+
PY
125+
126+
- name: Build
127+
run: uv build
128+
129+
- name: Publish to TestPyPI
130+
run: uv publish --publish-url https://test.pypi.org/legacy/

0 commit comments

Comments
 (0)