Repository navigation
ci: release automation via release-please (release-actions) - #230
Conversation
Replace the manual "push a vX.Y.Z tag" release flow with the same merge-driven process used by software-agent-sdk, adapted for npm: - prepare-release.yml: manual dispatch opens a rel-X.Y.Z PR that bumps the package version (npm version --no-git-tag-version). Uses a bot PAT so the PR triggers CI + integration tests. - create-release.yml: on merge of a rel-* PR, creates the GitHub release (auto notes + release-note-required preamble) and dispatches the publish workflows (releases created by GITHUB_TOKEN don't auto-trigger them). - npm-publish.yml / release.yml: now triggered by release:published (and workflow_dispatch) instead of raw tag pushes; skip pre-releases; the GitHub Release creation moves out of release.yml into create-release.yml. - npm-publish.yml dispatches version-bump-prs.yml after a successful publish. - version-bump-prs.yml: waits for the version on npm, then opens a bump PR in agent-canvas (the only exact-pinned consumer; others float or track git). - Docs: add .github/workflows/README-RELEASE.md and update PUBLISHING.md. Requires an OPENHANDS_BOT_GITHUB_PAT_PUBLIC secret (classic PAT, repo+workflow).
Endpoint audit❌ 8 off-contract call(s) — not on the agent-server · classifiers: cloud
❌ Not on agent-server (gated, 8)⛔ (no known backend) — served by no backend we can see (7)
|
Adds bump-agent-server-version.yml, which keeps the pinned software-agent-sdk / agent-server image up to date (the version this client is tested and documented against). Source of truth is package.json -> config.agentServerImage; the workflow also updates the integration-tests.yml, AGENTS.md, and README.md mirrors, then opens a bump-agent-server-X.Y.Z PR. - Runs weekly (schedule) and on manual workflow_dispatch with an optional explicit version; otherwise detects the latest non-prerelease SDK release. - Verifies the matching agent-server image is published in GHCR before bumping, so it won't open a PR that integration tests can't pass. - Opening the PR (via the bot PAT) runs CI + integration tests against the new image, validating the client before merge. - Decoupled from the npm package version: this does not cut a client release. Documented in AGENTS.md and README-RELEASE.md.
Remove bump-agent-server-version.yml. Bumping the tracked agent-server / SDK version is now driven by the software-agent-sdk release automation, which opens a bump-agent-server-X.Y.Z PR here on each SDK release (event-driven on real releases instead of polling weekly). Docs reworded accordingly.
|
✅ Review complete. This review was performed through OpenHands Cloud Automation. You can log in and view the conversation here. |
all-hands-bot
left a comment
There was a problem hiding this comment.
🟡 Acceptable — clean port of the SDK release automation with sensible npm adaptations. Architecture is sound; the PAT-vs-GITHUB_TOKEN distinction is well-understood and documented, the duplicate-release guard is in place, and concurrency groups protect against double-publish. One documentation inconsistency must be fixed before this merges.
[CRITICAL ISSUES]
- [PR Description,
⚠️ Prerequisite section] Secret name mismatch: The prerequisite block says the repo needsOPENHANDS_BOT_GITHUB_PAT_PUBLIC, but every workflow and every documentation artifact added by this PR usesOPENHANDS_BOT_GITHUB_TYPESCRIPT_CLIENT. A maintainer following the PR description to set up prerequisites would create the wrong secret; the workflows would then silently fail at the steps that use it. Please update the PR description to useOPENHANDS_BOT_GITHUB_TYPESCRIPT_CLIENT.
[IMPROVEMENT OPPORTUNITIES]
- [.github/workflows/version-bump-prs.yml, job
create-version-bump-prs] Missing job timeout: The npm polling loop inside this job can run for up to 20 minutes (60 × 20 s). Withouttimeout-minuteson the job, a worst-case stuck run (e.g., npm propagation failure followed by a hung step) could tie up a runner slot for the 6-hour default. Consider addingtimeout-minutes: 30to bound execution time.
[TESTING GAPS]
- [PR Description] No end-to-end evidence: The validation section confirms YAML validity and PR-body rendering but does not demonstrate an actual workflow run. For release automation, a full dry-run is not always practical; at minimum, record which steps have been manually smoke-tested (e.g., trigger
prepare-release.ymlagainst a test branch, verify thecreate-release.ymlcondition logic) so reviewers can assess confidence.
[RISK ASSESSMENT]
- [Overall PR]
⚠️ Risk Assessment: 🟡 MEDIUM
This is a complete replacement of the existingpush: tagsrelease flow — the old trigger is fully removed from both publish workflows. Recovery viaworkflow_dispatchexists, and the PR's own open question acknowledges the lack of a push-tags fallback. The merge-driven flow is proven insoftware-agent-sdk, but the first release on this repo should be treated as a live test; a patch version is safer than a minor/major for the inaugural run. The secret-name discrepancy is the only blocker.
VERDICT:
❌ Needs rework: Fix the secret name in the PR description before merging — everything else is solid.
KEY INSIGHT:
The automation logic is correct and well-engineered; the only gap is a stale prerequisite note in the PR body that names the wrong secret.
Improve this review? If any feedback above seems incorrect or irrelevant to this repository, you can teach the reviewer to do better:
- Add a
.agents/skills/custom-codereview-guide.mdfile to your branch (or edit it if one already exists) with the/codereviewtrigger and the context the reviewer is missing. See the customization docs for the required frontmatter format.- Re-request a review - the reviewer reads guidelines from the PR branch, so your changes take effect immediately.
- When your PR is merged, the guideline file goes through normal code review by repository maintainers.
Resolve with AI? Install the iterate skill in your agent and run
/iterateto automatically drive this PR through CI, review, and QA until it's merge-ready.Was this review helpful? React with 👍 or 👎 to give feedback.
This review was generated by an AI agent (OpenHands) on behalf of the user through OpenHands Automation. View conversation
|
✅ Review complete. This review was performed through OpenHands Cloud Automation. You can log in and view the conversation here. |
all-hands-bot
left a comment
There was a problem hiding this comment.
🔴 Needs improvement — The overall release-automation shape is reasonable, and the earlier secret-name/timeout feedback has been addressed. But the new merge-driven path will fail before publishing because the release PR now commits the target package version while the publish workflows still call npm version with that same version.
[CRITICAL ISSUES]
- [.github/workflows/release.yml, line 58] Release correctness:
prepare-release.ymlcommitspackage.json/package-lock.jsonat the target version. When the tag from that merge is published,npm version "$TARGET_VERSION" --no-git-tag-versionruns against a package that is already atTARGET_VERSION, and npm exits withnpm error Version not changed(verified in a temp copy of this package).npm-publish.ymlhas the same version-setting command, so both npm and GitHub Packages publishing will fail. Make the publish jobs idempotent: skipnpm versionwhennode -p "require('./package.json').version"already equals the target, or use--allow-same-version, then keep the existing validation step.
[IMPROVEMENT OPPORTUNITIES]
- [PUBLISHING.md] Stale workflow descriptions: The final “Workflow Files” section still describes
npm-publish.ymlandrelease.ymlas tag-triggered workflows, and still saysrelease.ymlcreates the GitHub Release. That contradicts the new merge-driven flow and should be updated once the publish-path fix lands.
[TESTING GAPS]
- [PR description] No dry-run evidence for the publish path: CI passing proves the repo still builds, but these new release jobs are not exercised by PR checks. Add a small smoke-test transcript or dry-run evidence for the version-setting/publish path; the same-version
npm versionfailure above is exactly the kind of issue such evidence would catch.
[RISK ASSESSMENT]
- [Overall PR]
⚠️ Risk Assessment: 🔴 HIGH
This replaces the repository’s release mechanism, touches package publishing, workflow dispatch, secrets/PAT usage, npm trusted publishing, GitHub Packages publishing, and cross-repo PR automation. The blast radius is the entire release process, and there is a verified blocker in the first publish path. Recommendation: Do not auto-merge. Request a maintainer to validate a dry-run of the fixedrel-X.Y.Zflow through both publish workflows before relying on it for a real release.
VERDICT:
❌ Needs rework: Fix the publish workflows’ same-version handling before merging.
KEY INSIGHT:
The new release PR correctly makes the version bump reviewable, but the publish jobs still assume the old tag-only flow where the checked-out package version was not already the release version.
Improve this review? If any feedback above seems incorrect or irrelevant to this repository, you can teach the reviewer to do better:
- Add a
.agents/skills/custom-codereview-guide.mdfile to your branch (or edit it if one already exists) with the/codereviewtrigger and the context the reviewer is missing (e.g., "Security concerns about X do not apply here because Y"). See the customization docs for the required frontmatter format.- Re-request a review - the reviewer reads guidelines from the PR branch, so your changes take effect immediately.
- When your PR is merged, the guideline file goes through normal code review by repository maintainers.
Resolve with AI? Install the iterate skill in your agent and run
/iterateto automatically drive this PR through CI, review, and QA until it's merge-ready.Was this review helpful? React with 👍 or 👎 to give feedback.
This review was generated by an AI agent (OpenHands) on behalf of the user through OpenHands Automation. View conversation
|
@OpenHands address the comments |
|
I'm on it! VascoSch92 can track my progress at all-hands.dev |
Co-authored-by: openhands <openhands@all-hands.dev>
|
@VascoSch92 addressed the review comments.
Validation run locally:
This comment was generated by an AI agent (OpenHands) on behalf of the requester. |
|
✅ Review complete. This review was performed through OpenHands Cloud Automation. You can log in and view the conversation here. |
all-hands-bot
left a comment
There was a problem hiding this comment.
🟢 Good taste — The merge-driven release flow is well-structured, and the prior publish idempotency issue is fixed. The workflows keep the risky parts bounded with explicit dispatch, job timeouts, target-version validation, documented recovery paths, and green CI.
[RISK ASSESSMENT]
- [Overall PR]
⚠️ Risk Assessment: 🟡 MEDIUM
This changes the repository release mechanism and both package publishing paths, so the operational blast radius is meaningful. The implementation is constrained, though: release creation only follows mergedrel-*PRs, both publish workflows validate the target version, the downstream bump waits for npm availability, existing review blockers are resolved, and the PR now includes smoke-test evidence for the version-setting failure mode. The first real release should still be watched by a maintainer.
VERDICT:
✅ Worth merging: Core release automation is sound, previously raised blockers have been addressed, and checks are green.
KEY INSIGHT:
Moving the version bump into a reviewed release PR makes the release artifact source more auditable while explicit workflow dispatch handles the GITHUB_TOKEN release-event limitation.
This review was generated by an AI agent (OpenHands) on behalf of the user through OpenHands Automation. View conversation
There was a problem hiding this comment.
@VascoSch92 I wonder if it’s best:
- to use OPENHANDS_BOT_GITHUB_TYPESCRIPT_CLIENT for this repo
- to use the OPENHANDS_PUBLIC-something token that other public Open Source repos are using
At this time, the reason why Simon set the second to public repos is to limit potential damage: the token with PUBLIC in the name must not be used on private repos or have any perms on private repos.
In theory, a new one here is even better: its blast radius would be limited to this repo. On the other hand, if it’s per repo (and it is, in repo settings), then GitHub has more limited perms for it, and refreshing it in the future means running around repo by repo. WDYT?
I don't have preferences. What I was thinking was to have the minimal token that accomplish the task. For instance, the token has minimal scope and can access just public repos (I cannot scope just to this repo and agent-canvas :-() |
|
Can we start standardizing on https://github.com/OpenHands/release-actions so that the release process looks roughly the same across all of our repos? I'm aware that there are some extra features baked into this release and the release of We maintain many versioned artifacts and it's confusing to have a different release process across all of them. |
Replace the SDK-style merge-driven release front end with release-please, using OpenHands' centralized reusable workflows (OpenHands/release-actions). - add pr.yml (conventional PR-title lint + type: labels) and release.yml (release-please release line), both calling release-actions @main - add release-please state: release-please-config.json (release-type node, include-component-in-tag false so tags stay vX.Y.Z), seeded .release-please-manifest.json (1.24.2), and .github/release.yml notes categories - remove prepare-release.yml, create-release.yml and version-bump-prs.yml (release-please now cuts the release; the downstream agent-canvas bump is dropped, which also drops the OPENHANDS_BOT_GITHUB_TYPESCRIPT_CLIENT PAT) - fold the GitHub Packages publisher into publish-github-packages.yml (release: published + manual), freeing release.yml for the release-please caller; drop the version-bump dispatch + actions: write from npm-publish.yml - update README-RELEASE.md, AGENTS.md and PUBLISHING.md for the new flow
The manifest was seeded at 1.24.2 (the stale package.json version), but the actual latest release is 1.26.0 (npm `latest`, newest `vX.Y.Z` tag, GitHub Latest release). Seeding below the newest existing tag would make release-please compute a next version that already exists (e.g. v1.25.0/v1.26.0) and collide on tag/release creation. - .release-please-manifest.json -> 1.26.0 (matches the newest tag) - package.json + package-lock.json -> 1.26.0; main had been stale at 1.24.2 since the old tag-driven flow set the published version from the tag name without committing it back - README-RELEASE.md: note the seed matches npm `latest` / newest tag
jlav
left a comment
There was a problem hiding this comment.
Thanks for the change @VascoSch92!
It looks good to me, just left one minor comment. I would recommend, following merging this PR, that you have an agent look through any new commits since 1.26.0 and apply the correct type: label (like type: fix, type: feat, etc.) to each PR so that those PRs are categorized correctly in the release notes.
After this is merged in, the release actions will enforce conventional PR titles so that labels will be applied automatically.
| echo "✓ Version $PACKAGE_VERSION matches target" | ||
|
|
||
| - name: Publish to npm with provenance | ||
| run: npm publish --access public --provenance --tag latest |
There was a problem hiding this comment.
The --latest flag should only be applied if the published semver is the newest.
The release-please setup supports back-porting bug fixes using release branches, so it's possible to cut a release that isn't the latest.
|
🚀 Released in v1.27.0. |
Summary
Drives releases with release-please via OpenHands' centralized reusable workflows in
OpenHands/release-actions, replacing the earlier SDK-style "dispatch a version → merge arel-X.Y.ZPR" flow. The version is now derived from Conventional-Commit PR titles — nobody picks a version, pushes tags, or drafts releases by hand.What this is
release-actionsonly provides the release-cut front end (lint/label PR titles → maintain a release PR → on merge create the GitHub Release + tag + bump version files). It does not publish. So this PR keeps the existing publish back end and swaps only the front end:Added (call
release-actions@main)pr.yml→pr-title.yml@main— Conventional-Commit title lint +type:labels (pull_request_target, nosecrets: inherit).release.yml→release-please.yml@main— release-please release line on push tomain(secrets: inheritfor the org App token).Added (release-please state)
release-please-config.json—release-type: node(bumpspackage.json+package-lock.json);include-component-in-tag: falsekeeps tags asvX.Y.Z..release-please-manifest.json— seeded{ \".\": \"1.24.2\" }(current version)..github/release.yml— release-notes categories, grouped bytype:labels.Removed
prepare-release.yml,create-release.yml— release-please now opens the release PR and creates the Release.version-bump-prs.yml— the downstreamagent-canvasbump is dropped (per decision), which also drops the need for theOPENHANDS_BOT_GITHUB_TYPESCRIPT_CLIENTPAT.Edited
publish-github-packages.yml— folds in the oldrelease.ymlGitHub-Packages job; now triggers onrelease: published(+workflow_dispatch), freeing therelease.ymlfilename for the release-please caller.npm-publish.yml— unchanged publish path; dropped the version-bump dispatch step and itsactions: writepermission.README-RELEASE.md,AGENTS.md,PUBLISHING.md— rewritten for the release-please flow.Why the publish jobs still fire
release-please authors the Release with the org GitHub App token, not
GITHUB_TOKEN, so therelease: publishedevent is delivered andnpm-publish.yml/publish-github-packages.ymlrun. (A release created byGITHUB_TOKENwould be suppressed by GitHub's recursion guard.)RELEASE_APP_ID/RELEASE_APP_PRIVATE_KEY— already configured as org-level secrets and inherited org-wide; nothing to create.PR_TITLEmust be enabled so release-please reads each PR title as the commit:Behavioral change
Every PR title must now be Conventional Commits (
feat:/fix:/…), and the repo must squash-merge. The customrelease-note-requiredpreamble from the oldcreate-release.ymlis gone — notes come from the.github/release.ymlcategories instead.Validation