Skip to content

Merge pull request #34 from ApodexAI/fix/tokenizer-cold-cache-fetch-gate #7

Merge pull request #34 from ApodexAI/fix/tokenizer-cold-cache-fetch-gate

Merge pull request #34 from ApodexAI/fix/tokenizer-cold-cache-fetch-gate #7

Workflow file for this run

name: Release
on:
push:
tags: ["v*"]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
# Fail before building anything if the tag names a version the tree does
# not declare, or if the release has no changelog entry to publish.
- name: Verify tag matches declared version
run: python3 scripts/version.py --check-tag "$TAG"
env:
TAG: ${{ github.ref_name }}
- name: Extract release notes
run: |
set -euo pipefail
version="$(python3 scripts/version.py)"
python3 scripts/changelog_section.py "$version" > release-notes.md
# The tagged tree is re-verified rather than trusting main's CI run: a tag
# can point at a commit that never went through a pull request.
- run: uv sync --frozen --extra dev
- run: uv run ruff check agent_core tests scripts
- run: uv run pyright agent_core
- run: uv run pytest -q
# The gate pins tiktoken's own cache key and content hash, and only a real
# tiktoken can falsify them. Scope that optional dependency to this contract
# test; the isolated run uses the tokenizer version pinned in uv.lock.
- run: uv run --isolated --frozen --extra dev --extra tokenizer pytest -q tests/test_tokenizer_nonblocking.py::test_pinned_cache_metadata_matches_tiktokens_own_declaration
- run: uv build
# A PyPI version number can never be reused, not even after deleting the
# release. Reject malformed metadata here rather than burning the version.
- name: Validate package metadata
run: uv run --with twine twine check dist/*
# The release contract requires the artifact to install and import in a
# clean environment. Checking it here matters more than usual because a
# PyPI version number cannot be reclaimed: a wheel that fails to import
# would burn the version rather than fail the release.
- name: Install and import the built wheel in a clean environment
run: |
set -euo pipefail
uv venv /tmp/wheel-smoke
uv pip install --python /tmp/wheel-smoke/bin/python dist/*.whl
/tmp/wheel-smoke/bin/python - <<'SMOKE'
import agent_core
from agent_core import user_msg
assert user_msg("hi") == {"role": "user", "content": "hi"}
print("imported", agent_core.__name__, "with", len(agent_core.__all__), "exports")
SMOKE
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-artifacts
path: |
dist/
release-notes.md
if-no-files-found: error
# Separate job so `id-token: write` — which mints the OIDC identity PyPI
# trusts — is scoped to publishing alone and never exposed to the build or to
# any third-party action running beside it.
publish-pypi:
needs: build
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-artifacts
path: release-artifacts/
# Trusted Publishing: no API token, no secret. PyPI verifies the OIDC
# claim naming this repository, this workflow file, and the environment
# above, then issues a short-lived upload token itself.
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
packages-dir: release-artifacts/dist/
# Publish the GitHub Release last. A failed PyPI upload therefore cannot leave
# a GitHub Release claiming that a version was published when it was not.
publish-github:
needs: publish-pypi
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-artifacts
path: release-artifacts/
# `gh release create` is not retry-safe after a partial API failure. Use
# an upsert so rerunning this job always converges on the same release.
- name: Publish GitHub Release
run: |
set -euo pipefail
if gh release view "$TAG" >/dev/null 2>&1; then
gh release edit "$TAG" \
--title "AgentCore ${TAG#v}" \
--notes-file release-artifacts/release-notes.md
gh release upload "$TAG" --clobber \
release-artifacts/dist/*.whl release-artifacts/dist/*.tar.gz
else
gh release create "$TAG" \
--title "AgentCore ${TAG#v}" \
--notes-file release-artifacts/release-notes.md \
release-artifacts/dist/*.whl release-artifacts/dist/*.tar.gz
fi
env:
TAG: ${{ github.ref_name }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# This job downloads artifacts and never checks out the repository, so
# `gh` has no git remote to infer the target from and fails with
# "not a git repository". Name it explicitly.
GH_REPO: ${{ github.repository }}