feat: add extra_args passthrough to bundle install - #394
Conversation
Threads extra command-line arguments to `bundle install` from the
`ruby.bundle_fetch` bzlmod tag / `rb_bundle_fetch` repo rule / `rb_bundle_install`
rule down onto the install command line.
Primary use case: cross-platform bundles. With bundler's `--target-rbconfig`
(RubyGems 3.4+ / Gem::TargetRbConfig), the host ruby can install a DIFFERENT
platform's precompiled gems — e.g. assembling an x86_64-linux vendor/bundle on
an arm64-darwin host for a container image layer, without a linux executor:
ruby.bundle_fetch(
name = "bundle",
gemfile = "//:Gemfile",
gemfile_lock = "//:Gemfile.lock",
extra_args = ["--target-rbconfig", "/path/to/linux/rbconfig.rb"],
)
Covers both the bzlmod and WORKSPACE paths (shared rb_bundle_fetch repo rule)
and the standalone rb_bundle_install rule.
extra_args now supports $(location)/$(rootpath)/$(execpath) make-variable
expansion (built-in ctx.expand_location) against a new `data` label_list, which
is also threaded as inputs to the bundle install action. This lets a file-valued
flag reference a target instead of a raw path:
ruby.bundle_fetch(
name = "bundle_linux_amd64",
gemfile = "//:Gemfile",
gemfile_lock = "//:Gemfile.lock",
data = ["//image:x86_64-linux-rbconfig.rb"],
extra_args = ["--target-rbconfig", "$(location //image:x86_64-linux-rbconfig.rb)"],
)
Threaded through the bzlmod tag, repo rule, generated BUILD, and install rule.
Adds a public dist_files filegroup (glob dist/**/*) to each per-platform ruby repo, aliased on the @ruby hub. Lets you package the interpreter into a container image (portable-ruby is relocatable), e.g.: pkg_tar(name = "ruby_runtime", srcs = ["@ruby//:dist_files"], package_dir = "/usr/local", strip_prefix = "dist")
Adds the pieces needed to install a bundle for a FOREIGN platform (e.g. build a linux gems layer from a macOS host via --target-rbconfig) and package it into a container image: * env values now support $(location ...)/$(execpath ...) expansion against `data` (mirrors extra_args) — lets an env var reference a build artifact, e.g. prepend a generated cross-compiler wrapper dir onto PATH. * new `rbconfig` filegroup on the ruby dist (+ hub alias): the interpreter's own relocatable rbconfig.rb, for `gem install --target-rbconfig` cross-builds. * `binstubs` attr (default True): skip `bundle binstubs --all` for cross-platform bundles, where the host ruby can't validate the target's native extensions; the (empty) binstubs dir is still materialized. * `gems` output group: just the vendor/bundle tree (no Gemfile/binstubs), so consumers can lay the gems into a container BUNDLE_PATH with a clean strip_prefix.
It would be great to have a sample test so that it doesn't break in the future. |
| # to `gem install --target-rbconfig` cross-compiles source gems for THIS Ruby's | ||
| # platform — its rubyhdrdir/libdir auto-resolve to the staged `dist` tree. Under | ||
| # a platform transition it resolves to the target arch's Ruby. | ||
| filegroup( |
There was a problem hiding this comment.
If all files are Ruby, it's better to use rb_library for it.
| # The complete Ruby install tree (bin/, lib/, include/, ...). Useful for | ||
| # packaging the interpreter into a container image (portable-ruby is relocatable | ||
| # via relative rpaths, so this tars cleanly to e.g. /usr/local). | ||
| filegroup( |
There was a problem hiding this comment.
You should be able to use @ruby//:files already to get this.
| # Expand `$(location ...)`/`$(execpath ...)` in env values (against `data`), | ||
| # mirroring `extra_args`. Lets an env var reference a build artifact by label | ||
| # — e.g. prepending a generated cross-compiler wrapper dir onto PATH. |
There was a problem hiding this comment.
No need for trivial comments, the code is self-explanatory.
|
Let's get CI passing before merge too. |
…h example Addresses review feedback on bazel-contrib#394 (comment 5223558709): "It would be great to have a sample test so that it doesn't break in the future," in reply to the offer to add an example/e2e test for the new extra_args attribute. Adds extra_args = ["--quiet"] to the existing bundle_fetch() used by examples/gem (both the bzlmod MODULE.bazel and legacy WORKSPACE entry points), so the extra_args -> rb_bundle_fetch -> rb_bundle_install plumbing is exercised by every existing examples/gem CI job. If that threading ever regresses (e.g. the flag gets dropped or the bundle install command line gets mangled), the existing `bazel build ...` step fails instead of the regression going unnoticed. Verified locally: built @bundle//bin:rake with this change (bzlmod mode) and confirmed the generated install script contains `bundle install --standalone --local --quiet`.
Fixes the failing docs:update_0_test/docs:update_1_test (stardoc diff tests) in the Ruleset CI job. The rb_bundle_install and rb_bundle_fetch attrs added earlier in this PR (extra_args, data, binstubs) changed the .bzl docstrings but docs/*.md were never regenerated to match. Ran `bazel run //docs:update` and committed the resulting diff verbatim.
|
Pushed a fix for the failing Also validated the CI on this branch is showing |
|
@DhashS Can you please address other inline comments I left? |
What
Adds an
extra_argsattribute that appends extra command-line arguments to thebundle installinvocation, plumbed through all three entry points:ruby.bundle_fetchbzlmod tag (extensions.bzl)rb_bundle_fetchrepo rule (bundle_fetch.bzl, used by both bzlmod and WORKSPACE)rb_bundle_installrule (bundle_install.bzl)Why
Cross-platform bundles. Bundler 2.6 / RubyGems 3.4 added
bundle install --target-rbconfig=<rbconfig.rb>(Gem::TargetRbConfig), which lets the host Ruby install a different platform's precompiled gems. There's currently no way to pass that (or any other) flag throughrb_bundle_install— the command is hardcoded toinstall --standalone --local, theenvattr isn't consulted by bundler for--target-rbconfig(it's a Thor CLI option, not aBundler::Settingskey), andBUNDLE_IGNORE_CONFIG=1rules out.bundle/config.With
extra_args, an arm64-darwin host can assemble anx86_64-linuxvendor/bundlefor a container image layer without a Linux executor:(Today the documented cross-platform story is RBE via the multi-platform toolchains from #377 — this offers a complementary, executor-free path for precompiled gems.)
Verified
Threaded end-to-end: with
extra_argsset, the generated@bundle//:BUILDcarriesextra_args = [...]and the generated install script runs:Notes / open questions
extra_argsis a verbatimstring_list. For file-valued flags like--target-rbconfig, a natural follow-up is$(location)expansion + threading the file as an action input (hermetic). Happy to add that here or in a follow-up — whichever you prefer..cmdtemplate updated symmetrically.examples/if you'd like — guidance welcome on the preferred shape.🤖 Generated with Claude Code