👷 Validate the Rust host bridge in CI: guards, published gem, and dep-heads - #68
Merged
Merged
Conversation
…-heads The Rust host bridge specs require structuredmerge_host_prototype, a native gem from the separate structuredmerge-rust repo that is not published, so tree_haver, ast-template and ast-merge-git suites failed whenever selected. - Skip host-dependent examples when the host is unavailable (common case). - Add a CI-only STRUCTUREDMERGE_RUST_HOST_PUBLISHED switch to the 12 host Gemfiles that requires the published gem. The Gem suite (current) and a new Coverage job set it, so they represent what is available today and fail until the gem is released. - Add Rust host @ HEAD (builds the x86_64-linux platform gem from structuredmerge-rust HEAD) and Deps @ HEAD (runs each changed gem against that host plus its runtime_heads dependencies) jobs, and include all three new jobs in Check. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8aveNcdgPobyMrq8DkD9r
CI must reveal when common end-user paths are broken. Build the Rust host exactly as structuredmerge-rust's release workflow does (Ruby 4.0, CARGO_FEATURE_LINK_RUBY), and before running specs require it under the dep-heads bundle on the standard rv Ruby. The release build currently links libruby.so.4.0, which rv pre-built Rubies do not provide, so host specs were silently skipping while the job passed; it now fails for gems that declare the host until the release build produces a gem that loads there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8aveNcdgPobyMrq8DkD9r
pboling
added a commit
that referenced
this pull request
Sep 15, 2026
The Rust host switch from #68 declared the gem in two separate blocks, which RuboCop flags as Bundler/DuplicatedGem. Merge them into one if/elsif (local path wins, otherwise the published gem when STRUCTUREDMERGE_RUST_HOST_PUBLISHED=true) in the remaining 11 Gemfiles. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P8aveNcdgPobyMrq8DkD9r
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Rust host bridge specs added on 2026-09-10/11 (tree_haver
RustTslp, ast-template and ast-merge-gitRustHostProvider) requirestructuredmerge_host_prototype. That gem lives in the separate structuredmerge-rust repo (packages/ruby, a nativerb_sysextension) and is not published. CI never provides it, so those suites fail whenever they are selected (for example #64, andmainat c9f96be / 46d9dd8).Policy
CI must reveal when common end-user paths are broken, and must not claim something works for end users when it does not. A gap we can close ourselves by installing a gem we control is not a failure; a gem that will not load for users on standard Rubies is.
Changes
Guard the common case (host not present)
Skip the ungated host specs when the host is unavailable, using the patterns other host specs already use:
rust_tslp_language_matrix_spec.rb,rust_tslp_json5_contract_spec.rb:skip RustTslp.unavailable_reason unless RustTslp.available?rust_host_provider_spec.rb:.available?example skips only when the host library cannot be loaded; host-backed examples are in a guarded contextreal_git_integration_spec.rb: explicit Rust selector examples skip unlessRustHostProvider.available?current and coverage: the published host gem
The 12 Gemfiles that carry the
STRUCTUREDMERGE_RUST_DEVhost block gain a CI-only switch: withSTRUCTUREDMERGE_RUST_HOST_PUBLISHED=true(and no host already declared), they require the publishedstructuredmerge_host_prototype (~> 0.2). Local bundles are unchanged.kettle-testwith coverage on, using each gem'smise.tomlthresholds, for maximum coverage once the gem is published. It fails like current until then.dep-heads: what end users will install, built from structuredmerge-rust HEAD
x86_64-linuxplatform gem exactly asrelease-ruby-host.ymldoes (Ruby 4.0, Alef,CARGO_FEATURE_LINK_RUBY=1), then uploads it.dep_heads.gemfile: the gem'sGemfileplusgemfiles/modular/runtime_heads.gemfile, with HEAD declarations replacing the Gemfile's released declarations of the same gems (as the dep-heads appraisal does).KETTLE_FAMILY_BUNDLE_GEMFILEpoints spec subprocesses (for example the ast-merge-git Git drivers) at the same bundle.require "structuredmerge_host_prototype"must succeed under the dep-heads bundle before specs run, so the job fails instead of letting host specs skip.Checknow includes the three new jobs.Current finding: release host gems do not load on rv Rubies
The first CI run showed the release-style build links the native library against
libruby.so.4.0(readelf -d:NEEDED libruby.so.4.0, fromCARGO_FEATURE_LINK_RUBY=1, structuredmerge-rust f970e1c). rv pre-built Rubies do not ship a shared libruby, so loading fails withlibruby.so.4.0: cannot open shared object file, and the host specs silently skipped while Deps @ HEAD reported success. The same gem loads in a shared-libruby Ruby (e.g. mise).mise run ruby-package(structuredmerge-rustcurrent.ymland local builds) does not link libruby, which is why local validation passed.With the verify step, Deps @ HEAD now fails for the host gems until structuredmerge-rust's release build produces a gem that loads on rv Rubies. That is the intended end-user signal; this PR does not change the Rust side.
Verification
actionlint .github/workflows/current.yml: clean; YAML parses.Could not find gem 'structuredmerge_host_prototype (~> 0.2)'; flag off → resolves without the host.mise run ruby-packagehost gem (no libruby link): tree_haver 87/0, ast-template 74/0, ast-merge-git 95/0 failures, host specs run.Could not find gem 'structuredmerge_host_prototype (~> 0.2)'; Rust host @ HEAD builtstructuredmerge_host_prototype-0.2.0-x86_64-linux.gemfrom structuredmerge-rust e44a2e3; Deps @ HEAD skipped host specs (libruby) — addressed by the verify step above.Expected CI now: Gem suite and Coverage fail for the host gems (published gem unavailable); Rust host @ HEAD passes; Deps @ HEAD fails for the host gems (release host gem does not load on rv Ruby) and passes for the rest.
🤖 Generated with Claude Code
https://claude.ai/code/session_01P8aveNcdgPobyMrq8DkD9r