Skip to content

Commit e652526

Browse files
paddymulclaude
andcommitted
ci: publish dev wheel to TestPyPI on every PR
Adds a PublishTestPyPI job that builds a .dev{run_id} versioned wheel and publishes it to TestPyPI via trusted publishing (OIDC). Posts a PR comment with pip/uv install commands, updated in-place on new pushes. Requires one-time manual setup: create `testpypi` environment in GitHub repo settings and register the trusted publisher on TestPyPI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bb5d825 commit e652526

1 file changed

Lines changed: 76 additions & 0 deletions

File tree

.github/workflows/checks.yml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ permissions:
1010
contents: read
1111
pages: write
1212
id-token: write
13+
pull-requests: write
1314

1415
concurrency:
1516
group: ${{ github.workflow }}-${{ github.ref }}
@@ -81,6 +82,13 @@ jobs:
8182
run: pnpm install --frozen-lockfile
8283
- name: Install the project
8384
run: uv sync --all-extras --dev
85+
- name: Patch version for TestPyPI
86+
if: github.event_name == 'pull_request'
87+
run: |
88+
BASE=$(grep -Po '^version = "\K[^"]+' pyproject.toml)
89+
DEV="${BASE}.dev${{ github.run_id }}"
90+
sed -i "s/^version = \".*\"/version = \"${DEV}\"/" pyproject.toml
91+
echo "Published version: ${DEV}"
8492
- name: Build JS extension + Python wheel
8593
run: ./scripts/full_build.sh
8694
- name: Upload build artifacts
@@ -93,6 +101,74 @@ jobs:
93101
./packages/buckaroo-js-core/dist/
94102
./packages/buckaroo-widget/dist/
95103
104+
PublishTestPyPI:
105+
name: Publish to TestPyPI
106+
if: >-
107+
github.event_name == 'pull_request' &&
108+
github.event.pull_request.head.repo.full_name == github.repository
109+
needs: [BuildWheel]
110+
runs-on: depot-ubuntu-latest
111+
timeout-minutes: 5
112+
environment: testpypi
113+
permissions:
114+
id-token: write
115+
pull-requests: write
116+
steps:
117+
- name: Download build artifacts
118+
uses: actions/download-artifact@v4
119+
with:
120+
name: buckaroo-build
121+
path: artifacts
122+
- name: Publish to TestPyPI
123+
uses: pypa/gh-action-pypi-publish@release/v1
124+
with:
125+
repository-url: https://test.pypi.org/legacy/
126+
packages-dir: artifacts/dist/
127+
- name: Comment on PR with install command
128+
uses: actions/github-script@v7
129+
with:
130+
script: |
131+
const fs = require('fs');
132+
const distFiles = fs.readdirSync('artifacts/dist');
133+
const wheel = distFiles.find(f => f.endsWith('.whl'));
134+
const version = wheel.match(/buckaroo-(.+?)-/)[1];
135+
const body = [
136+
'## :package: TestPyPI package published',
137+
'',
138+
'```bash',
139+
`pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo==${version}`,
140+
'```',
141+
'',
142+
'or with uv:',
143+
'',
144+
'```bash',
145+
`uv pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo==${version}`,
146+
'```',
147+
].join('\n');
148+
149+
const { data: comments } = await github.rest.issues.listComments({
150+
owner: context.repo.owner,
151+
repo: context.repo.repo,
152+
issue_number: context.issue.number,
153+
});
154+
const marker = '## :package: TestPyPI package published';
155+
const existing = comments.find(c => c.body.startsWith(marker));
156+
if (existing) {
157+
await github.rest.issues.updateComment({
158+
owner: context.repo.owner,
159+
repo: context.repo.repo,
160+
comment_id: existing.id,
161+
body,
162+
});
163+
} else {
164+
await github.rest.issues.createComment({
165+
owner: context.repo.owner,
166+
repo: context.repo.repo,
167+
issue_number: context.issue.number,
168+
body,
169+
});
170+
}
171+
96172
# ---------------------------------------------------------------------------
97173
# Source-level tests — operate on the codebase, no wheel needed
98174
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)