Skip to content

Commit b8ba479

Browse files
fix(release): restore release binaries — immutable-release draft flow + portable BSD sed (#641)
## Problem `v0.2.0` shipped **source-only** (regression from `v0.1.1`, which had `affinescript-linux-x64`, `affinescript-macos-x64`, `affinescript-macos-arm64`, `SHA256SUMS`). Downstream consumers on locked-down networks rely on the prebuilt binary (building from source needs opam + ~15 packages, blocked when `opam.ocaml.org` 403s), and the `v0.1.1` binary can't parse `v0.2.0`-only syntax — e.g. quandledb's `quandle_gui.affine` → `Parse error` (quandledb PR #60 had to pin `v0.1.1`). ## Root cause — two bugs, both confirmed from the failed v0.2.0 run ([26694097435](https://github.com/hyperpolymath/affinescript/actions/runs/26694097435)) 1. **Immutable releases.** `prepare` created a *published* release, then the build matrix uploaded assets to it. The repo enabled immutable releases between `v0.1.1` (`immutable:false`) and `v0.2.0` (`immutable:true`); immutable *published* releases reject asset uploads — the linux leg died with: ``` HTTP 422: Cannot upload assets to an immutable release. ``` 2. **BSD sed.** The version-bake step (added in v0.2.0) used `sed -i "s/…"`, which **BSD sed on the macOS runners** rejects (`sed: 1: "lib/version.ml": extra characters at the end of l command`) — so `macos-x64` and `macos-arm64` failed *before building anything*. ## Fix (`.github/workflows/release.yml` only) - **Draft → upload → publish:** create the release as a `--draft` (mutable), let the build legs upload binaries into it, and `gh release edit --draft=false --latest` **last** in the checksums job — so it seals atomically with all four assets attached, compatible with immutable releases. - **Portable in-place sed:** `sed -i.bak …` (accepted by both GNU and BSD sed) + remove the backups. ## Verification - Compiler builds in release mode locally (`dune build --release` → ELF x86-64); `--version` and `check <file>` work. - Bake substitutions match `lib/version.ml` (`let value = "0.2.1"`) and `.build/dune-project` (`(version 0.2.1)`). - YAML validated. ## Publishing `v0.2.0` is immutable and cannot be amended, so binaries are published via a fresh **`v0.2.1`** tag built with this fixed workflow (per the task: "otherwise cut v0.2.1"). This PR lands the same fix on `main` for all future releases. Refs ADR-019, #260 S2. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Lz7pRcec2Z3tVtaAhvB3M8 --- _Generated by [Claude Code](https://claude.ai/code/session_01Lz7pRcec2Z3tVtaAhvB3M8)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 5a42e6e commit b8ba479

1 file changed

Lines changed: 20 additions & 4 deletions

File tree

.github/workflows/release.yml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,21 @@ jobs:
3434
steps:
3535
- name: Checkout code
3636
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
37-
- name: Create the release (idempotent)
37+
- name: Create the release as a draft (idempotent)
38+
# Immutable releases (enabled on this repo) forbid adding assets to a
39+
# *published* release — the v0.2.0 build legs hit "HTTP 422: Cannot
40+
# upload assets to an immutable release", so it shipped source-only.
41+
# Fix: create the release as a DRAFT (still mutable); the build legs
42+
# upload binaries into the draft and the checksums job publishes it
43+
# last, sealing it atomically with all assets attached.
3844
env:
3945
GH_TOKEN: ${{ github.token }}
4046
run: |
4147
tag="${GITHUB_REF_NAME}"
4248
if gh release view "$tag" >/dev/null 2>&1; then
4349
echo "release $tag already exists; reusing"
4450
else
45-
gh release create "$tag" --generate-notes --verify-tag --title "$tag"
51+
gh release create "$tag" --draft --generate-notes --verify-tag --title "$tag"
4652
fi
4753
build:
4854
needs: prepare
@@ -75,8 +81,14 @@ jobs:
7581
# LSP serverInfo, ONNX producer_version).
7682
run: |
7783
v="${GITHUB_REF_NAME#v}"
78-
sed -i "s/^let value = .*/let value = \"$v\"/" lib/version.ml
79-
sed -i "s/^(version .*)/(version $v)/" .build/dune-project
84+
# Use `sed -i.bak` (backup-suffix attached): both GNU sed (Linux) and
85+
# BSD sed (macOS) accept it. Bare `sed -i "s/..."` makes BSD sed treat
86+
# the script as the backup suffix and the filename as a command, dying
87+
# with "extra characters at the end of l command" — which is exactly
88+
# why the v0.2.0 macOS legs failed before building anything.
89+
sed -i.bak "s/^let value = .*/let value = \"$v\"/" lib/version.ml
90+
sed -i.bak "s/^(version .*)/(version $v)/" .build/dune-project
91+
rm -f lib/version.ml.bak .build/dune-project.bak
8092
echo "Baked version: $v"
8193
grep '^let value' lib/version.ml
8294
grep '^(version' .build/dune-project
@@ -107,3 +119,7 @@ jobs:
107119
( cd dl && sha256sum affinescript-* | sort -k2 > SHA256SUMS )
108120
cat dl/SHA256SUMS
109121
gh release upload "$tag" --repo "$GITHUB_REPOSITORY" dl/SHA256SUMS --clobber
122+
# Seal the release last. Under immutable releases assets can only be
123+
# added while the release is a draft, so publish only once all four
124+
# assets (three binaries + SHA256SUMS) are attached.
125+
gh release edit "$tag" --repo "$GITHUB_REPOSITORY" --draft=false --latest

0 commit comments

Comments
 (0)