Skip to content
Merged
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
15 changes: 10 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,24 @@ jobs:
--region us-west-2

- run:
name: Build and publish agentenv-protocol
name: Build and publish the protocol package
command: |
set -euo pipefail
# This index carries the protocol under its former distribution name, agentenv-protocol;
# PyPI has it as agentenv-framework-protocol (publish-pypi.yml).
sed -i 's/^name = "agentenv-framework-protocol"$/name = "agentenv-protocol"/' packages/agentenv-protocol/pyproject.toml
grep -q '^name = "agentenv-protocol"$' packages/agentenv-protocol/pyproject.toml
python -m build packages/agentenv-protocol --outdir packages/agentenv-protocol/dist
twine upload --repository codeartifact packages/agentenv-protocol/dist/*

- run:
name: Build package (pin exact agentenv-protocol version)
name: Build package (pin the exact protocol version, by this index's name)
command: |
set -euo pipefail
PV=$(sed -n 's/^version = "\(.*\)"/\1/p' packages/agentenv-protocol/pyproject.toml)
# Only the quoted requirement: the bare name also appears in the sdist include
# list, the uv workspace members and [tool.uv.sources], which must not be rewritten.
sed -i "s/\"agentenv-protocol[^\"]*\"/\"agentenv-protocol==${PV}\"/" pyproject.toml
# Only the quoted requirement: the directory name also appears in the sdist include list
# and the uv workspace members, and the bare name keys [tool.uv.sources]; none may change.
sed -i "s/\"agentenv-framework-protocol[^\"]*\"/\"agentenv-protocol==${PV}\"/" pyproject.toml
python -c "import tomllib; tomllib.load(open('pyproject.toml','rb'))"
grep -q "\"agentenv-protocol==${PV}\"" pyproject.toml
python -m build
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/check_clean_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from agent_env.task.store import TASK_INSTANCES_COLLECTION, TASKS_COLLECTION, TaskInstance, TaskStepStatus

REUSED = (ARTIFACTS_COLLECTION, TASKS_COLLECTION, LEDGER_COLLECTION)
OWN_DISTRIBUTIONS = {"agentenv-framework", "agentenv-protocol"}
OWN_DISTRIBUTIONS = {"agentenv-framework", "agentenv-framework-protocol"}


def main() -> int:
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/clean_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def main() -> int:
for package in ("packages/agentenv-protocol", "."):
_run([uv, "tool", "run", "--python", sys.executable, "--from", "build", "pyproject-build",
"--outdir", str(work / "dist"), package], env=env, cwd=REPO)
protocol = _one(work / "dist", "agentenv_protocol-*.whl")
protocol = _one(work / "dist", "agentenv_framework_protocol-*.whl")
framework = _one(work / "dist", "agentenv_framework-*.whl")

_step(f"Check {framework.name} ships every tracked example and its entry points")
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/local-backends.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Lockfile resolves from PyPI only
run: |
if grep 'source = { registry = ' uv.lock | grep -v 'registry = "https://pypi.org/simple"' | grep -q .; then echo "uv.lock has a registry source other than PyPI"; exit 1; fi
grep -A2 '^name = "agentenv-protocol"$' uv.lock | grep -q 'source = { editable = "packages/agentenv-protocol" }'
grep -A2 '^name = "agentenv-framework-protocol"$' uv.lock | grep -q 'source = { editable = "packages/agentenv-protocol" }'
- name: Lockfile is current, before and after a release bump
run: |
uv lock --check
Expand Down
72 changes: 72 additions & 0 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Publish to PyPI

# On a release tag, uploads agentenv-framework-protocol and then agentenv-framework to PyPI through trusted
# publishing, so no token is stored anywhere. Each job builds its distribution the way the release does
# (agentenv-framework pinned to the exact agentenv-framework-protocol it was released with) and runs in its own
# environment, because PyPI binds a pending publisher to one workflow and environment per project. Files already on
# PyPI are skipped, so a rerun is safe.

on:
push:
tags: ["v*"]

permissions:
contents: read

jobs:
protocol:
runs-on: ubuntu-latest
timeout-minutes: 15
environment: pypi-protocol
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Install uv from public PyPI
run: python -m pip install --quiet --index-url https://pypi.org/simple uv

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Release tools can change
Each release installs the latest uv and fetches twine without a version pin. A later tool update could break the checks or upload even when the release code has not changed. Pin both to versions tested with this workflow.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/publish-pypi.yml
Line: 31

Comment:
**Release tools can change**
Each release installs the latest `uv` and fetches `twine` without a version pin. A later tool update could break the checks or upload even when the release code has not changed. Pin both to versions tested with this workflow.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Cursor Fix in Claude Code Fix in Codex

- name: Check the tag names the version being built
run: |
version=$(sed -n 's/^version = "\(.*\)"/\1/p' pyproject.toml)
[ "v${version}" = "${GITHUB_REF_NAME}" ] || { echo "::error::tag ${GITHUB_REF_NAME}, but pyproject.toml is at ${version}"; exit 1; }
- name: Build agentenv-framework-protocol
run: uv build --no-sources packages/agentenv-protocol --out-dir dist
- name: Check its metadata renders
run: uvx --index-url https://pypi.org/simple twine check --strict dist/*
- name: Publish agentenv-framework-protocol
run: uv publish --trusted-publishing always --check-url https://pypi.org/simple/ dist/*

framework:
needs: protocol
runs-on: ubuntu-latest
timeout-minutes: 15
environment: pypi
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
- name: Install uv from public PyPI
run: python -m pip install --quiet --index-url https://pypi.org/simple uv
- name: Build agentenv-framework, pinned to this release's agentenv-framework-protocol
run: |
protocol=$(sed -n 's/^version = "\(.*\)"/\1/p' packages/agentenv-protocol/pyproject.toml)
# Only the quoted requirement: the directory name also appears in the sdist include list and the uv
# workspace members, and the bare name keys [tool.uv.sources]; none of those may be rewritten.
sed -i "s/\"agentenv-framework-protocol[^\"]*\"/\"agentenv-framework-protocol==${protocol}\"/" pyproject.toml
grep -q "\"agentenv-framework-protocol==${protocol}\"" pyproject.toml
uv build --no-sources --out-dir dist
- name: Check its metadata renders
run: uvx --index-url https://pypi.org/simple twine check --strict dist/*
- name: Publish agentenv-framework
run: uv publish --trusted-publishing always --check-url https://pypi.org/simple/ dist/*
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ The required checks on pull requests and `main` are `unit`, `integration-local`,
`integration-local-slow`, `installer`, `plugin-api` and `clean-install`. `.github/workflows/local-backends.yml` runs
the first four, all installed from public PyPI with no secrets and no external services (a `registry:2` service container for the integration jobs). The
`unit` job also fails if `uv.lock` resolves anything from a registry other than PyPI or if
`agentenv-protocol` is not the editable workspace member. The integration jobs run
`agentenv-framework-protocol` is not the editable workspace member. The integration jobs run
`.github/scripts/check_skip_policy.py` over the JUnit report: only `agentenv-capability-missing`
skips for the allowed capabilities pass, and the fast job allows no skips under
`tst/integration/store/`. The `installer` job runs `tst/installer` when a pull request or push
Expand Down
7 changes: 4 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ This is the same install CI performs. `make install` is equivalent.

| Command | What it runs | Needs |
|---|---|---|
| `make unit-test` | unit suite for `agentenv-framework` and `agentenv-protocol` | nothing external |
| `make unit-test` | unit suite for `agentenv-framework` and `agentenv-framework-protocol` | nothing external |
| `make int-test-fast` | integration tests against the local backends | Docker |
| `make int-test-slow` | tests that build images or deploy sandboxes, minutes each | Docker, and a sandbox backend for some |
| `make clean-install-test` | both distributions built as the release builds them, installed into a fresh venv from public PyPI, and `agent-env run hello` run twice by name | Python 3.11, uv and git |
Expand Down Expand Up @@ -79,8 +79,9 @@ Every pull request needs an approving review from a code owner (see `CODEOWNERS`
## Releases

Maintainers cut releases. Version bumps are automated when a labelled pull request merges, so
contributors should not edit `version` in `pyproject.toml`. Releases publish the distribution
`agentenv-framework`; the import package `agent_env` and the command `agent-env` keep their names.
contributors should not edit `version` in `pyproject.toml`. Each release publishes
`agentenv-framework` and `agentenv-framework-protocol` to PyPI (`.github/workflows/publish-pypi.yml`, trusted publishing
on the release tag); the import package `agent_env` and the command `agent-env` keep their names.

## Getting help

Expand Down
Loading
Loading