Skip to content

ci: publish an installable wheel from every push and PR - #90

Open
pofallon wants to merge 1 commit into
mainfrom
ci/publish-dev-wheels-as-artifacts
Open

ci: publish an installable wheel from every push and PR#90
pofallon wants to merge 1 commit into
mainfrom
ci/publish-dev-wheels-as-artifacts

Conversation

@pofallon

Copy link
Copy Markdown
Contributor

Option B from the earlier discussion: CI-built artifacts you can install without cutting a release.

Why

Testing a branch inside another project currently means either a git dependency — which builds from source and so validates neither the sdist exclude list nor the wheel's file selection — or cutting a release. CI built nothing, so there was no third option. The repo has zero artifacts to date.

What

A build job producing an installable sdist + wheel per commit, retained 14 days. The run summary carries the exact commands for that specific build:

Installable build a1b2c3d

Built from feat/zai-anthropic at a1b2c3d4e5f6. No release, no tag — expires in 14 days.

gh run download --repo get2knowio/airframe 1234567890 \
  --name dist-a1b2c3d --dir /tmp/airframe-build

uv pip install /tmp/airframe-build/airframe_agents-0.9.1-py3-none-any.whl

(That's the real rendered output — I executed the summary step locally with the GitHub expressions substituted, rather than trusting the heredoc escaping by eye.)

Decisions worth reviewing

  • No needs: test. The point is to hand you something to install from a branch, and a branch you're still debugging is exactly when you want it. The run's own status already reports whether tests passed. Easy to change if you'd rather gate it.
  • PR head SHA, not github.sha — on pull_request events the latter is the ephemeral merge commit, which nobody can find in their branch history.
  • twine check + check-wheel-contents on every PR. This is arguably the bigger win: packaging regressions currently surface only at release time, when the tag is already cut. Costs ~30s.
  • Install-by-path in the printed commands, not --find-links — for the reason found while building ci: verify the built artifact before publishing it #89: --find-links only adds to the index, so a published version higher than the local build wins the resolution and you silently test the wrong artifact.
  • uv build --no-sources, matching ci: verify the built artifact before publishing it #89.

Action versions

Uses upload-artifact@v7 — v4 is several majors stale. I checked the v5/v6/v7 release notes: the breaking changes are Node runtime bumps, and name / path / retention-days / if-no-files-found are all unchanged. I'll bump #89's v4 pins separately; worth knowing that download-artifact@v8 now enforces artifact hash checks by default rather than warning, which covers most of the integrity concern I raised on that PR.

What I ruled out

GitHub Packages hosts npm, RubyGems, Maven, NuGet and Docker — Python is still unsupported, with an open request from May 2026. No pypi.pkg.github.com.

A PEP 503 index on GitHub Pages would give a credential-free URL other projects' CI could resolve by name, which this can't (gh run download needs a token even on a public repo). Worth doing if that need appears, but it requires per-build dev versions like 0.10.0.dev5+a1b2c3d to avoid filename collisions, so it's a larger change than this one.

Overlap with #89

Both build and verify. Different triggers and purposes: this one distributes dev builds on every commit, #89 gates the release. Once both land, extracting a reusable workflow would remove the duplication — happy to do that as a follow-up rather than couple the two PRs now.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UBTr6Q6kTGUMQiwwBHcdMj

Testing a branch inside another project currently means either a git
dependency — which builds from source and so validates neither the sdist
exclude list nor the wheel's file selection — or cutting a release. CI
built nothing, so there was no third option (the repo has zero artifacts
to date).

Adds a `build` job producing an installable sdist + wheel per commit,
retained 14 days. The run summary carries the exact `gh run download`
and install commands for that build, so the path from a green CI run to
"installed in my other project" is a copy-paste.

Notes on the specifics:

- No `needs: test`. The point is to hand you something to install from a
  branch, and a branch you are still debugging is exactly when you want
  it. The run's own status already reports whether tests passed.
- Uses the PR head SHA, not `github.sha`, which on pull_request events is
  the ephemeral merge commit nobody can find in their branch history.
- Runs `twine check` and `check-wheel-contents` on every PR. This is the
  real win beyond distribution: packaging regressions currently surface
  only at release time, when the tag is already cut.
- Install-by-path in the printed commands, not `--find-links`, for the
  reason found while building the release gate: `--find-links` only adds
  to the index, so a published version higher than the local build wins
  the resolution and you silently test the wrong artifact.
- `uv build --no-sources` matches the release workflow — build the way
  every other tool would, with `tool.uv.sources` disabled.

Uses upload-artifact v7 (current major; v4 is several majors stale).

GitHub Packages was the obvious alternative and does not work: it hosts
npm, RubyGems, Maven, NuGet and Docker, but Python remains unsupported.
The other option is a PEP 503 index on GitHub Pages, which would give a
credential-free URL other projects' CI could resolve by name — worth
doing if that need appears, but it requires per-build dev versions
(0.X.Y.devN+sha) to avoid filename collisions, so it is a larger change
than this.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UBTr6Q6kTGUMQiwwBHcdMj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant