Skip to content

rainix-autopublish has no concurrency group: concurrent merges race one version and can wedge a repo's releases #324

Description

@thedavidmeister

rainix-autopublish.yaml publishes a version and then pushes the version bump that makes the next run see a new version. Nothing serialises its runs, and no consumer declares a concurrency: group either — all eleven package-release.yaml callers have zero concurrency:

rain.solmem, rain.interpreter, rain.math.float, rain.erc4626.words, rain.flare,
rain.orderbook, rain.strings, rain.datacontract, rain.metadata, rain.erc20,
rain.lib.typecast

Two merges landing close together start two runs. Both check out their own pre-bump sha, both read the same [package].version, both compute changed=true, and both reach Publish to Soldeer with the same package~version. One wins; the loser fails.

This is live, not theoretical. rain.solmem, 2026-08-17:

The worse outcome has not landed yet but is unguarded. Tag and push fetches, replays onto origin/<ref> and runs git push origin HEAD with no retry. If that push loses to a concurrent push after Publish to Soldeer succeeded, main is left declaring a version that is already on the registry, and soldeer_gate's ahead-invariant (rainix-static/src/soldeer_gate.rs) then hard-errors on every subsequent run — that repo's releases are blocked until a human hand-bumps foundry.toml.

Proposed fix

A workflow-level group in the reusable itself, so all eleven consumers get it without eleven edits:

name: rainix-autopublish
concurrency:
  group: rainix-autopublish-${{ github.ref }}
  cancel-in-progress: false
on:
  workflow_call:

cancel-in-progress: false is the half that prevents the wedge — cancelling a run between Publish to Soldeer and Tag and push produces exactly the wedged state above. A literal group name, not ${{ github.workflow }} (which a called workflow inherits from its caller), avoids colliding with any group a caller declares.

Worth confirming on a real run that a workflow-level concurrency in a called workflow is honoured. GitHub's docs only imply it, via the warning against reusing the same group name in caller and called workflows.

Two things a concurrency group does not fix:

  1. A queued run still checks out its own event sha, so once the leader has bumped [package].version the follower's tree is stale and trips the ahead-invariant. That is a red run rather than a wedge, but it is red on the second of every burst.
  2. Tag and push still has no push-retry loop, which is the actual wedge mechanism. Serialising makes it far less likely to fire; it does not remove it.

rain.solmem has a caller-level group landed as a stopgap in rainlanguage/rain.solmem#138. Whatever PR lands the reusable-level fix here should delete that consumer-local block.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions