From 12f35504413dde2598c2e9089982e52e76f4d121 Mon Sep 17 00:00:00 2001 From: Mao Nakamoto <41178744+maonakamoto@users.noreply.github.com> Date: Sun, 16 Aug 2026 18:44:30 +0200 Subject: [PATCH] ci: make the release a reconciler, not a trigger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The self-releasing workflow I merged an hour ago would not have released anything, and the proof is in this repo: #16 merged to main and no publish run started. threadkit's identical change did fire — because I merged that one by hand with a user token. auto-merge merges with GITHUB_TOKEN, and a push made with that token starts no workflow. So `on: push: branches: [main]` silently does not fire for exactly the merges that matter here. This is the no-cascade rule already documented in CLAUDE.md, and I walked into it while writing the thing meant to remove manual steps. Two fixes, because one of them is a promise and the other is a mechanism: - auto-merge.yml carries REARM_WORKFLOWS, whose comment says "keep this in sync when a push-triggered workflow is added". I added one and did not. Now listed. - More importantly: publish.yml gains an hourly schedule. The question it asks — "is package.json's version on the registry?" — is idempotent, so asking it on a timer costs one `npm view` when there is nothing to do and repairs a missed release when there is. A hand-maintained list of workflows to re-arm is something to keep correct forever; a reconciler is correct by construction. This matches how deploys already work in the fleet: compare desired against actual and act on the difference, rather than trusting an event to arrive. Co-Authored-By: Claude Opus 5 --- .github/workflows/auto-merge.yml | 2 +- .github/workflows/publish.yml | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 4cab138..d79b3d1 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -50,5 +50,5 @@ jobs: # Everything that runs on push and therefore would NOT fire after a # merge made with the default GITHUB_TOKEN. Keep this in sync when a # push-triggered workflow is added. - REARM_WORKFLOWS: ci.yml + REARM_WORKFLOWS: ci.yml,publish.yml run: bash scripts/ci/auto-merge-sweep.sh diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 999f3aa..ca33121 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,6 +12,17 @@ on: push: branches: [main] tags: ['v*'] + # The reconciler, and the reason this is reliable. A merge made by auto-merge + # uses GITHUB_TOKEN, and a push with that token starts no workflow — so the + # push trigger above silently does not fire for exactly the merges that matter. + # auto-merge.yml re-arms a hand-maintained list of workflows, which is one more + # thing to keep in sync (it was already wrong once: publish.yml was missing). + # + # So the schedule asks the registry the same idempotent question on a timer: + # is package.json's version published? If a release was missed by any means, + # it goes out within the hour without anyone noticing it was missed. + schedule: + - cron: '17 * * * *' workflow_dispatch: jobs: