Why announcing is different from everything else colophon does¶
Colophon's verbs are safe to run twice. announce is not, and that is not an
oversight — it is a property of the thing being done, and the design says so
rather than hiding it.
Everything else has an answer for a second run¶
A release that already exists is reported, not created again. A tag that already points at the commit is left alone. A release whose assets are incomplete gains the missing ones and nothing else. A stranded draft is finished rather than duplicated. Run any of it twice and the second run changes nothing.
That is not luck. Each of those is a fact colophon can go and read before it acts: the forge will say whether a release exists, whether a tag is there and where it points, which assets are attached. Idempotence is cheap when the world can be asked what it already contains.
Even apply, which writes comments to issues, gets it: each comment carries
an idempotency key, and the forge finds the existing comment rather than
posting a second one. That guarantee is the forge's, not colophon's.
Colophon asks for it and the provider honours it.
An announcement cannot be read back¶
A message posted to a channel through a webhook leaves nothing colophon can query. There is no "has this been announced" call, no key the platform honours, no id to look for. Discord will happily accept the same embed a hundred times and show it a hundred times.
So the choice is between two honest positions and one dishonest one:
- Say it happens at least once, and let a retried job announce again.
- Keep a record — somewhere durable that says "this release was announced to this adapter" — and maintain it forever.
- Imply it happens once, and be wrong the first time somebody retries a job.
Colophon takes the first.
Why not keep a record¶
Because the record is a second source of truth about the world, and it can be wrong in both directions.
If it says an announcement went out and it did not — the write succeeded and the webhook call did not — then nobody is told, and the record is the reason nobody notices. If it says one did not and it did, the announcement repeats anyway. Every place it could live has a cost: a release description is regenerated, a git note needs a push, a file in the repository is a commit per release, a forge label is forge-specific.
All of that to avoid a duplicate message in a chat channel, which is a cost a person absorbs in the time it takes to read it. The cure is worse than the disease, and the disease is mild.
An adapter that CAN tell, does¶
At-least-once is the contract, not a ceiling. Where a medium can be read, the
adapter reads it: a blog post either exists at that URL or it does not, and a
mail service may honour a per-message key. Those adapters report unchanged
rather than announced, and colophon shows the difference.
What is refused is a uniform promise. The guarantee varies by adapter because the world varies by adapter, and saying otherwise would mean the strongest claim colophon could make about the weakest medium.
What this buys¶
No state to keep correct, no migration when the record's format changes, and no class of bug where colophon believes something about the world that is not true. The failure mode is a duplicate message, visible to everyone, fixable by ignoring it.
Compare that with the failure mode of the alternative: silence, caused by bookkeeping, discovered when somebody asks why they never heard about a release.
See also¶
colophon announce— the verb- Announcing a release — the configuration
- Why a release is published complete — the same question asked of assets, where the answer is to check first