Skip to content

feat(NO-TASK): Add a reusable workflow to sync release-please config - #152

Open
aaronware wants to merge 1 commit into
mainfrom
feat/NO-TASK/sync-release-please-config
Open

feat(NO-TASK): Add a reusable workflow to sync release-please config#152
aaronware wants to merge 1 commit into
mainfrom
feat/NO-TASK/sync-release-please-config

Conversation

@aaronware

Copy link
Copy Markdown
Contributor

Adds a reusable workflow that regenerates a consumer's committed release-please-config.json when Renovate bumps the shared standard.

Why this exists

release-please has no extends, and it reads its config through the GitHub API off the target branchgithub.getFileJson(configFile, branch) — not from the workflow's checkout. So a shared standard can neither be referenced nor generated at release time. The JSON has to be committed in every repo that uses it.

Across ~28 repos, that would mean a hand-made pull request each time the standard changes.

How it avoids that

@linchpinagency/release-please-config ships the standard on npm, so the version bump becomes the carrier:

release a new version of the standard
        ↓
Renovate bumps the devDependency into maintenance/YYYY-MM
        ↓
this workflow regenerates the committed JSON onto that same PR
        ↓
auto-approve-maintenance → only allow-listed files → approves
auto-merge-maintenance   → renovate[bot] + maintenance branch → squash merge

release-please-config.json is already on both maintenance allow-lists, so neither of those workflows needed changing.

Design notes worth reviewing

npx --no-install is load-bearing. It makes the run fail rather than silently fetch from the registry, so regeneration can only ever use the version the lockfile just pinned. The lockfile stays the source of truth and the consumer's check job is deterministic — never @latest.

Two guards live in the workflow, not the caller, because it combines a pull_request trigger with a PAT and a checkout of the head ref:

  • same-repository pull requests only, so a fork PR can never reach that checkout
  • the expected bot only (allowed_actor, default renovate[bot])

Wiring this up loosely from a caller therefore can't turn it into an arbitrary-code path.

GH_BOT_TOKEN rather than github.token, because a push made with github.token does not trigger workflow runs — the PR's own checks would never re-run against the commit this job adds.

It commits as renovate[bot] so the PR keeps one author and auto-merge-maintenance's author == renovate[bot] guard still holds.

git add is scoped to the one file. If a future sync ever touched anything else, it would be left uncommitted rather than swept into a PR that auto-merges.

Rebase, not merge, before pushing — Renovate force-pushes its branches, and a merge commit would confuse its next update. concurrency serialises runs per PR and never cancels mid-flight, so a run can't be killed between its commit and its push.

Independent of #149

The README section is written against main, not against the check-overrides content, so this does not depend on #149 merging.

Not yet released

Needs a v4 tag move before consumers referencing @v4 pick it up.

release-please has no `extends`, and it reads its config through the GitHub API
off the target branch - github.getFileJson(configFile, branch) - not from the
workflow checkout. So a shared standard can neither be referenced nor generated
at release time: the JSON has to be committed in every repo that uses it.

Across ~30 repos that would mean a hand-made pull request each time the standard
changes. This makes the npm version the carrier instead. Renovate bumps
@linchpinagency/release-please-config, this workflow regenerates the committed
JSON onto that same pull request, and the existing auto-approve-maintenance /
auto-merge-maintenance path takes it from there - release-please-config.json is
already on both allow-lists, so none of that needed changing.

Regeneration runs the version the pull request just installed, via
`npx --no-install`, never @latest. The lockfile stays the source of truth and the
`check` job in each consumer is deterministic.

Two guards live in the workflow rather than the caller, because it combines a
pull_request trigger with a PAT and a checkout of the head ref: same-repository
pull requests only, and the expected bot only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant