Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
".": "0.6.2",
"fleet": "0.1.3"
"fleet": "0.1.3",
"sdk/python": "0.1.0"
}
8 changes: 7 additions & 1 deletion release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
}
],
"changelog-path": "CHANGELOG.md",
"exclude-paths": ["fleet"]
"exclude-paths": ["fleet", "sdk/python"]
},
"fleet": {
"component": "fleet-agent",
Expand All @@ -39,6 +39,12 @@
}
],
"changelog-path": "CHANGELOG.md"
},
"sdk/python": {
"release-type": "python",
"component": "sdk-python",
"include-component-in-tag": true,
"changelog-path": "CHANGELOG.md"
Comment on lines +43 to +47

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Python release tags go unpublished

When a maintainer merges the first generated sdk/python release PR, release-please creates the sdk-python-vX.Y.Z tag, but no checked-in workflow handles that tag or publishes the package, causing the GitHub release to complete without a corresponding PyPI release.

Comment on lines +43 to +47

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the publish workflow before enabling SDK releases

When this configuration reaches master, release-please can create and merge an sdk-python release PR and push its tag, but the reviewed tree contains no .github/workflows/release-sdk-python.yml (a repo-wide search found only the new README references). GitHub will therefore run no PyPI publisher for that tag, and adding the workflow later will not replay the missed tag-push event, leaving the GitHub release and manifest ahead of PyPI and preventing the documented pending-publisher bootstrap; land the workflow atomically or keep this component disabled until it exists.

Useful? React with 👍 / 👎.

}
}
}
43 changes: 40 additions & 3 deletions sdk/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ ARCBOX_SDK_E2E=1 uv run pytest tests/test_e2e.py
## Toolchain notes

- **uv** is the package/project manager (`uv_build` backend, `uv.lock`
committed). Publishing: `uv build && uv publish` (credentials via
`UV_PUBLISH_TOKEN`; TestPyPI first via a `[[tool.uv.index]]` entry if
desired).
committed). Publishing is CI-only: `uv build && uv publish` under
PyPI trusted publishing (OIDC) — see [Releasing](#releasing); no
`UV_PUBLISH_TOKEN` anywhere.
- **ruff** is both linter and formatter (`E,F,W,I,UP,B,SIM,RUF`).
- **pyright** (strict) is the authoritative type checker. Evaluated
alternatives (2026-08): **ty** 0.0.65 reports 16 false positives here
Expand All @@ -141,6 +141,43 @@ TODO(CI): wire the gates above into `.github/workflows` as an
`sdk-python` job (follow-up; workflow changes are intentionally not part
of this branch).

## Releasing

The SDK is a release-please component (`sdk-python` in
`release-please-config.json`), released on its own cadence, independent
of the main arcbox release train:

1. Conventional commits touching `sdk/python` accumulate on `master`.
2. release-please maintains a dedicated release PR for the component
(separate from the root, fleet-agent, and sdk-typescript PRs) that
bumps the `pyproject.toml` version and updates `CHANGELOG.md`.
3. Merging that PR creates the GitHub release and the tag
`sdk-python-vX.Y.Z` (same convention as `sdk-typescript-vX.Y.Z`).
4. The tag triggers the PyPI publish workflow
(`release-sdk-python.yml`), which checks out the tag's tree, re-runs
the full gate suite (`ruff check`, `ruff format --check`, `pyright`,
`pytest`, `gen_sync.py --check`), builds with `uv build`, and
publishes with `uv publish` via [trusted
publishing](https://docs.pypi.org/trusted-publishers/) (OIDC) —
tokenless: the job's `id-token: write` permission is exchanged for a
short-lived PyPI credential. The job skips cleanly if the version is
already on PyPI, so a re-dispatch never fails on an
already-published release.

One-time bootstrap — unlike npm, PyPI supports [pending
publishers](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/):
the trusted publisher is registered *before* the first upload and CI
does the first publish, so there is no local bootstrap publish and no
API token at any point:

1. On pypi.org → account → Publishing → "Add a new pending publisher"
(GitHub): PyPI project name `arcbox`, owner `arcboxlabs`, repository
`arcbox`, workflow filename `release-sdk-python.yml`, environment
left empty.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PyPI's own docs call the environment field "optional but strongly recommended" — leaving it empty binds the trusted publisher to repo + workflow filename only, so any run of release-sdk-python.yml on any ref can mint a publish credential with no environment approval gate. Worth either setting an environment here (and matching it in the workflow) or stating why empty is deliberate.

2. The first tag-triggered run then creates the `arcbox` project on
PyPI as it publishes, and the pending publisher becomes the
project's regular trusted publisher. Nothing else to configure.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A pending publisher does not reserve the name: per PyPI, it "does not create a project or reserve a project's name until it is actually used to publish," and if someone else registers arcbox first the pending publisher is invalidated. Since arcbox is short and generic and still unclaimed, worth a clause noting the first publish should follow registration promptly — "Nothing else to configure" currently reads as if the name is held.


## Status

Phase 1 of CORE-58 — the hello-world closed loop: `Sandbox` /
Expand Down