Skip to content

Add release automation and Renovate auto-merge - #178

Open
aponcedeleonch wants to merge 3 commits into
mainfrom
release-automation-setup
Open

Add release automation and Renovate auto-merge#178
aponcedeleonch wants to merge 3 commits into
mainfrom
release-automation-setup

Conversation

@aponcedeleonch

@aponcedeleonch aponcedeleonch commented Jul 22, 2026

Copy link
Copy Markdown
Member

What and why

toolhive-core has no release automation today: tags are hand-pushed. This adds the releaseo-driven release flow that stacklok/toolhive already uses, adapted for toolhive-core, plus daily release-checks and auto-merge of Renovate dependency bumps gated on green CI.

This is the first upstream hop of the CVE remediation cascade tracked in stacklok/stacklok-enterprise-platform#2190 (core → catalog → toolhive → registry-server → platform). The design (labels, classification rules, trust boundary) comes from that issue.

How auto-merge works here

The repo ruleset requires 1 approval, so GitHub-native auto-merge (or Renovate's) can never complete on its own: a bot cannot approve its own PR. Instead:

  • Renovate PRs carry the automerge label (from renovate.json).
  • approve-automerge.yml runs on CI completion and, for Renovate PRs whose checks are green, submits an approving review as a separate approver app identity, which satisfies the "require 1 approval" rule, then enables GitHub auto-merge.
  • Required status checks still gate the actual merge, so a red PR (including a breaking major bump) never merges.

The approver is scoped to Renovate PRs only. It never approves human PRs, release PRs, or any other bot's PRs.

Files

VERSION (new)

  • Seeded to 0.0.26, the current latest release tag. Single source of truth; releaseo reads and writes it.

renovate.json (changed)

  • Adds the automerge label alongside dependencies (the eligibility signal the approver checks) and sets minimumReleaseAge: "0".
  • Does not enable Renovate's own auto-merge, since the ruleset's required approval would block it anyway. Approval + merge are handled by approve-automerge.yml.

.github/workflows/approve-automerge.yml (new)

  • Triggers on workflow_run (completed) for CI. On success and for a pull_request run, resolves the PR from the head SHA and approves it iff it is authored by Renovate, carries automerge, and the head SHA's full check set is green. Then enables GitHub auto-merge (squash). Uses a distinct approver app token so the approval counts toward the ruleset.

.github/workflows/create-release-pr.yml (new)

  • Manual workflow_dispatch with bump_type (patch/minor/major, default patch), for the minor/major bumps that stay behind a human. Mirrors toolhive's version but strips all Helm chart / values / helm-docs steps; bumps only VERSION.

.github/workflows/create-release-tag.yml (new)

  • Triggers on push to main touching VERSION (a release PR merged). Verifies the commit came from a release PR (robust to squash and merge-commit), then creates the tag and GitHub Release together in one gh release create. That ordering matters because the existing release.yml triggers on push: tags and runs gh release upload, which needs the Release to already exist. release.yml is left untouched.

.github/workflows/release-check.yml (new)

  • Daily cron (06:17 UTC) plus manual trigger. Opens or updates exactly one release PR for commits merged since the last tag. Idempotent: it reuses the single open release/* PR if one exists and only creates a new one when none is open, so it never stacks.
  • Classification: dependency-only iff every PR merged since the last tag's timestamp was authored by an automation identity (Renovate, login app/renovate) and carries the dependencies label. It lists merged PRs via the API rather than parsing commits, so squash vs merge-commit doesn't matter.
    • dependency-only: applies automerge, enables GitHub auto-merge. Merges once checks are green and the release PR has one approving review (see note below).
    • functional (any human-authored or unlabeled PR): applies needs-human, no auto-merge, and the PR body lists which PRs tipped it functional.
    • fail-safe: if commits exist but no merged PRs can be listed, it is treated as functional. Never auto-releases when uncertain.

Note: release PRs need a human approval

Because the approver is scoped to Renovate PRs only, dependency-only release PRs have auto-merge enabled but still need one human approving review before they merge (required checks still gate them). Renovate dependency PRs are fully hands-off; the release PR that ships them is the one human checkpoint per release. If you'd prefer the approver to also cover release PRs (identified by the release-bot author + automerge label), that's a small change, say the word.

Verification

  • actionlint passes on all four new workflows.
  • renovate-config-validator passes on renovate.json.
  • Classification jq unit-checked against fixtures: all-Renovate-with-dependencies -> dependency-only; one human PR -> functional (and names it); bot PR missing the label -> functional; nothing-since-tag -> functional fail-safe.
  • Approver eligibility + green-check dry-run in bash: Renovate + label + green -> approve; human / release-bot / unlabeled / pending / failing -> skip.
  • The release-check PR-body block is marker-delimited and rewritten each run, so daily runs don't accumulate blocks.

Out of scope, needs an admin (flagged, not done here)

Repo/org settings, not files, so not in this diff:

  • vars.RELEASE_APP_CLIENT_ID + secrets.RELEASE_APP_PRIVATE_KEY (release-bot app) must exist in toolhive-core. Without them the release workflows fail at the token step.
  • vars.APPROVER_APP_CLIENT_ID + secrets.APPROVER_APP_PRIVATE_KEY (approver app) must exist. This app must be a DISTINCT identity from Renovate (a bot can't approve its own PR), with Pull requests: write + Contents: read.
  • The automerge / needs-human labels: the daily workflow creates them idempotently; Renovate applies automerge from its config.

Tracking issue: stacklok/stacklok-enterprise-platform#2190

@jhrozek

jhrozek commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

@aponcedeleonch could you rebase so we get the grype fix?

aponcedeleonch and others added 3 commits July 28, 2026 13:53
Mirrors toolhive's releaseo-driven release flow, adapted for toolhive-core
(VERSION-only bumps, no Helm chart steps), and turns on Renovate auto-merge
gated on green required checks. First upstream hop of the CVE remediation
cascade (stacklok-enterprise-platform#2190).

- VERSION: seed to 0.0.26 (current latest tag)
- renovate.json: automerge + platformAutomerge, minimumReleaseAge 0,
  add the `automerge` approver-app label
- create-release-pr.yml: manual patch/minor/major release PR (VERSION only)
- create-release-tag.yml: tag + Release on VERSION change to main
- release-check.yml: daily, idempotent single release PR, classifies
  dependency-only vs functional and gates functional on a human

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The repo ruleset requires 1 approval, so Renovate's own auto-merge can never
complete (a bot can't approve its own PR). Drop the auto-merge behavior from
renovate.json and add an approve-automerge workflow that supplies the approval
from a separate app identity.

- renovate.json: remove automerge/automergeType/platformAutomerge; keep the
  `automerge` label + minimumReleaseAge 0
- approve-automerge.yml: on CI workflow_run success, approve eligible bot PRs
  (automerge label + bot author, not the approver's own PR) once the head SHA's
  full check set is green, then enable GitHub auto-merge (squash)
- release-check.yml: wording now refers to the approve-automerge workflow

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Gate eligibility on the PR being authored by Renovate (not just any bot), so the
workflow never auto-approves human PRs, release PRs, or other bots' PRs. Update
release-check wording: dependency-only release PRs now need a maintainer's
approval (the approver only covers Renovate PRs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@aponcedeleonch
aponcedeleonch force-pushed the release-automation-setup branch from 210c569 to 3f1037f Compare July 28, 2026 10:53
@aponcedeleonch

Copy link
Copy Markdown
Member Author

@jhrozek done! thanks for the heads up. For this to work we need 2 new github apps. Sorry, I dropped the ball and got distracted. I will try to put in some hours for getting this to work

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants