release: prepare v2026.5.3 (cookie-import + three-mode qa-runner) #3
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Tag-triggered release pipeline. | |
| # | |
| # CI (lint, typecheck, test, audit) runs on Gitea — see .gitea/workflows/ci.yml. | |
| # This workflow exists for two reasons: | |
| # 1. To publish the sdist + wheel as a GitHub release at the tag (always on). | |
| # 2. To publish those same artefacts to PyPI via OIDC trusted-publisher | |
| # (gated on the `ENABLE_PYPI_PUBLISH` repo variable being `'true'` — | |
| # requires the one-time PyPI/TestPyPI setup from #12 to be complete). | |
| # | |
| # Phase 1 (current, until #12 is closed): `publish` (PyPI) is skipped via the | |
| # repo variable gate; the GitHub release ships from `build` directly. Tag | |
| # pushes produce a complete release on | |
| # https://github.com/jmagly/carbonyl-agent/releases with the wheel + sdist | |
| # attached, but nothing is sent to PyPI. | |
| # | |
| # Phase 2 (after #12 is closed): set repository variable | |
| # `ENABLE_PYPI_PUBLISH=true` in Settings → Secrets and variables → Actions → | |
| # Variables. The next tag push will run the publish job; the GitHub release | |
| # then runs after publish as the strict release gate. | |
| # | |
| # Refs: roctinam/carbonyl-agent#11, #12 | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Verify tag matches pyproject.toml version | |
| run: | | |
| TAG_VERSION="${GITHUB_REF_NAME#v}" | |
| PYPROJECT_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])") | |
| if [ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]; then | |
| echo "::error::Tag $GITHUB_REF_NAME does not match pyproject.toml version $PYPROJECT_VERSION" | |
| exit 1 | |
| fi | |
| - run: pip install hatch twine | |
| - run: hatch build | |
| - run: twine check dist/* | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| publish: | |
| # PyPI publish — gated on ENABLE_PYPI_PUBLISH repo variable. | |
| # Skipped in Phase 1 (pre-#12 completion). To enable: Settings → | |
| # Secrets and variables → Actions → Variables → add `ENABLE_PYPI_PUBLISH` | |
| # with value `true`. Then close #12. | |
| if: vars.ENABLE_PYPI_PUBLISH == 'true' | |
| runs-on: ubuntu-latest | |
| needs: [build] | |
| environment: | |
| name: release | |
| url: https://pypi.org/p/carbonyl-agent | |
| permissions: | |
| id-token: write | |
| steps: | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Publish to PyPI via trusted publisher (OIDC) | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| github-release: | |
| # GitHub release — always runs. Depends on `build` directly so the | |
| # release ships even when the PyPI publish job is gated off (Phase 1). | |
| # When PyPI publish is enabled (Phase 2), `needs: [build, publish]` | |
| # would be the strict ordering; for now we keep `needs: [build]` and | |
| # rely on the gate. If publish runs and fails, github-release still | |
| # runs — that is intentional during Phase 1 so a transient PyPI hiccup | |
| # never blocks the GitHub release (which is the source of truth | |
| # pre-#12). Reconsider after #12 closes. | |
| runs-on: ubuntu-latest | |
| needs: [build] | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Extract release notes from CHANGELOG.md | |
| id: notes | |
| run: | | |
| VERSION="${GITHUB_REF_NAME#v}" | |
| # Pull the section between "## [VERSION]" (or "## VERSION") and the next "## " heading | |
| awk -v ver="$VERSION" ' | |
| $0 ~ "^## \\[?"ver"\\]?" { in_section=1; next } | |
| in_section && /^## / { exit } | |
| in_section { print } | |
| ' CHANGELOG.md > release-notes.md | |
| if [ ! -s release-notes.md ]; then | |
| echo "No CHANGELOG section for $VERSION; using tag annotation instead." > release-notes.md | |
| fi | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Create GitHub release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: carbonyl-agent ${{ steps.notes.outputs.version }} | |
| body_path: release-notes.md | |
| files: dist/* | |
| fail_on_unmatched_files: true |