Skip to content

Release

Release #5

Workflow file for this run

name: Release
on:
workflow_dispatch:
concurrency:
group: odp-python-release
cancel-in-progress: false
permissions:
contents: read
jobs:
verify:
if: github.repository == 'offering-protocol/odp-python'
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.release.outputs.tag }}
version: ${{ steps.release.outputs.version }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-python@v7
with:
python-version: "3.14"
- uses: astral-sh/setup-uv@v10.2.0
with:
version: "0.11.8"
enable-cache: true
cache-dependency-glob: uv.lock
- name: Validate release
id: release
env:
GH_TOKEN: ${{ github.token }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
echo "Releases must run from main." >&2
exit 1
fi
version=$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "The project version must be a stable semantic version such as 0.1.0." >&2
exit 1
fi
tag="v$version"
if gh release view "$tag" >/dev/null 2>&1; then
echo "Release $tag already exists." >&2
exit 1
fi
if git rev-parse --verify "refs/tags/$tag" >/dev/null 2>&1; then
tag_commit=$(git rev-list -n 1 "$tag")
if [[ "$tag_commit" != "$GITHUB_SHA" ]]; then
echo "Tag $tag does not identify the selected main commit." >&2
exit 1
fi
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "version=$version" >> "$GITHUB_OUTPUT"
- run: uv sync --all-groups --locked --python 3.14
- name: Check out ODP specifications
uses: actions/checkout@v7
with:
repository: offering-protocol/odp-specs
path: .conformance/odp-specs
- name: Check out Node.js reference implementation
uses: actions/checkout@v7
with:
repository: offering-protocol/odp-node
path: .conformance/odp-node
- name: Set up pnpm
uses: pnpm/action-setup@v6
with:
version: 11.1.3
- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: 22
- name: Install Node.js reference implementation
run: pnpm --dir .conformance/odp-node install --frozen-lockfile
- name: Verify release
run: make verify conformance interoperability
env:
ODP_NODE_DIR: .conformance/odp-node
ODP_PYTHON: python
ODP_SPECS_DIR: .conformance/odp-specs
- name: Upload distributions
uses: actions/upload-artifact@v7
with:
name: odp-python-distributions
path: dist/*
if-no-files-found: error
retention-days: 7
- name: Upload conformance reports
uses: actions/upload-artifact@v7
with:
name: odp-python-release-conformance
path: .conformance/reports/*.json
if-no-files-found: error
retention-days: 7
release:
needs: verify
environment: release
permissions:
attestations: write
contents: write
id-token: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-python@v7
with:
python-version: "3.14"
- uses: actions/download-artifact@v8
with:
name: odp-python-distributions
path: dist
- name: Download conformance reports
uses: actions/download-artifact@v8
with:
name: odp-python-release-conformance
path: .conformance/reports
- name: Create release tag
env:
TAG: ${{ needs.verify.outputs.tag }}
run: |
if git rev-parse --verify "refs/tags/$TAG" >/dev/null 2>&1; then
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag --annotate "$TAG" --message "ODP Python $TAG" "$GITHUB_SHA"
git push origin "$TAG"
- name: Attest distributions
uses: actions/attest-build-provenance@v4
with:
subject-path: dist/*
- name: Check PyPI version
id: registry
env:
VERSION: ${{ needs.verify.outputs.version }}
run: |
if curl --fail --silent --show-error \
"https://pypi.org/pypi/offering-protocol/$VERSION/json" >/dev/null; then
echo "published=true" >> "$GITHUB_OUTPUT"
else
echo "published=false" >> "$GITHUB_OUTPUT"
fi
- name: Publish to PyPI
if: steps.registry.outputs.published != 'true'
uses: pypa/gh-action-pypi-publish@release/v1
- name: Verify PyPI consumer
run: ./scripts/verify-consumer.sh
env:
ODP_CONSUMER_SOURCE: registry
ODP_PYTHON_VERSION: ${{ needs.verify.outputs.version }}
- name: Publish GitHub release
run: >-
gh release create "${{ needs.verify.outputs.tag }}"
.conformance/reports/agent.json#odp-python-agent-conformance.json
.conformance/reports/service.json#odp-python-service-conformance.json
dist/*
--generate-notes
--title "ODP Python ${{ needs.verify.outputs.tag }}"
--verify-tag
env:
GH_TOKEN: ${{ github.token }}