Skip to content

ci(release): standardize on synth pattern — sums + cosign + SLSA + SBOM#143

Open
avrabe wants to merge 1 commit into
mainfrom
chore/standardize-release-yml
Open

ci(release): standardize on synth pattern — sums + cosign + SLSA + SBOM#143
avrabe wants to merge 1 commit into
mainfrom
chore/standardize-release-yml

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 24, 2026

Summary

LOOM has not shipped any release binaries since v0.5.0 — every Release workflow run since at least v1.0.2 fails at the Build WASM (wasm32-wasip2) step (rules_wasm_component pinned to v0.3.0), and the Create-Release job's needs: [build-native, build-wasm] short-circuits the upload. v0.9.0, v1.0.5, v1.1.0, v1.1.1 are all tagged with zero assets.

This rewrites .github/workflows/release.yml to adopt the pulseengine/synth reference pattern per the cross-repo release-artifact standardization brief.

Required asset set (per the brief)

Asset Purpose
loom-vX.Y.Z-<triple>.{tar.gz|zip} per-platform binary archive
loom-X.Y.Z.cdx.json CycloneDX SBOM (toolchain)
SHA256SUMS.txt sha256 of every other asset
SHA256SUMS.txt.sig cosign detached signature
SHA256SUMS.txt.pem Fulcio leaf certificate
SHA256SUMS.txt.cosign.bundle verifier-friendly bundle
build-env.txt rustc/cargo/cosign/runner versions

What changed

  • Drop the WASM build job. It's a release-blocker (broken since at least v1.0.2), the WASM binary isn't in the standard asset list, and the underlying rules_wasm_component@v0.3.0 pin is a separate concern.
  • Drop the OCI publish + OCI signing + custom-JSON SLSA path. The standard is GitHub-native SLSA attestation (actions/attest-build-provenance@v2) plus cosign-signed SHA256SUMS.txt. No OCI side-channel.
  • Drop per-file *.sha256 sidecars. Replaced by one signed SHA256SUMS.txt covering every asset (including the SBOM).
  • Trigger: release: publishedpush: tags: v*, so the workflow CREATES the release atomically with its assets, rather than racing an asset-less release page.
  • Phase 6 onward is verbatim from synth's release.yml; only the SBOM manifest path is adapted (loom-cli/Cargo.toml instead of crates/synth-cli/Cargo.toml).

Build matrix

x86_64-unknown-linux-gnu, x86_64-apple-darwin (on macos-14), aarch64-apple-darwin (on macos-latest), x86_64-pc-windows-msvc. aarch64-unknown-linux-gnu via cross is deferred — z3-sys cross-compile is untested in this repo.

Validation plan

After merge, dispatch the workflow against tag v1.1.1 (which currently has zero assets) to populate the standard asset set and verify the cosign + attestation paths work end-to-end:

gh workflow run release.yml -f tag=v1.1.1

Then verify the published assets:

cosign verify-blob \
  --certificate-identity-regexp \
    'https://github.com/pulseengine/loom/.github/workflows/release.yml@.*' \
  --certificate-oidc-issuer \
    'https://token.actions.githubusercontent.com' \
  --bundle SHA256SUMS.txt.cosign.bundle SHA256SUMS.txt
gh attestation verify loom-v1.1.1-x86_64-unknown-linux-gnu.tar.gz --repo pulseengine/loom

Test plan

  • Workflow file passes YAML parse (no gh workflow view errors)
  • Workflow run succeeds end-to-end (validated post-merge via workflow_dispatch against v1.1.1)
  • SHA256SUMS.txt.cosign.bundle verifies with the canonical one-liner above
  • gh attestation verify succeeds for every binary archive
  • Each release-asset name matches the brief's required format

LOOM has not shipped any release binaries since v0.5.0: every Release
workflow run since at least v1.0.2 has failed at the `Build WASM
(wasm32-wasip2)` step (rules_wasm_component pinned to v0.3.0, the
WASM build cannot move forward). The Create-Release job had
`needs: [build-native, build-wasm]`, so the failing WASM job
short-circuits the upload step and all native binaries get
discarded — v0.9.0 / v1.0.5 / v1.1.0 / v1.1.1 are tagged with zero
assets.

This rewrite adopts pulseengine/synth's release.yml as the reference
implementation (per the cross-repo standardization brief):

- Drop the WASM build job entirely (release-blocker; not in the
  standard asset list; rules_wasm_component pin issue is a separate
  concern).
- Drop the OCI publish + OCI signing + custom-JSON SLSA path. The
  standard set is the single signed SHA256SUMS plus GitHub-native
  SLSA attestation, no OCI side-channel.
- Drop per-file `*.sha256` sidecars — replaced by one signed
  SHA256SUMS.txt covering every asset (and the SBOM).
- Trigger switches from `release: published` to `push: tags: v*`
  so the workflow CREATES the release atomically with its assets,
  instead of racing a manually-created (asset-less) release page.

The artifact-generation block (Phase 6 onward) is copied verbatim
from pulseengine/synth/.github/workflows/release.yml — only the SBOM
manifest path is adapted (`loom-cli/Cargo.toml` instead of
`crates/synth-cli/Cargo.toml`).

Required assets per the brief, and only these:

- loom-vX.Y.Z-<triple>.{tar.gz|zip}    binary archives, per platform
- loom-X.Y.Z.cdx.json                  CycloneDX SBOM
- SHA256SUMS.txt                       sha256 of every other asset
- SHA256SUMS.txt.sig                   cosign detached signature
- SHA256SUMS.txt.pem                   Fulcio leaf certificate
- SHA256SUMS.txt.cosign.bundle         verifier-friendly bundle
- build-env.txt                        rustc/cargo/cosign/runner versions

Build matrix: x86_64-linux, x86_64-darwin (macos-14), aarch64-darwin
(macos-latest), x86_64-windows. aarch64-linux via `cross` deferred —
z3-sys cross-compile is untested in this repo.

Verification one-liner (to paste in release notes after first run):

  cosign verify-blob \
    --certificate-identity-regexp \
      'https://github.com/pulseengine/loom/.github/workflows/release.yml@.*' \
    --certificate-oidc-issuer \
      'https://token.actions.githubusercontent.com' \
    --bundle SHA256SUMS.txt.cosign.bundle SHA256SUMS.txt
  gh attestation verify loom-vX.Y.Z-<triple>.tar.gz --repo pulseengine/loom

Validation plan: after merge, dispatch the workflow against tag
v1.1.1 (which currently has zero assets) to populate it with the
standard asset set.

Trace: REQ-INFRA
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