Skip to content
This repository was archived by the owner on Sep 7, 2026. It is now read-only.

ci: release automation via release-please (release-actions) - #230

Merged
VascoSch92 merged 10 commits into
mainfrom
release-automation
Jun 24, 2026
Merged

VascoSch92 merged 10 commits into
mainfrom
release-automation

Conversation

@VascoSch92

@VascoSch92 VascoSch92 commented Jun 23, 2026 •

Copy link
Copy Markdown
Member

Summary

Drives releases with release-please via OpenHands' centralized reusable workflows in OpenHands/release-actions, replacing the earlier SDK-style "dispatch a version → merge a rel-X.Y.Z PR" flow. The version is now derived from Conventional-Commit PR titles — nobody picks a version, pushes tags, or drafts releases by hand.

PR (conventional title) ─▶ pr.yml (lint + type: label)
        │ merge
push to main ─▶ release.yml (release-please) ─▶ "release PR" ─(merge)─▶ Release + tag vX.Y.Z
                                                                              │ release: published
                                                              ┌───────────────┴───────────────┐
                                                       npm-publish.yml          publish-github-packages.yml
                                                       (npmjs.org)              (GitHub Packages)

What this is

release-actions only 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, no secrets: inherit).
  • release.yml → release-please.yml@main — release-please release line on push to main (secrets: inherit for the org App token).

Added (release-please state)

  • release-please-config.json — release-type: node (bumps package.json + package-lock.json); include-component-in-tag: false keeps tags as vX.Y.Z.
  • .release-please-manifest.json — seeded { \".\": \"1.24.2\" } (current version).
  • .github/release.yml — release-notes categories, grouped by type: labels.

Removed

  • prepare-release.yml, create-release.yml — release-please now opens the release PR and creates the Release.
  • version-bump-prs.yml — the downstream agent-canvas bump is dropped (per decision), which also drops the need for the OPENHANDS_BOT_GITHUB_TYPESCRIPT_CLIENT PAT.

Edited

  • publish-github-packages.yml — folds in the old release.yml GitHub-Packages job; now triggers on release: published (+ workflow_dispatch), freeing the release.yml filename for the release-please caller.
  • npm-publish.yml — unchanged publish path; dropped the version-bump dispatch step and its actions: write permission.
  • 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 the release: published event is delivered and npm-publish.yml / publish-github-packages.yml run. (A release created by GITHUB_TOKEN would be suppressed by GitHub's recursion guard.)

⚠️ One-time prerequisites

  • RELEASE_APP_ID / RELEASE_APP_PRIVATE_KEY — already configured as org-level secrets and inherited org-wide; nothing to create.
  • Squash-merge with PR_TITLE must be enabled so release-please reads each PR title as the commit:
    gh api -X PATCH repos/OpenHands/typescript-client \
      -f squash_merge_commit_title=PR_TITLE -f squash_merge_commit_message=COMMIT_MESSAGES \
      -F allow_squash_merge=true -F allow_merge_commit=false -F allow_rebase_merge=false \
      -F delete_branch_on_merge=true

Behavioral change

Every PR title must now be Conventional Commits (feat:/fix:/…), and the repo must squash-merge. The custom release-note-required preamble from the old create-release.yml is gone — notes come from the .github/release.yml categories instead.

Validation

  • All workflow YAML and the two release-please JSON files parse.
  • No dangling references to the removed workflows / PAT remain in the repo.

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).
@github-actions

github-actions Bot commented Jun 23, 2026 •

Copy link
Copy Markdown
Contributor

Endpoint audit

❌ 8 off-contract call(s) — not on the agent-server · classifiers: cloud

Category Count
❌ Off-contract (not on agent-server) 8
  ⛔ no known backend 7
  ↗️ served by cloud 1
➕ Missing API (agent-server has, client lacks) 9
agent-server endpoints 104
client endpoints 101

❌ Not on agent-server (gated, 8)

⛔ (no known backend) — served by no backend we can see (7)

  • DELETE /api/meta-profiles/{}
  • GET /api/meta-profiles
  • GET /api/meta-profiles/{}
  • POST /api/cloud-proxy
  • POST /api/meta-profiles/{}
  • POST /api/meta-profiles/{}/activate
  • POST /api/skills/installed/{}/update

↗️ served by cloud (1)

  • GET /api/shared-events/search

➕ Missing API — agent-server exposes it, client does not implement (9)

  • GET /
  • GET /api/bash/bash_events
  • GET /api/conversations
  • GET /api/conversations/{}/events
  • GET /api/conversations/{}/workspace
  • GET /api/conversations/{}/workspace/{}
  • GET /api/init
  • POST /api/init
  • POST /api/skills/installed/{}/refresh

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.
@all-hands-bot
all-hands-bot self-requested a review June 24, 2026 08:31
@all-hands-bot
all-hands-bot marked this pull request as ready for review June 24, 2026 08:31

all-hands-bot commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

✅ Review complete.

This review was performed through OpenHands Cloud Automation. You can log in and view the conversation here.

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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 needs OPENHANDS_BOT_GITHUB_PAT_PUBLIC, but every workflow and every documentation artifact added by this PR uses OPENHANDS_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 use OPENHANDS_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). Without timeout-minutes on 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 adding timeout-minutes: 30 to 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.yml against a test branch, verify the create-release.yml condition logic) so reviewers can assess confidence.

[RISK ASSESSMENT]

  • [Overall PR] ⚠️ Risk Assessment: 🟡 MEDIUM
    This is a complete replacement of the existing push: tags release flow — the old trigger is fully removed from both publish workflows. Recovery via workflow_dispatch exists, and the PR's own open question acknowledges the lack of a push-tags fallback. The merge-driven flow is proven in software-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:

  1. Add a .agents/skills/custom-codereview-guide.md file to your branch (or edit it if one already exists) with the /codereview trigger and the context the reviewer is missing. See the customization docs for the required frontmatter format.
  2. Re-request a review - the reviewer reads guidelines from the PR branch, so your changes take effect immediately.
  3. 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 /iterate to 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

Comment thread .github/workflows/version-bump-prs.yml Outdated

all-hands-bot commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

✅ Review complete.

This review was performed through OpenHands Cloud Automation. You can log in and view the conversation here.

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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.yml commits package.json/package-lock.json at the target version. When the tag from that merge is published, npm version "$TARGET_VERSION" --no-git-tag-version runs against a package that is already at TARGET_VERSION, and npm exits with npm error Version not changed (verified in a temp copy of this package). npm-publish.yml has the same version-setting command, so both npm and GitHub Packages publishing will fail. Make the publish jobs idempotent: skip npm version when node -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.yml and release.yml as tag-triggered workflows, and still says release.yml creates 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 version failure 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 fixed rel-X.Y.Z flow 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:

  1. Add a .agents/skills/custom-codereview-guide.md file to your branch (or edit it if one already exists) with the /codereview trigger 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.
  2. Re-request a review - the reviewer reads guidelines from the PR branch, so your changes take effect immediately.
  3. 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 /iterate to 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

Comment thread .github/workflows/release.yml Outdated
@VascoSch92

Copy link
Copy Markdown
Member Author

@OpenHands address the comments

@openhands-ai

openhands-ai Bot commented Jun 24, 2026

Copy link
Copy Markdown

I'm on it! VascoSch92 can track my progress at all-hands.dev

Co-authored-by: openhands <openhands@all-hands.dev>

Copy link
Copy Markdown
Member Author

@VascoSch92 addressed the review comments.

  • Pushed 3fc6400 to make both publish workflows idempotent when the release PR/tag already has package.json at the target version. They now skip npm version when the current version matches and keep validation of the final package version.
  • Updated PUBLISHING.md so the workflow descriptions no longer describe the old tag-triggered/GitHub-Release-creating path.
  • Updated the PR description’s Validation section with publish-path smoke-test evidence.
  • Resolved the review threads for the publish idempotency issue and the already-addressed version-bump timeout.

Validation run locally:

  • Parsed the five release workflows with PyYAML.
  • Smoke-tested the same-version path (1.24.2) to confirm it skips npm version and validates successfully.
  • Smoke-tested a changed-version path (9.9.9) to confirm npm version --no-git-tag-version still runs when needed.
  • Checked touched docs/workflows for stale tag-triggered wording.

This comment was generated by an AI agent (OpenHands) on behalf of the requester.

@VascoSch92
VascoSch92 requested a review from all-hands-bot June 24, 2026 09:23

all-hands-bot commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

✅ Review complete.

This review was performed through OpenHands Cloud Automation. You can log in and view the conversation here.

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 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 merged rel-* 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

@OpenHands OpenHands deleted a comment from openhands-ai Bot Jun 24, 2026

@enyst enyst left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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?

@VascoSch92

Copy link
Copy Markdown
Member Author

@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 :-()

@jlav

jlav commented Jun 24, 2026

Copy link
Copy Markdown
Member

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 software-agent-sdk, but where those gaps exist I'd like to see them contributed back as features on https://github.com/OpenHands/release-actions so we can more easily share them.

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
@VascoSch92 VascoSch92 changed the title ci: merge-driven release automation (SDK-style) ci: release automation via release-please (release-actions) Jun 24, 2026
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 jlav left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@VascoSch92
VascoSch92 merged commit fb24376 into main Jun 24, 2026
9 checks passed
@VascoSch92 VascoSch92 added the type: ci CI configuration changes label Jun 24, 2026
@openhands-release-bot openhands-release-bot Bot added the released: v1.27.0 Shipped in v1.27.0 label Jun 25, 2026
@openhands-release-bot

Copy link
Copy Markdown
Contributor

🚀 Released in v1.27.0.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

released: v1.27.0 Shipped in v1.27.0 type: ci CI configuration changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants