Skip to content

rainix-autopublish runs no test before a Soldeer publish, so a red suite still ships an immutable revision #322

Description

@thedavidmeister

rainix-autopublish's only test step is Cargo test:

      - name: Cargo test
        if: ${{ (inputs.crates != '' || inputs.crate != '') && (steps.cargo.outputs.changed == 'true' || steps.npm.outputs.changed == 'true' || steps.soldeer.outputs.changed == 'true') }}

A Soldeer-only caller passes neither crates nor crate, so the condition is false and no test runs at all before forge soldeer push. rain.solmem's package-release.yaml passes only soldeer-package: rain-solmem.

Nothing else covers the gap on the caller's side either. package-release.yaml and the caller's rainix.yaml both fire on push: branches: [main], so the publish runs concurrently with the test suite, not after it. A merge that breaks forge test publishes an immutable Soldeer revision and creates the GitHub Release before the red check has a verdict.

Evidence

rain.solmem has published 12 revisions this way (sol-v0.1.4 .. sol-v0.1.15, 2026-07-25 to 2026-08-18). No publishing run executed forge test. Several of those revisions changed memory-writing assembly:

  • 0.1.4unsafeExtend out-of-bounds write fix (both array libraries)
  • 0.1.10 — unchecked mul(_, 0x20) word-scaling guards, matrix flatten allocation fix
  • 0.1.13unsafeExtend(a, a) rerouted through the allocating path

Why gating is safe here, unlike #303

#303 argues against a full-suite gate in rainix-tag-release because a tag is spent once used, so a flaky test burns a release. rainix-autopublish has the opposite failure mode: on a failed run nothing is published, [package].version stays in-dev, and the next push to main retries the same version for free. A red gate costs a rerun, not a burned version.

Proposed fix

A Soldeer test step mirroring the Cargo one, before Publish to Soldeer:

      - name: Sol test
        if: ${{ inputs.soldeer-package != '' && steps.soldeer.outputs.changed == 'true' }}
        run: nix develop github:rainlanguage/rainix/${{ env.RAINIX_SHA }}#sol-shell -c forge test

Gated on changed == 'true' for the same reason the Cargo step is: an unchanged push short-circuits without paying for the suite.

Spun out of rainlanguage/rain.solmem#87, which is fixed in-repo only as far as the changelog artifact goes. This half is shared CI and belongs here.

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