ci: dispatch PyPI release after creating GitHub release#3068
Conversation
Co-authored-by: openhands <openhands@all-hands.dev>
Python API breakage checks — ✅ PASSEDResult: ✅ PASSED |
REST API breakage checks (OpenAPI) — ✅ PASSEDResult: ✅ PASSED |
all-hands-bot
left a comment
There was a problem hiding this comment.
Taste Rating: 🟢 Good taste - Pragmatic solution to a known GitHub Actions limitation
The approach is correct: GITHUB_TOKEN cannot trigger workflows from release events, so explicit dispatch via workflow_dispatch is the standard workaround. Implementation looks solid:
actions: writepermission is necessary and appropriate- Dispatch conditional matches release creation (
steps.check.outputs.exists == 'false') - Tag reference
--ref "v${VERSION}"ensures the workflow runs against the tagged commit - Manual validation confirms the dispatch works
[RISK ASSESSMENT]
CI infrastructure change that adds workflow dispatch capability. Manually tested, no agent behavior changes, no breaking changes.
VERDICT:
✅ Worth merging: Clean fix for the release automation gap
KEY INSIGHT:
Explicit workflow dispatch is the correct pattern when using GITHUB_TOKEN to create releases, since GitHub intentionally prevents GITHUB_TOKEN-triggered events from starting new workflow runs.
all-hands-bot
left a comment
There was a problem hiding this comment.
✅ QA Report: PASS
Workflow changes validated. The PR successfully addresses the release automation gap by explicitly dispatching the PyPI workflow when GitHub releases are created.
Does this PR achieve its stated goal?
Yes. The PR fixes the release workflow so that PyPI packages are automatically published when a GitHub release is created. The root cause was that create-release.yml uses the repository GITHUB_TOKEN to create releases, which doesn't trigger release.published events for other workflows (GitHub's security feature to prevent infinite loops). The fix explicitly dispatches pypi-release.yml via workflow_dispatch, bypassing this limitation.
| Phase | Result |
|---|---|
| Environment Setup | ✅ Repository checked out, workflows validated |
| CI Status | ✅ All critical checks passing (pre-commit, tests, API breakage) |
| Functional Verification | ✅ Workflow syntax validated, command tested, historical evidence confirms the fix |
Functional Verification
Test 1: Verify the problem exists
Step 1 — Evidence of the broken state (v1.20.0 release):
Checked workflow runs for the v1.20.0 release (created May 4, 2026 at 15:30:39Z):
$ gh run list --repo OpenHands/software-agent-sdk --workflow "pypi-release.yml" --limit 10 \
--json databaseId,displayTitle,headBranch,conclusion,event,createdAt
# v1.20.0 (May 4, 2026):
{
"event": "workflow_dispatch", # <- Manual dispatch on May 5
"createdAt": "2026-05-05T17:18:43Z",
"headBranch": "v1.20.0"
}
# Previous releases (v1.19.1, v1.19.0, v1.18.1, v1.18.0):
{
"event": "release", # <- Automatic trigger
...
}Interpretation: The v1.20.0 release did NOT automatically trigger the PyPI workflow via release.published event. Only a manual workflow_dispatch on May 5 published the packages. Previous releases all triggered automatically via the release event.
Root cause confirmed: The create-release.yml workflow was introduced in commit a6201c3 (May 4, 10:05 AM). When v1.20.0's release PR merged (same day, ~3:30 PM), the new workflow created the release using GITHUB_TOKEN, which doesn't trigger release.published for other workflows.
Test 2: Validate the fix implementation
Step 2 — Verify PR changes are correct:
- Permission added:
$ git diff origin/main HEAD -- .github/workflows/create-release.yml | grep -A 2 "permissions:"
+ actions: write
contents: write✅ The actions: write permission is required to dispatch workflows.
- Dispatch step added:
- name: Dispatch PyPI release workflow
if: steps.check.outputs.exists == 'false'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version.outputs.version }}
run: |
gh workflow run pypi-release.yml \
--repo "${{ github.repository }}" \
--ref "v${VERSION}"✅ Command syntax verified with gh workflow run --help. The --ref parameter correctly specifies the release tag.
- Workflow supports workflow_dispatch:
$ gh workflow view pypi-release.yml --repo OpenHands/software-agent-sdk --yaml
on:
workflow_dispatch: # <- Already supported
release:
types: [published]✅ The target workflow supports workflow_dispatch trigger.
- Summary message updated:
- "The `pypi-release.yml` workflow will now publish packages to PyPI."
+ "The `pypi-release.yml` workflow was dispatched to publish packages to PyPI."✅ More accurate messaging (active vs. future tense).
Test 3: Verify YAML syntax and pre-commit compliance
Step 3 — Run validation tools:
$ uv run pre-commit run --files .github/workflows/create-release.yml
Format YAML files........................................................Passed
Ruff format..........................................(no files to check)Skipped
Ruff lint............................................(no files to check)Skipped
PEP8 style check (pycodestyle).......................(no files to check)Skipped
Type check with pyright..............................(no files to check)Skipped✅ Pre-commit hooks pass.
Test 4: Evidence the fix works
Step 4 — Validation from PR author:
The PR author manually tested the dispatch command for v1.20.0:
$ gh run view 25391325228 --repo OpenHands/software-agent-sdk
{
"conclusion": "success",
"displayTitle": "Publish all OpenHands packages (uv)",
"headBranch": "v1.20.0",
"name": "Publish all OpenHands packages (uv)",
"status": "completed"
}✅ The workflow dispatch succeeded, confirming the approach works.
Issues Found
None.
Conclusion: This PR correctly implements the fix described in the PR description. The three changes (permission grant, explicit dispatch, updated summary) work together to ensure PyPI releases happen automatically when GitHub releases are created, without relying on the release.published event that doesn't trigger for repository-token-created releases.
Co-authored-by: openhands <openhands@all-hands.dev>
Summary
actions: writeso it can dispatch workflows.pypi-release.ymlexplicitly after creating a GitHub release.Root Cause
The auto-created GitHub release uses the repository
GITHUB_TOKEN, so the resultingrelease.publishedevent does not create another workflow run. Dispatchingpypi-release.ymldirectly uses the supportedworkflow_dispatchpath.Validation
uv run pre-commit run --files .github/workflows/create-release.ymlpypi-release.ymlforv1.20.0: https://github.com/OpenHands/software-agent-sdk/actions/runs/25391325228Agent Server images for this PR
• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server
Variants & Base Images
eclipse-temurin:17-jdknikolaik/python-nodejs:python3.13-nodejs22-slimgolang:1.21-bookwormPull (multi-arch manifest)
# Each variant is a multi-arch manifest supporting both amd64 and arm64 docker pull ghcr.io/openhands/agent-server:f7548bd-pythonRun
All tags pushed for this build
About Multi-Architecture Support
f7548bd-python) is a multi-arch manifest supporting both amd64 and arm64f7548bd-python-amd64) are also available if needed