1717 tag :
1818 description : " Release tag to create / upload assets to"
1919 required : true
20- default : " bindings-v0.1.1 "
20+ default : " bindings-v0.2.0 "
2121 push :
2222 tags :
2323 - " bindings-v*"
2424
2525permissions :
2626 contents : read
2727
28- env :
29- # Ruby gem version (drives the .gem filenames). Python and npm carry their
30- # own versions in their manifests — the Ruby gem intentionally lags at 0.1.0.
31- BINDING_VERSION : " 0.1.0"
32-
3328jobs :
29+ # 0. Single source of truth for the release version: derive it from the tag
30+ # (`bindings-v0.2.0` -> `0.2.0`) so every packaged artifact — Ruby gem,
31+ # Python wheel, npm tarball — carries the same version as the release. No
32+ # manifest is trusted for the version; they are all stamped from this output
33+ # before packaging, so the tag alone drives everything.
34+ version :
35+ runs-on : ubuntu-latest
36+ outputs :
37+ version : ${{ steps.v.outputs.version }}
38+ tag : ${{ steps.v.outputs.tag }}
39+ steps :
40+ - id : v
41+ run : |
42+ set -euo pipefail
43+ if [ "${{ github.event_name }}" = "push" ]; then
44+ tag="${{ github.ref_name }}"
45+ else
46+ tag="${{ inputs.tag }}"
47+ fi
48+ # Strip the leading "bindings-v" (or bare "bindings-") to get a plain
49+ # semver the language packagers accept.
50+ version="${tag#bindings-v}"
51+ version="${version#bindings-}"
52+ echo "tag=${tag}" >> "$GITHUB_OUTPUT"
53+ echo "version=${version}" >> "$GITHUB_OUTPUT"
54+ echo "release tag=${tag} -> package version=${version}"
55+
3456 # 1. Build the shared library on a native runner per target.
3557 build-lib :
3658 name : build-lib (${{ matrix.target }})
@@ -189,8 +211,10 @@ jobs:
189211
190212 # 2a. Ruby platform gems (packaging is host-independent — build all on one runner).
191213 ruby :
192- needs : [build-lib, build-lib-freebsd, build-lib-netbsd]
214+ needs : [version, build-lib, build-lib-freebsd, build-lib-netbsd]
193215 runs-on : ubuntu-latest
216+ env :
217+ BINDING_VERSION : ${{ needs.version.outputs.version }}
194218 steps :
195219 - uses : actions/checkout@v4
196220 - uses : ruby/setup-ruby@v1
@@ -201,6 +225,16 @@ jobs:
201225 with :
202226 path : artifacts
203227
228+ - name : Stamp gem version from release tag
229+ working-directory : bindings/ruby
230+ run : |
231+ set -euxo pipefail
232+ # gem build reads RockboxFFI::VERSION from version.rb; keep it in lock-
233+ # step with the -o filename (BINDING_VERSION) so the gem's internal
234+ # version matches its filename and the release tag.
235+ printf 'module RockboxFFI\n VERSION = "%s"\nend\n' "$BINDING_VERSION" \
236+ > lib/rockbox_ffi/version.rb
237+
204238 - name : Build platform gems
205239 working-directory : bindings/ruby
206240 run : |
@@ -246,8 +280,10 @@ jobs:
246280 # the manylinux tag. BSD wheels are best-effort — pip falls back to the
247281 # sdist when the tag does not match.
248282 python :
249- needs : [build-lib, build-lib-freebsd, build-lib-netbsd]
283+ needs : [version, build-lib, build-lib-freebsd, build-lib-netbsd]
250284 runs-on : ubuntu-latest
285+ env :
286+ BINDING_VERSION : ${{ needs.version.outputs.version }}
251287 steps :
252288 - uses : actions/checkout@v4
253289 - uses : actions/setup-python@v5
@@ -258,6 +294,14 @@ jobs:
258294 with :
259295 path : artifacts
260296
297+ - name : Stamp wheel version from release tag
298+ working-directory : bindings/python
299+ run : |
300+ set -euxo pipefail
301+ # Pin the first (project) `version = "..."` in pyproject.toml to the tag.
302+ sed -i "0,/^version = .*/s//version = \"${BINDING_VERSION}\"/" pyproject.toml
303+ grep -m1 '^version = ' pyproject.toml
304+
261305 - name : Install build tooling
262306 run : pip install build wheel
263307
@@ -305,8 +349,10 @@ jobs:
305349
306350 # 2c. npm: pack the main package + per-platform binary packages into tarballs.
307351 npm :
308- needs : [build-lib, build-lib-freebsd, build-lib-netbsd]
352+ needs : [version, build-lib, build-lib-freebsd, build-lib-netbsd]
309353 runs-on : ubuntu-latest
354+ env :
355+ BINDING_VERSION : ${{ needs.version.outputs.version }}
310356 steps :
311357 - uses : actions/checkout@v4
312358 - uses : oven-sh/setup-bun@v2
@@ -318,6 +364,35 @@ jobs:
318364 with :
319365 path : artifacts
320366
367+ - name : Stamp npm versions from release tag
368+ working-directory : bindings/typescript
369+ run : |
370+ set -euxo pipefail
371+ # Bump the main package, every per-platform package, and the main
372+ # package's optionalDependencies (which must pin the exact per-platform
373+ # version) all to the tag — otherwise `npm install rockbox-ffi` pulls a
374+ # stale prebuilt-binary package.
375+ node -e '
376+ const fs = require("fs");
377+ const v = process.env.BINDING_VERSION;
378+ const main = "package.json";
379+ const m = JSON.parse(fs.readFileSync(main, "utf8"));
380+ m.version = v;
381+ for (const k of Object.keys(m.optionalDependencies || {})) {
382+ m.optionalDependencies[k] = v;
383+ }
384+ fs.writeFileSync(main, JSON.stringify(m, null, 2) + "\n");
385+ for (const d of fs.readdirSync("npm", { withFileTypes: true })) {
386+ if (!d.isDirectory()) continue;
387+ const p = `npm/${d.name}/package.json`;
388+ if (!fs.existsSync(p)) continue;
389+ const j = JSON.parse(fs.readFileSync(p, "utf8"));
390+ j.version = v;
391+ fs.writeFileSync(p, JSON.stringify(j, null, 2) + "\n");
392+ }
393+ console.log("stamped npm packages to", v);
394+ '
395+
321396 - name : Build dist, stage binaries, pack tarballs
322397 working-directory : bindings/typescript
323398 run : |
@@ -467,7 +542,7 @@ jobs:
467542
468543 # 3. Collect every artifact and attach it to the GitHub Release.
469544 release :
470- needs : [build-lib, build-lib-freebsd, build-lib-netbsd, ruby, python, npm, swift]
545+ needs : [version, build-lib, build-lib-freebsd, build-lib-netbsd, ruby, python, npm, swift]
471546 runs-on : ubuntu-latest
472547 permissions :
473548 contents : write
@@ -496,18 +571,9 @@ jobs:
496571 done
497572 ls -l release
498573
499- - name : Determine tag
500- id : tag
501- run : |
502- if [ "${{ github.event_name }}" = "push" ]; then
503- echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
504- else
505- echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT"
506- fi
507-
508574 - name : Upload to GitHub Release
509575 uses : softprops/action-gh-release@v2
510576 with :
511- tag_name : ${{ steps.tag .outputs.tag }}
577+ tag_name : ${{ needs.version .outputs.tag }}
512578 files : release/*
513579 fail_on_unmatched_files : true
0 commit comments