Skip to content

Adopt scientist-labs/rust-gem-release@v0 for releases#35

Merged
xrl merged 5 commits into
mainfrom
migrate-to-rust-gem-release
Jun 19, 2026
Merged

Adopt scientist-labs/rust-gem-release@v0 for releases#35
xrl merged 5 commits into
mainfrom
migrate-to-rust-gem-release

Conversation

@xrl

@xrl xrl commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

What

Migrates parsekit's release pipeline to the shared reusable workflow scientist-labs/rust-gem-release, pinned @v0 (the moving-major alias, currently resolving to 0.2.0). This is the same template proven by red-candle 1.8.0, which shipped all four platforms to rubygems.org green on 2026-06-18.

The old .github/workflows/release.yml was a hand-rolled workflow_dispatch-only job that bumped the version, committed + tagged, built a single source gem, and pushed to RubyGems inline. It is replaced by a thin caller that, on a pushed version tag, builds:

  • the source gem (universal fallthrough; compiles the native stack on install)
  • arm64-darwin precompiled fat gem (native build on Apple Silicon)
  • x86_64-linux precompiled fat gem (cross-gem)

Each fat gem carries one compiled extension per Ruby ABI, so consumers install with no Rust toolchain.

Files changed

  • .github/workflows/release.yml (modify) — replaced the inline 61-line manual release with the canonical caller uses: scientist-labs/rust-gem-release/.github/workflows/release.yml@v0. Triggers on version tags + workflow_dispatch (publish default false). Inputs: gem-name: parsekit, version-command: ruby -r./lib/parsekit/version -e 'print ParseKit::VERSION', build-aarch64-linux: false, publish: ${{ github.event_name == 'push' || inputs.publish }}; secret rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}; permissions: contents: write.
  • lib/parsekit.rb (modify) — PREREQ Bump codecov/codecov-action from 4 to 5 #1: ABI require-shim. Probes parsekit/<major.minor>/parsekit first via $LOAD_PATH require, falling back to flat parsekit/parsekit. The old require_relative "parsekit/parsekit" could never find the extension that a precompiled fat gem installs outside lib/.
  • parsekit.gemspec (modify) — PREREQ Bump actions/download-artifact from 4 to 5 #2: env-gated platform branch on RUST_GEM_PLATFORM. When set: spec.platform = it, spec.extensions = [], and the per-ABI .bundle/.so are packed; else declare the ext/parsekit/extconf.rb extension (normal source gem).

ci.yml is kept as the PR-CI path (it curls eng.traineddata and exports TESSDATA_PREFIX, which the shared build.yml has no hook to do); no build.yml caller was added.

Prereqs added

  • ABI require-shim in lib/parsekit.rb
  • env-gated platform branch (RUST_GEM_PLATFORM) in parsekit.gemspec

Both were absent before this PR — without them the precompiled gems would publish but never load (only the source gem would be usable).

Why aarch64-linux is off

parsekit's native extension statically builds MuPDF and Tesseract + Leptonica from C/C++ source (bundled-tesseract downloads source at build time). The shared workflow's aarch64 leg cross-compiles that bundled-C++ stack on an x86_64 host inside cross-gem's fixed image, which is fragile and may lack network for the source download. build-aarch64-linux: false keeps a tag reliably yielding source + arm64-darwin + x86_64-linux; aarch64 users fall through to the source gem (which compiles on install). Flip it back on once the shared workflow grows a native-arm / prebuilt-sysroot path for C-heavy gems.

Follow-up (not in this PR, non-blocking for the release pipeline): the precompiled gems do not package eng.traineddata, so OCR raises an InitError post-install unless system tessdata exists. Fix consumer-side by packaging or fetching tessdata.

Safety

  • publish defaults to a DRY-RUN. On manual workflow_dispatch, publish is false unless explicitly toggled on. Only a real version-tag push sets publish true.
  • A tag push is token-gated: if RUBYGEMS_API_KEY is empty the push step is a clean no-op.
  • The tag must equal the version-command output (0.1.3); note the constant is ParseKit (capital K).

Template reference: red-candle 1.8.0.


DRAFT — do not merge until a publish=false dry-run is green; trigger with: gh workflow run release.yml -f publish=false --ref migrate-to-rust-gem-release

🤖 Generated with Claude Code

xrl and others added 3 commits June 18, 2026 14:32
Replace the hand-rolled workflow_dispatch release (manual version bump +
commit + tag + single source gem build + RubyGems push) with a thin caller
of the shared reusable workflow scientist-labs/rust-gem-release@v0, modeled
on red-candle 1.8.0 (the proven template). A pushed version tag now builds
the source gem + arm64-darwin + x86_64-linux precompiled fat gems (one ext
per Ruby ABI), creates the GitHub Release, and conditionally publishes.

Also add the two consumer prerequisites the precompiled gems need to load:

- lib/parsekit.rb: ABI require-shim. Probe the Ruby-ABI-versioned native
  path (parsekit/<major.minor>/parsekit) first via $LOAD_PATH `require`,
  falling back to the flat parsekit/parsekit. The old require_relative form
  could never find the ext that a precompiled fat gem installs outside lib/.

- parsekit.gemspec: env-gated platform branch on RUST_GEM_PLATFORM — when
  set, spec.platform = it, spec.extensions = [] (no recompile on install),
  and the per-ABI .bundle/.so are packed; else declare the extconf extension
  (normal source gem).

Safety: aarch64-linux is disabled (build-aarch64-linux: false) — parsekit
statically builds MuPDF + Tesseract/Leptonica from C/C++ source and the
shared workflow's cross-gem aarch64 cross-build of that bundled-C++ stack is
fragile; aarch64 users fall through to the source gem. publish defaults to a
dry-run on manual dispatch; only a tag push publishes, and push no-ops when
RUBYGEMS_API_KEY is empty. ci.yml is kept as the PR-CI path (it curls
eng.traineddata + sets TESSDATA_PREFIX, which the shared build.yml cannot).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wire parsekit's release into the rust-gem-release@v0 cross-image path so
BOTH linux legs (x86_64-linux + aarch64-linux) build precompiled gems
instead of falling through to the source gem.

- release.yml: set linux-cross-image-repo=ghcr.io/scientist-labs/rust-gem-cross
  (deps-enriched FROM rbsys/<platform>:0.9.128), flip build-aarch64-linux on
  (x86_64 already default-on), add the label-gated pull_request dry-run
  trigger + if-gate, raise job-timeout-minutes for the heavy MuPDF +
  bundled-Tesseract/Leptonica from-source compile, and make the publish
  expr robust (push or explicit dispatch opt-in only).
- ext/parsekit/Cargo.lock: committed (force-added past gitignore), pins
  rb-sys to 0.9.128 so rb-sys-dock derives rbsys/<platform>:0.9.128 — the
  exact tag the workflow pre-seeds. No cargo-config/feature change needed:
  mupdf-sys finds cmake+libclang in the base image and tesseract-rs 0.2's
  bundled build needs only cmake+clang+network egress (all present); the
  union apt tesseract/leptonica dev libs are forward-compat for a future
  system-tesseract crate.
- Rakefile: guard the dev-only rspec require in begin/rescue LoadError so
  the cross-gem build container (runtime bundle only) can load the Rakefile
  and run native:<platform>; gemspec already passed to ExtensionTask;
  cross_platform carries the x86_64-linux/aarch64-linux/arm64-darwin union.

Runtime note (unchanged): the precompiled gem does not bundle
eng.traineddata; OCR consumers still need system tessdata via TESSDATA_PREFIX.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@xrl xrl added the dry-run-release Run the full precompiled release matrix as a publish=false dry-run label Jun 18, 2026
@xrl xrl added dry-run-release Run the full precompiled release matrix as a publish=false dry-run and removed dry-run-release Run the full precompiled release matrix as a publish=false dry-run labels Jun 18, 2026
Pin the reusable release workflow to the explicit latest version 0.10.0
and remove the stray @v0 doc-comment reference, as the moving-major @v0
tag is being retired.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@xrl xrl marked this pull request as ready for review June 18, 2026 23:15
@xrl xrl added dry-run-release Run the full precompiled release matrix as a publish=false dry-run and removed dry-run-release Run the full precompiled release matrix as a publish=false dry-run labels Jun 18, 2026
@xrl xrl merged commit e86ac7e into main Jun 19, 2026
21 checks passed
@xrl xrl deleted the migrate-to-rust-gem-release branch June 19, 2026 00:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dry-run-release Run the full precompiled release matrix as a publish=false dry-run

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant