Skip to content

ci: publish agent-learning-kit to PyPI via Trusted Publishing - #93

Merged
khushalsonawat merged 5 commits into
mainfrom
chore/publish-pypi
Sep 12, 2026
Merged

ci: publish agent-learning-kit to PyPI via Trusted Publishing#93
khushalsonawat merged 5 commits into
mainfrom
chore/publish-pypi

Conversation

@khushalsonawat

@khushalsonawat khushalsonawat commented Sep 12, 2026

Copy link
Copy Markdown
Member

What

Publishes agent-learning-kit to PyPI via Trusted Publishing (OIDC) — no long-lived token — on merge to main, and updates the README Install section (which becomes the PyPI project page).

.github/workflows/publish-pypi.yml

  • Trigger: every push to main (i.e. every merged PR). No workflow_dispatch, no tag trigger.
  • check job: reads the pyproject version (uv version --short) and looks it up on PyPI. 404 → release; 200 → skip cleanly (ordinary merges stay green and never page the reviewer); anything else → fail rather than guess. Refuses any ref other than main.
  • build job (only when releasing, holds no secrets): uv build, then a smoke install of the wheel that imports fi.simulate.hosted.child_entrypoint and fi.alk.harness and runs alk --help. persist-credentials: false.
  • publish job: runs under the pypi environment → pauses for a required reviewer (self-review prevented) → publishes with id-token: write only; downloads + publishes, runs no repo code. attestations: true (PEP 740), skip-existing: true.
  • All actions SHA-pinned; setup-uv held to 0.12.x; timeouts; concurrency serializes publishes and never cancels one mid-flight.

pyproject.toml

[build-system] requires = ["hatchling>=1.27,<2"] — the build backend is the one artifact input uv.lock doesn't cover.

README.md

Install leads with pip install agent-learning-kit; source install kept for contributors; all relative links/images made absolute (they'd 404 on pypi.org).

How to release

Bump version in pyproject.toml (+ uv lock) → merge to main → approve the pypi deployment when it pauses. Each version publishes exactly once (PyPI is immutable); a mistake needs a new version.

⚠️ Merging this PR is the first release

0.1.0 is not on PyPI, so the merge itself triggers check → build → publish (waiting on reviewer). The reviewer's approval click is the 0.1.0 publish. The pending Trusted Publisher is registered (future-agi / agent-learning-kit / publish-pypi.yml / env pypi); it does not reserve the name, so approve promptly.

Why

The hosted simulation-runner image bundles this SDK and installs it from PyPI (Dockerfile.simulation-runner); nothing has published it until now, which left the sim-runner release pipeline inert. Publishing (immutable) was chosen over shipping hand-built wheels (mutable, unverifiable).

khushalsonawat and others added 3 commits September 12, 2026 12:14
Adds publish-pypi.yml: on an `sdk-vX.Y.Z` tag, build with `uv build`,
smoke-import the wheel (fi.simulate.hosted.child_entrypoint, fi.alk.harness),
then publish through OIDC Trusted Publishing under the `pypi` environment —
no long-lived PyPI token. A guard refuses any tag whose version does not
equal the pyproject version, so a tag can never publish the wrong release.
The publish action is SHA-pinned (release/v1 is a moving branch).

README: the Install section now leads with `pip install agent-learning-kit`
(it becomes the PyPI project page); source install is kept for contributors.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- drop workflow_dispatch: it bypassed the tag guard and let any
  push-capable account publish an arbitrary ref
- guard is now unconditional and ref-aware (refuses non-sdk-v* refs)
- SHA-pin every action to its current release; download-artifact ran
  unpinned inside the id-token job
- checkout persist-credentials:false; explicit attestations:true
- timeout-minutes + per-tag concurrency
- bound the build backend: hatchling>=1.25,<2

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- header now documents the account-level PENDING publisher flow (the
  project does not exist on PyPI yet), the org-account ownership rule,
  and that a pending publisher does not reserve the name
- skip-existing: a re-run after a partial upload must not 400
- smoke venv pinned to Python 3.12 (matches sdk-smoke.yml); also
  exercises the `alk` console script; setup-uv pinned to 0.12.x
- README: all 29 relative links/images made absolute — README.md is the
  PyPI long description and relative paths 404 on pypi.org
- hatchling bound raised to >=1.27,<2

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…dy on PyPI

Replaces the tag trigger with `push: branches: [main]`. A `check` job looks
the pyproject version up on PyPI: 404 → build + publish (reviewer-gated),
200 → skip cleanly so ordinary merges stay green and never page the
reviewer, anything else → fail rather than guess. Refuses any ref other
than main. No workflow_dispatch, no tag trigger; concurrency serializes
publishes and never cancels one mid-flight.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- publish job verifies dist/ is exactly the approved version's wheel+sdist
- check uses the project-level PyPI index (purged on release), treats a
  partial upload as unpublished, retries transient errors
- re-check after the reviewer gate so a late approval is a no-op
- run summary shows version + commit for approvers
- setup-uv pinned exact; comments reduced to the operator essentials

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@khushalsonawat
khushalsonawat merged commit 458a8ee into main Sep 12, 2026
8 checks passed
@khushalsonawat
khushalsonawat deleted the chore/publish-pypi branch September 12, 2026 07:36
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.

5 participants