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
53 changes: 53 additions & 0 deletions .github/workflows/_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,41 @@ name: _build

on:
workflow_call:
inputs:
checkout_ref:
description: "Optional ref to check out, used by manual release reruns."
required: false
type: string
default: ""
release_tag:
description: "Optional v-prefixed tag that should define the package version."
required: false
type: string
default: ""

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.checkout_ref || github.ref }}
fetch-depth: 0 # Full history required for setuptools-scm

- name: Pin package version for release tags
if: ${{ inputs.release_tag != '' || startsWith(github.ref, 'refs/tags/v') }}
run: |
TAG="${{ inputs.release_tag }}"
TAG="${TAG:-$GITHUB_REF_NAME}"
VERSION="${TAG#v}"
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Release tag '$TAG' did not resolve to a semver package version."
exit 1
fi
echo "SETUPTOOLS_SCM_PRETEND_VERSION_FOR_AGENTOPS_TOOLKIT=$VERSION" >> "$GITHUB_ENV"
echo "EXPECTED_PACKAGE_VERSION=$VERSION" >> "$GITHUB_ENV"
echo "Release package version pinned to $VERSION from $TAG"

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
Expand All @@ -52,6 +78,33 @@ jobs:
- name: Build package
run: uv build

- name: Assert release artifact version
run: |
if [ -z "${EXPECTED_PACKAGE_VERSION:-}" ]; then
echo "No release package version was pinned; skipping artifact version assertion."
exit 0
fi
python - <<'PY'
import os
import sys
from pathlib import Path

expected = os.environ["EXPECTED_PACKAGE_VERSION"]
dist = Path("dist")
matches = [
*sorted(dist.glob(f"agentops_toolkit-{expected}.tar.gz")),
*sorted(dist.glob(f"agentops_toolkit-{expected}-*.whl")),
]
if not matches:
print(f"::error::Expected dist artifact for version {expected}, found:")
for artifact in sorted(dist.iterdir()):
print(f" - {artifact.name}")
sys.exit(1)
print("Release artifacts:")
for artifact in matches:
print(f" - {artifact.name}")
PY

- name: Show build info
run: |
ls -la dist/
Expand Down
15 changes: 10 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,19 @@ jobs:
run: |
for i in 1 2 3 4 5; do
echo "Attempt $i: installing agentops-toolkit==${{ steps.version.outputs.version }}"
pip install \
if pip install \
"agentops-toolkit==${{ steps.version.outputs.version }}" \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
&& break
echo "Not available yet, waiting 30s..."
sleep 30
--extra-index-url https://pypi.org/simple/; then
exit 0
fi
if [ "$i" -lt 5 ]; then
echo "Not available yet, waiting 30s..."
sleep 30
fi
done
echo "::error::agentops-toolkit==${{ steps.version.outputs.version }} was not available from TestPyPI after 5 attempts."
exit 1

- name: Smoke test
run: |
Expand Down
22 changes: 18 additions & 4 deletions .github/workflows/cut-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,27 @@ jobs:
- name: Update CHANGELOG
run: |
DATE=$(date +%Y-%m-%d)
# Only insert versioned section if it doesn't already exist
if grep -q "## \[${{ env.version }}\]" CHANGELOG.md; then
echo "CHANGELOG already has [${{ env.version }}] entry — skipping insertion"
else
sed -i "/adheres to \[Semantic Versioning\]/a \\\n## [${{ env.version }}] - $DATE\n" CHANGELOG.md
echo "CHANGELOG updated with [${{ env.version }}] - $DATE"
exit 0
fi
VERSION="${{ env.version }}" DATE="$DATE" python - <<'PY'
import os
import sys
from pathlib import Path

path = Path("CHANGELOG.md")
text = path.read_text(encoding="utf-8")
marker = "## [Unreleased]"
version = os.environ["VERSION"]
date = os.environ["DATE"]
if marker not in text:
print("::error::CHANGELOG.md is missing the ## [Unreleased] section.")
sys.exit(1)
replacement = f"{marker}\n\n## [{version}] - {date}"
path.write_text(text.replace(marker, replacement, 1), encoding="utf-8")
PY
echo "CHANGELOG updated with [${{ env.version }}] - $DATE"

- name: Sync plugin versions
run: |
Expand Down
20 changes: 15 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ jobs:
# Reusable build: test + package
build:
uses: ./.github/workflows/_build.yml
with:
checkout_ref: ${{ inputs.tag || github.ref }}
release_tag: ${{ inputs.tag || (startsWith(github.ref, 'refs/tags/v') && github.ref_name) || '' }}

# Publish to TestPyPI for final pre-release verification
publish-testpypi:
Expand Down Expand Up @@ -107,6 +110,8 @@ jobs:
if [ -n "${{ inputs.tag }}" ]; then
VERSION="${{ inputs.tag }}"
VERSION="${VERSION#v}"
elif [[ "$GITHUB_REF" == refs/tags/v* ]]; then
VERSION="${GITHUB_REF_NAME#v}"
else
pip install setuptools-scm
VERSION=$(python -m setuptools_scm)
Expand All @@ -118,14 +123,19 @@ jobs:
run: |
for i in 1 2 3 4 5; do
echo "Attempt $i: installing agentops-toolkit==${{ steps.version.outputs.version }}"
pip install \
if pip install \
"agentops-toolkit==${{ steps.version.outputs.version }}" \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
&& break
echo "Not available yet, waiting 30s..."
sleep 30
--extra-index-url https://pypi.org/simple/; then
exit 0
fi
if [ "$i" -lt 5 ]; then
echo "Not available yet, waiting 30s..."
sleep 30
fi
done
echo "::error::agentops-toolkit==${{ steps.version.outputs.version }} was not available from TestPyPI after 5 attempts."
exit 1

- name: Smoke test — version and help
run: |
Expand Down
15 changes: 10 additions & 5 deletions .github/workflows/staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,19 @@ jobs:
run: |
for i in 1 2 3 4 5; do
echo "Attempt $i: installing agentops-toolkit==${{ steps.version.outputs.version }}"
pip install \
if pip install \
"agentops-toolkit==${{ steps.version.outputs.version }}" \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
&& break
echo "Not available yet, waiting 30s..."
sleep 30
--extra-index-url https://pypi.org/simple/; then
exit 0
fi
if [ "$i" -lt 5 ]; then
echo "Not available yet, waiting 30s..."
sleep 30
fi
done
echo "::error::agentops-toolkit==${{ steps.version.outputs.version }} was not available from TestPyPI after 5 attempts."
exit 1

- name: Smoke test — version and help
run: |
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ This format follows [Keep a Changelog](https://keepachangelog.com/) and adheres

## [Unreleased]

### Fixed
- **Release workflow verification.** Release builds now pin package versions from
the release tag, assert the generated distribution matches that version, and
fail TestPyPI verification immediately when the expected package is not
available.

## [0.2.1] - 2026-05-26

### Changed
- Consolidated the tutorial set into two quickstarts plus one end-to-end
Foundry + AgentOps workshop, with the quickstarts now covering the broader
Expand Down
Loading