From a565c8469a0af916db22eb0f9783d611ab976fa9 Mon Sep 17 00:00:00 2001 From: Edgar Arakelyan Date: Thu, 1 Oct 2026 14:27:51 -1000 Subject: [PATCH] ci: create a GitHub release for each tag, with notes from its pull requests Once both packages are on PyPI, the publish workflow creates the tag's GitHub release. The notes are GitHub's generated list of the pull requests merged since the previous tag, under a line linking the two PyPI versions, since the protocol's version has no tag of its own. The start tag is passed explicitly: GitHub otherwise counts from the previous release, and there are none yet, so the first release would list every pull request. Only this job may write contents, it reads the tag from the environment rather than interpolating it into the script, and an existing release is skipped, so a rerun stays safe. .github/release.yml puts Dependabot's `dependencies` pull requests in their own section. Both packages link the releases as their PyPI changelog, and the README and CONTRIBUTING describe where release notes come from. Co-Authored-By: Claude Opus 5.5 --- .github/release.yml | 8 +++++ .github/workflows/publish-pypi.yml | 37 +++++++++++++++++++++-- CONTRIBUTING.md | 4 ++- README.md | 2 +- packages/agentenv-protocol/pyproject.toml | 1 + pyproject.toml | 1 + 6 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 .github/release.yml diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 00000000..8cb88251 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,8 @@ +changelog: + categories: + - title: Changes + labels: ["*"] + exclude: + labels: ["dependencies"] + - title: Dependencies + labels: ["dependencies"] diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 55860ba2..600c2906 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -3,8 +3,9 @@ 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. +# environment, because PyPI binds a pending publisher to one workflow and environment per project. Once both are on +# PyPI, it creates the tag's GitHub release, whose notes list the pull requests merged since the previous tag. Files +# already on PyPI and a release that already exists are skipped, so a rerun is safe. on: push: @@ -70,3 +71,35 @@ jobs: 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/* + + release: + needs: framework + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + fetch-depth: 0 + persist-credentials: false + - name: Create the GitHub release, with notes from the pull requests since the previous tag + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + run: | + tag="${GITHUB_REF_NAME}" + if gh release view "$tag" >/dev/null 2>&1; then + echo "Release ${tag} already exists." + exit 0 + fi + framework="${tag#v}" + protocol=$(sed -n 's/^version = "\(.*\)"/\1/p' packages/agentenv-protocol/pyproject.toml) + header="On PyPI: [agentenv-framework ${framework}](https://pypi.org/project/agentenv-framework/${framework}/) ยท [agentenv-framework-protocol ${protocol}](https://pypi.org/project/agentenv-framework-protocol/${protocol}/)" + args=(--verify-tag --title "$tag" --generate-notes --notes "$header") + # Without a start tag, GitHub counts from the previous release rather than the previous tag. + previous=$(git tag --list 'v*' --sort=-v:refname | grep -A1 -x "$tag" | sed -n 2p) + if [ -n "$previous" ]; then + args+=(--notes-start-tag "$previous") + fi + gh release create "$tag" "${args[@]}" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e503f573..3ee3ff19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,7 +81,9 @@ Every pull request needs an approving review from a code owner (see `CODEOWNERS` Maintainers cut releases. Version bumps are automated when a labelled pull request merges, so 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. +on the release tag); the import package `agent_env` and the command `agent-env` keep their names. Once both are +on PyPI, the same workflow creates the GitHub release, whose notes are the titles of the pull requests merged since +the previous tag, so a clear pull request title is also the release note. ## Getting help diff --git a/README.md b/README.md index 5c733f5c..b794ba14 100644 --- a/README.md +++ b/README.md @@ -348,7 +348,7 @@ The `agentenv-framework` distribution and `agentenv-framework-protocol` are vers ### Releases -A release is a version bump in both `pyproject.toml` files plus a `vX.Y.Z` tag. Maintainers cut releases: the bump is automated when a labelled pull request merges, so contributors do not edit `version` or push tags (see the Releases section of [CONTRIBUTING.md](https://github.com/scaleapi/agentenv-framework/blob/main/CONTRIBUTING.md)). Each release publishes both packages to PyPI; there is no `CHANGELOG.md`. +A release is a version bump in both `pyproject.toml` files plus a `vX.Y.Z` tag. Maintainers cut releases: the bump is automated when a labelled pull request merges, so contributors do not edit `version` or push tags (see the Releases section of [CONTRIBUTING.md](https://github.com/scaleapi/agentenv-framework/blob/main/CONTRIBUTING.md)). Each release publishes both packages to PyPI and gets a [GitHub release](https://github.com/scaleapi/agentenv-framework/releases) whose notes list the pull requests merged since the previous one; there is no `CHANGELOG.md`. ### Support, security, license diff --git a/packages/agentenv-protocol/pyproject.toml b/packages/agentenv-protocol/pyproject.toml index 07864dfd..1cc596cb 100644 --- a/packages/agentenv-protocol/pyproject.toml +++ b/packages/agentenv-protocol/pyproject.toml @@ -45,6 +45,7 @@ Homepage = "https://www.agentenvframework.com" Documentation = "https://www.agentenvframework.com/docs" Repository = "https://github.com/scaleapi/agentenv-framework/tree/main/packages/agentenv-protocol" Issues = "https://github.com/scaleapi/agentenv-framework/issues" +Changelog = "https://github.com/scaleapi/agentenv-framework/releases" [build-system] requires = ["hatchling"] diff --git a/pyproject.toml b/pyproject.toml index f743d2de..ec122d69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,6 +83,7 @@ Homepage = "https://www.agentenvframework.com" Documentation = "https://www.agentenvframework.com/docs" Repository = "https://github.com/scaleapi/agentenv-framework" Issues = "https://github.com/scaleapi/agentenv-framework/issues" +Changelog = "https://github.com/scaleapi/agentenv-framework/releases" [tool.hatch.build.targets.wheel] packages = ["src/agent_env"]