Deprecated: Function get_magic_quotes_gpc() is deprecated in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 99

Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 619

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 832

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
Bundler Blog The latest news on Bundler https://bundler.io/blog 2025-07-17T07:13:00+00:00 The Bundler Team Bundler v2.7: last release before Bundler 4 https://bundler.io/blog/2025/07/17/bundler-v2-7.html 2025-07-17T07:13:00+00:00 2025-10-20T08:26:09+00:00 David Rodríguez <p>A major release of Bundler is finally happening, consolidating unreleased major changes that had been pending for a decade. It will be named Bundler 4 (skipping Bundler 3), so that we can release it in lockstep with RubyGems 4, making the version number of Bundler &amp; RubyGems in sync from now on.</p> <p>Final Bundler 4 release will happen at the end of 2025, but for now we’re presenting Bundler 2.7 as the last big step towards this major release.</p> <p>Bundler 2.7 features a <code>simulate_version</code> configuration that will allow users to configure Bundler to behave exactly as Bundler 4 will behave, with all major breaking changes enabled by default. We encourage all users to enable this setting, experiment with Bundler 4, and leave us feedback. Community feedback is super important to us, and we’re still open to revisiting the changes that the final version will include.</p> <p>You can find more about future Bundler 4 changes and how to enable Bundler 4 mode in our <a href="https://github.com/rubygems/rubygems/blob/ff473128011e7abe1eeb0414d9cd48677acb5487/doc/bundler/UPGRADING.md">upgrade guide</a></p> <p>In addition to changes to get ready for Bundler 4, Bundler 2.7 also features some additional improvements such as:</p> <ul> <li>Our gem generator is now more customizable than ever, displays more informative output, and provides a skeleton with better defaults.</li> <li>Network errors are better handled to print more actionable errors and avoid unnecessary retries that will never succeed.</li> <li>Bundler is now more resilient in presence of incorrect lockfiles, or locally installed gemspecs with incorrect dependencies.</li> <li>Several issues have been fixed to make Bundler play nicer with default gems like <code>rdoc</code> or <code>irb</code>.</li> <li>Auto-switch and auto-restart mechanism based on locked version of Bundler has been improved.</li> <li><code>bundle install</code> can now properly unlock rails (or any other gem including its own dependencies as a monorepo) when changing its Gemfile <code>git</code> source to pin it to a specific <code>ref</code>.</li> </ul> <p>Happy bundling!</p> Bundler v2.6: lockfile checksums are finally there https://bundler.io/blog/2024/12/19/bundler-v2-6.html 2024-12-19T17:01:00+00:00 2025-10-20T08:26:09+00:00 David Rodríguez <p>We’re happy to announce Bundler 2.6, featuring gem checksum verification, right in the <code>Gemfile.lock</code> file.</p> <p>This feature has actually been implemented for more than a year. However, it was merged very close to the Bundler 2.5 release and we did not yet have a good plan for enabling the feature in a graceful manner, so we’ve kept it hidden until now.</p> <p>Bundler 2.6 finally officially allows to opt-in into this beta feature.</p> <h2 id="whats-this-feature-for">What’s this feature for?</h2> <p>A lockfile is an easy way to ensure all environments will use a consistent version of every dependency. However, Bundler lockfiles did not protect from potential tampering of the sources of that specific version. This is what the this feature does. When enabled, Bundler will keep track of the checksum of every version in the lockfile, in the lockfile itself. Then, before installing that lockfile on any machine, it will verify that the checksum of the <code>.gem</code> file it’s about to install matches the checksum previously recorded in the lockfile. If they don’t match, Bundler will refuse to install that package and consider it compromised.</p> <h3 id="how-to-enable-lockfile-checksums">How to enable lockfile checksums?</h3> <p>Bundler 2.6 provides two ways of enabling checksums.</p> <ul> <li> <p>For a single lockfile, you can run <code>bundle lock --add-checksums</code>. This will add a new <code>CHECKSUMS</code> section to the lockfile that Bundler will keep up to date.</p> </li> <li> <p>To configure Bundler to always include checksums in new lockfiles, run <code>bundle config lockfile_checksums true</code>.</p> </li> </ul> <h3 id="how-does-it-work-once-the-feature-is-enabled">How does it work, once the feature is enabled?</h3> <p>Hopefully nothing will ever change for you after enabling the feature. However, if <code>bundle install</code> ever downloads a package (or tries to install it from cache) the checksum of which does not match what’s recorded in the lockfile for that package, Bundler will print an error like the following and abort installation:</p> <div class="highlight"><pre class="highlight plaintext"><code>$ bundle install Fetching gem metadata from https://rubygems.org/........ Bundler found mismatched checksums. This is a potential security risk. rake (13.2.1) sha256=46cb38dae65d7d74b6020a4ac9d48afed8eb8149c040eccf0523bec91907059d from the lockfile CHECKSUMS at Gemfile.lock:1241:17 and the API at https://rubygems.org/ rake (13.2.1) sha256=17e8b7c1b247f3349d4a7160c3f587b6c7fd67cf7be3b3710e118b8416f94ddb from the gem at /my/repo/vendor/cache/rake-13.2.1.gem If you trust the lockfile CHECKSUMS at Gemfile.lock:1241:17, to resolve this issue you can: 1. remove the gem at /my/repo/vendor/cache/rake-13.2.1.gem 2. run `bundle install` To ignore checksum security warnings, disable checksum validation with `bundle config set --local disable_checksum_validation true` </code></pre></div> <h2 id="compatibility">Compatibility</h2> <p>Bundler will keep the <code>CHECKSUMS</code> section in the lockfile up to date if it’s already there, and verify that <code>.gem</code> packages checksums match what’s recorded in the lockfile before installing.</p> <p>On the other hand, Bundler will work like before if it doesn’t find a <code>CHECKSUMS</code> section in the lockfile.</p> <p>All lockfiles including a <code>CHECKUMS</code> section should have Bundler &gt;= 2.6 in the <code>BUNDLED WITH</code> section. Since Bundler internally has a mechanism to make sure it switches to the version of itself included in the <code>BUNDLED WITH</code> lockfile section, a lockfile with a <code>CHECKSUMS</code> section should always be run by Bundler &gt;= 2.6.</p> <p>Some platforms, like Heroku or Dependabot, don’t respect this auto-switching mechanism. However, these platforms are already using Bundler &gt;= 2.5 and since this feature is luckily already present (but hidden) since Bundler 2.5, they should deal just fine with new lockfiles including the new section.</p> <h2 id="should-i-take-any-other-steps-before-enabling-this-feature">Should I take any other steps before enabling this feature?</h2> <p>If your lockfile only includes <code>ruby</code> in the <code>PLATFORMS</code> section, that means that Bundler is most likely not storing platform-specific variants of your gems in the <code>Gemfile.lock</code> file. For example, your lockfile may include only <code>nokogiri-1.18.0</code>, while Bundler will actually install the most appropriate 1.18.0 variant for your platform, say <code>nokogiri-1.18.0-x86_64-linux</code>. However, that makes the lockfile checksums feature not work fine for <code>nokigiri</code> because Bundler will only check if the generic variant (what’s in the lockfile) is changed, but not the variant that’s actually installed.</p> <p>Because of this, Bundler 2.6 will print a warning when it ends up installing a different variant than the one included in the lockfile, and tell you to “normalize” the lockfile and add platform specific variants through <code>bundle lock --normalize-platforms</code>.</p> <h2 id="other-notable-changes-in-bundler-26">Other notable changes in Bundler 2.6</h2> <p>This is a non-exhaustive list of other notable improvements in Bundler 2.6:</p> <ul> <li><strong>Better support for switching between different versions of Ruby.</strong></li> </ul> <p>Sometimes when switching between different Ruby versions, even if the resolution recorded in the Gemfile.lock is stable, the most optimal platform-specific version for a gem may change. For example, <code>nokogiri-1.18.0.rc1-x86_64-darwin</code> does not support Ruby 3.5, but <code>nokogiri-1.18.0.rc1</code> does. Bundler 2.6 should be able to keep a consistent lockfile with all platform-specific variants, and use the one that works best for each Ruby version.</p> <ul> <li><strong>Better handling of git dependencies in application caches.</strong></li> </ul> <p>Bundler can keep <code>.gem</code> packages for your dependencies in <code>vendor/cache</code> so that, for example, they can be installed offline on a different machine. This did not work fine for git gems, though. Bundler 2.6 should now allow properly caching git gems in <code>vendor/cache</code>. You can enable this with <code>bundle config cache_all true</code>.</p> <ul> <li><strong>More careful redaction of gem server credentials in logs and <code>bundle config</code> output.</strong></li> </ul> <p>Bundler already did this but we found a few cases where it was not properly redacting sensitive info and fixed those.</p> <ul> <li><strong>Better <code>bundle exec</code> behaviour on Windows.</strong></li> </ul> <p>We have introduced several improvements so that <code>bundle exec</code> works the usual way, also on Windows.</p> <ul> <li><strong>Better documentation of commands and CLI flags.</strong></li> </ul> <p>We have introduced changes to make sure that this site, and the <code>bundle</code> CLI, properly documents all commands and CLI flags, and made sure it will stay like that going forward.</p> <p>And like always, many other bug fixes and improvements were implemented. Check <a href="https://github.com/rubygems/rubygems/releases/tag/bundler-v2.6.0">the full Bundler 2.6 changelog</a> for details.</p> <p>Happy bundling!</p> Bundler v2.4: new resolver, gems with Rust extensions, and more https://bundler.io/blog/2023/01/31/bundler-v2-4.html 2023-01-31T14:43:00+00:00 2025-10-20T08:26:09+00:00 David Rodríguez <p>2022 has been a busy year for the Bundler team, and we’re glad to present several improvements that we hope will make our users happy :)</p> <h2 id="a-better-pubgrub-based-resolver">A better, PubGrub based, resolver</h2> <p>Bundler now uses the most advanced algorithm to resolve versions, PubGrub. Kudos to Natalie Weizenbaum for <a href="https://nex3.medium.com/pubgrub-2fb6470504f">inventing it</a> and to John Hawthorn for <a href="https://github.com/jhawthorn/pub_grub">porting it to Ruby</a>!</p> <p>Our previous resolver, <a href="https://github.com/CocoaPods/Molinillo">Molinillo</a>, worked pretty well, but it really got in the middle when it didn’t.</p> <p>This may sound familiar for some:</p> <div class="highlight"><pre class="highlight plaintext"><code>$ bundle Fetching gem metadata from https://rubygems.org/............ Resolving dependencies....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................^C $ # Ok, that was enough waiting </code></pre></div> <p>Our new resolver, PubGrub, is usually much faster, because it learns from the resolution conflicts it finds during the resolution process to avoid redoing the same work over and over again. You can find more about this “conflict-driven clause learning” techniques in its <a href="https://nex3.medium.com/pubgrub-2fb6470504f">presentation blog post</a> back from 2018.</p> <p>Molinillo sometimes took too long to resolve because it would try the same things, backtrack, and run into the same conflicts over and over again, having to traverse very inefficiently a huge search space. But that was a relatively rare case in the real world.</p> <p>What’s probably more common is specifying version requirements in your Gemfile, that can’t be all satisfied at the same time. This is when the version solving problem does not have a solution, and when it becomes crucial to explain to users <em>why</em>, so that they can fix their set of version requirements to become solvable.</p> <p>Molinillo run into trouble here, and in cases with many moving parts, like upgrading Rails for example, it could end up printing a lot of conflicts, not easy to understand and solve. This is an old example from a public ticket:</p> <div class="highlight"><pre class="highlight plaintext"><code>Bundler could not find compatible versions for gem "actionpack": In Gemfile: inherited_resources (= 1.6.0) was resolved to 1.6.0, which depends on actionpack (&gt;= 3.2, &lt; 5) rails (= 4.2.0) was resolved to 4.2.0, which depends on actionpack (= 4.2.0) Bundler could not find compatible versions for gem "activesupport": In Gemfile: inherited_resources (= 1.6.0) was resolved to 1.6.0, which depends on has_scope (~&gt; 0.6.0.rc) was resolved to 0.6.0, which depends on activesupport (&gt;= 3.2, &lt; 5) rails (= 4.2.0) was resolved to 4.2.0, which depends on activesupport (= 4.2.0) Bundler could not find compatible versions for gem "railties": In Gemfile: inherited_resources (= 1.6.0) was resolved to 1.6.0, which depends on railties (&gt;= 3.2, &lt; 5) rails (= 4.2.0) was resolved to 4.2.0, which depends on railties (= 4.2.0) inherited_resources (= 1.6.0) was resolved to 1.6.0, which depends on responders was resolved to 1.1.2, which depends on railties (&gt;= 3.2, &lt; 4.2) </code></pre></div> <p>Not easy to know what to do about it.</p> <p>With PubGrub, you should now get human-readable explanations of failures. The most complex cases may are still, well… complex. But explanations should always make sense and point to the root cause of resolution failures.</p> <p>Here’s an example from our test suite:</p> <div class="highlight"><pre class="highlight plaintext"><code>Because every version of c depends on a &lt; 1 and every version of b depends on a &gt;= 2, every version of c is incompatible with b &gt;= 0. So, because Gemfile depends on b &gt;= 0 and Gemfile depends on c &gt;= 0, version solving has failed. </code></pre></div> <p>We tried to make this migration as backwards-compatible as possible, but there’s a chance of experiencing some different solutions to the ones found by Molinillo, since the version solving problem does not have unique solutions. Please report any issues you find with the new resolver.</p> <h3 id="easily-generate-gems-with-rust-extensions-using-bundle-gem">Easily generate gems with Rust extensions using <code>bundle gem</code></h3> <p>It’s now easier than ever to get started using Rust inside your gems. Check out <a href="/blog/2023/01/31/rust-gem-skeleton.html">this blog post</a> to learn how to generate a gem with all the boilerplate necessary with just a few commands.</p> <h3 id="faster-git-sources">Faster git sources</h3> <p>In the Bundler world, it’s common to point to git repositories when there’s no version released to rubygems.org that includes the changes that you need. This works fine, but it can get slow and use a lot of disk space when dealing with very big repositories.</p> <p>We have improved the way we clone these repositories to be faster and use less disk space. For example, something like</p> <div class="highlight"><pre class="highlight plaintext"><code>gem "rails", github: "rails/rails" </code></pre></div> <p>in your Gemfile could previously take ~30s and use up to 1Gb of disk space, because we would clone the full Rails repository, which has a large history.</p> <p>Now we just clone what’s strictly necessary for Bundler to work, resulting in big disk space savings, and much faster bundling.</p> <h3 id="new-cli-features">New CLI features</h3> <p>We added a few small CLI features, such as a new <code>--pre</code> flag to <code>bundle update</code> and <code>bundle lock</code> to explicitly opt-in to prereleases of selected (of all) gems without having to explictly change your Gemfile with pre-release requirements such as <code>&gt;= 7.1.0.beta</code>.</p> <h3 id="some-minor-breaking-changes">Some minor breaking changes</h3> <p>We took new year’s release to move on and get rid of some stuff that was causing maintenance burden for us:</p> <ul> <li>Ruby 2.3, 2.4, and 2.5 are no longer supported.</li> <li>RubyGems 2.5, 2.6, and 2.7 are no longer supported.</li> </ul> <p>In general, this support drop should not break anything because RubyGems should be able to choose the latest supported Bundler on the Ruby version that you’re using. But there are still some old RubyGems out there that don’t have this feature, and the <code>gem install bundler</code> command could break there. We have warned using Bundler on those old rubies for a year now, so we believe it’s time to move on.</p> <p>We also completely removed a controversial (mis-)feature from the Bundler code base, where Bundler would automatically acquire sudo permissions when not having the proper access rights. A great majority of users considered this feature harmful and hardly useful, so we decided to get rid of it.</p> <h3 id="and-bug-fixes">And bug fixes</h3> <p>As always, we continue to smooth the experience of using Bundler, so that it gets the job done and does not get in the middle other than that. And we’re also shipping a bunch of bug fixes to keep moving towards that goal.</p> <p>That’s all from the Bundler team. Have a happy new year, and enjoy using Bundler 2.4! 🎉</p> Generate gem skeleton with Rust extension https://bundler.io/blog/2023/01/31/rust-gem-skeleton.html 2023-01-31T14:42:00+00:00 2025-10-20T08:26:09+00:00 Josef Šimánek <p>Do you think <a href="https://en.wikipedia.org/wiki/Dynamic_programming_language">dynamically typed</a> <a href="https://en.wikipedia.org/wiki/Interpreter_(computing)">interpreted</a> <a href="https://www.ruby-lang.org/">Ruby language</a> and <a href="https://en.wikipedia.org/wiki/Type_system#Static_type_checking">statically typed</a> <a href="https://en.wikipedia.org/wiki/Compiled_language">compiled</a> <a href="https://www.rust-lang.org/">Rust language</a> could be friends? Yes, they can! And actually, they are!</p> <p>Officially it all started when <a href="https://github.com/ruby/ruby/blob/d5635dfe36588b04d3dd6065ab4e422f51629b11/doc/yjit/yjit.md">YJIT</a> was <a href="https://bugs.ruby-lang.org/issues/18481">ported to Rust</a> and <a href="https://github.com/ruby/ruby">Ruby codebase</a> has officially <a href="https://github.com/ruby/ruby/tree/master/yjit/src">onboarded Rust code</a>. This friendship matured when RubyGems <a href="https://rubygems.org/gems/rubygems-update/versions/3.3.11">3.3.11</a> (with a new <a href="https://github.com/rubygems/rubygems/pull/5175"><em>Add cargo builder for rust extensions</em></a> feature) <a href="https://blog.rubygems.org/2022/04/07/3.3.11-released.html">was released</a> capable of compiling Rust-based extensions during gem installation process (similar to well-known C-based gem extensions like nokogiri, pg or puma).</p> <p>And now, with Bundler 2.4, <code>bundle gem</code> skeleton generator can provide all the glue you need to start using Rust inside your gems thanks to the new <code>--ext=rust</code> parameter!</p> <h2 id="whats-new">What’s new?</h2> <p>Thanks to new parameter it is possible to generate simple Rust-based gem extension.</p> <p><em>Make sure to use RubyGems 3.4.6 or higher for the best experience.</em></p> <p><em>Notice I already have <code>bundle gem</code> command configured. Your output can differ. When running <code>bundle gem</code> for the first time, it will interactively ask you few questions.</em></p> <div class="highlight"><pre class="highlight plaintext"><code>$ bundle gem --ext=rust hello_rust Creating gem 'hello_rust'... MIT License enabled in config Initializing git repo in /home/retro/code/hello_rust create hello_rust/Gemfile create hello_rust/lib/hello_rust.rb create hello_rust/lib/hello_rust/version.rb create hello_rust/sig/hello_rust.rbs create hello_rust/hello_rust.gemspec create hello_rust/Rakefile create hello_rust/README.md create hello_rust/bin/console create hello_rust/bin/setup create hello_rust/.gitignore create hello_rust/test/test_helper.rb create hello_rust/test/test_hello_rust.rb create hello_rust/LICENSE.txt create hello_rust/Cargo.toml create hello_rust/ext/hello_rust/Cargo.toml create hello_rust/ext/hello_rust/extconf.rb create hello_rust/ext/hello_rust/src/lib.rs Gem 'hello_rust' was successfully created. For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html </code></pre></div> <p>For Rust-based extension last 4 entries are interesting.</p> <ul> <li><code>hello_rust/Cargo.toml</code> <ul> <li>Top-level <code>Cargo.toml</code> is just pointing to “nested” <code>Cargo.toml</code> in <code>ext</code> folder.</li> <li>It is useful to be able to run all <code>cargo</code> commands in top-level directory (next to <code>bundle</code>, <code>gem</code>, …).</li> <li>It is also useful for your IDE to be able to recognize there is Rust code in this folder, but not in standard path for Rust crate.</li> </ul> </li> <li><code>hello_rust/ext/hello_rust/Cargo.toml</code> <ul> <li>Actual <code>Cargo.toml</code> as known from Rust crates. It includes package metadata, configuration and dependencies. You can think of this file as a “gemspec for Rust packages”.</li> </ul> </li> <li><code>hello_rust/ext/hello_rust/extconf.rb</code> <ul> <li>Config file responsible for configuration of compilation of your Rust code in Ruby world (for example during gem installation).</li> <li>Currently based on <a href="https://github.com/oxidize-rb/rb-sys/tree/main/gem#the-rb_sys-gem">rb_sys gem</a>. Check <a href="https://github.com/oxidize-rb/rb-sys/tree/main/gem#create_rust_makefile">project README</a> for more info.</li> </ul> </li> <li><code>hello_rust/ext/hello_rust/src/lib.rs</code> <ul> <li>Yes, the holy grail of Rust-based extension - the Rust code!</li> </ul> </li> </ul> <h2 id="hello-from-rust">Hello from Rust!</h2> <p>Generated <code>hello_rust/ext/hello_rust/src/lib.rs</code> contains hello world example method defined at base class of extension. In my case it is <code>HelloRust#hello</code> with 1 string argument returning string as well. It is using <a href="https://github.com/matsadler/magnus">magnus</a> Rust bindings to Ruby for super smooth developer experience.</p> <div class="highlight"><pre class="highlight rust"><code><span class="cs"># hello_rust/ext/hello_rust/src/lib.rs</span> <span class="k">use</span> <span class="nn">magnus</span><span class="p">::{</span><span class="n">define_module</span><span class="p">,</span> <span class="n">function</span><span class="p">,</span> <span class="nn">prelude</span><span class="p">::</span><span class="o">*</span><span class="p">,</span> <span class="n">Error</span><span class="p">};</span> <span class="k">fn</span> <span class="nf">hello</span><span class="p">(</span><span class="n">subject</span><span class="p">:</span> <span class="nb">String</span><span class="p">)</span> <span class="k">-&gt;</span> <span class="nb">String</span> <span class="p">{</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"Hello from Rust, {}!"</span><span class="p">,</span> <span class="n">subject</span><span class="p">)</span> <span class="p">}</span> <span class="nd">#[magnus::init]</span> <span class="k">fn</span> <span class="nf">init</span><span class="p">()</span> <span class="k">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="n">Error</span><span class="o">&gt;</span> <span class="p">{</span> <span class="k">let</span> <span class="n">module</span> <span class="o">=</span> <span class="nf">define_module</span><span class="p">(</span><span class="s">"HelloRust"</span><span class="p">)</span><span class="o">?</span><span class="p">;</span> <span class="n">module</span><span class="nf">.define_singleton_method</span><span class="p">(</span><span class="s">"hello"</span><span class="p">,</span> <span class="nd">function!</span><span class="p">(</span><span class="n">hello</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span><span class="o">?</span><span class="p">;</span> <span class="nf">Ok</span><span class="p">(())</span> <span class="p">}</span> </code></pre></div> <p>That is equivalent to following Ruby code, including some boilerplate code, to enable Rust extension to communicate with Ruby.</p> <div class="highlight"><pre class="highlight ruby"><code><span class="k">module</span> <span class="nn">HelloRust</span> <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">hello</span><span class="p">(</span><span class="n">subject</span><span class="p">)</span> <span class="s2">"Hello from Rust, </span><span class="si">#{</span><span class="n">subject</span><span class="si">}</span><span class="s2">!"</span> <span class="k">end</span> <span class="k">end</span> </code></pre></div> <h2 id="lets-compile-and-run-some-rust">Let’s compile and run some Rust!</h2> <p>To be able to test this boilerplate code, you need to run <code>bundle install</code> first (to install all Ruby dependencies) followed by <code>bundle exec rake compile</code> compiling Rust code.</p> <p><em>Notice generated gemspec is not valid by default and running <code>bundle install</code> can break. In that case it is needed to update gemspec first and replace all TODO values with some real ones.</em></p> <div class="highlight"><pre class="highlight plaintext"><code>$ bundle install Fetching gem metadata from https://rubygems.org/. Resolving dependencies... Using rake 13.0.6 Using bundler 2.4.0 Using hello_rust 0.1.0 from source at `.` Using minitest 5.16.3 Using rake-compiler 1.2.1 Using rb_sys 0.9.52 Bundle complete! 5 Gemfile dependencies, 6 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed. </code></pre></div> <p>At this stage, everything is ready to compile Rust code and glue it with Ruby.</p> <p><em>You need to have Rust already installed on your system. See <a href="https://rustup.rs/">rustup</a> for a simple installation experience.</em></p> <div class="highlight"><pre class="highlight plaintext"><code>$ bundle exec rake compile mkdir -p tmp/x86_64-linux/hello_rust/3.1.2 cd tmp/x86_64-linux/hello_rust/3.1.2 /home/retro/.rubies/ruby-3.1.2/bin/ruby -I. -r.rake-compiler-siteconf.rb ../../../../ext/hello_rust/extconf.rb cd - cd tmp/x86_64-linux/hello_rust/3.1.2 /usr/bin/gmake generating target/release/libhello_rust.so (release) cargo rustc --target-dir target --manifest-path ../../../../ext/hello_rust/Cargo.toml --lib --release -- -C linker=gcc -L native=/home/retro/.rubies/ruby-3.1.2/lib -C link-arg=-lm Updating crates.io index ... shortened Compiling magnus-macros v0.2.0 Compiling rb-sys-build v0.9.52 Compiling rb-sys v0.9.52 Compiling hello_rust v0.1.0 (/home/retro/code/hello_rust/ext/hello_rust) Finished release [optimized] target(s) in 1m 03s cd - mkdir -p tmp/x86_64-linux/stage/lib/hello_rust /usr/bin/gmake install target_prefix= generating target/release/libhello_rust.so (release) cargo rustc --target-dir target --manifest-path ../../../../ext/hello_rust/Cargo.toml --lib --release -- -C linker=gcc -L native=/home/retro/.rubies/ruby-3.1.2/lib -C link-arg=-lm Finished release [optimized] target(s) in 0.09s installing hello_rust.so to /home/retro/code/hello_rust/lib/hello_rust /usr/bin/install -c -m 0755 hello_rust.so /home/retro/code//hello_rust/lib/hello_rust cp tmp/x86_64-linux/hello_rust/3.1.2/hello_rust.so tmp/x86_64-linux/stage/lib/hello_rust/hello_rust.so </code></pre></div> <p>And finally, it is possible to call <code>hello</code> method defined in Rust returning a string and printing it to the console.</p> <div class="highlight"><pre class="highlight plaintext"><code>$ bundle exec ruby -rhello_rust -e 'puts HelloRust.hello("Josef")' "Hello from Rust, Josef!" </code></pre></div> <p><em>Feel free to try to break this extension. For example you can try to pass different types of argument (like number or symbol). <a href="https://github.com/matsadler/magnus">magnus</a> is doing a great job <a href="https://github.com/matsadler/magnus#defining-methods">automatically converting</a> all those mistakes with friendly error messages.</em></p> <h2 id="summary">Summary</h2> <p>Starting Bundler 2.4, you can generate gem skeleton with all boilerplate code needed to start using Rust. But it is not only about your custom Rust code you can easily integrate into gems now. Thanks to integration with <a href="https://doc.rust-lang.org/cargo/">cargo</a> (Rust package manager) you can use any of <a href="https://crates.io/">Rust crates</a> available. Rust ecosystem is well known for highly optimized and memory safe libraries. Thanks to <a href="https://github.com/matsadler/magnus">magnus</a> and <code>bundle gem</code> command, it is possible to glue those Rust libraries into Ruby world smoothly. Sky is the limit ;-)</p> <p><em>To see real-life example how powerful could be Rust for data processing, I recommend to check <a href="https://github.com/rubytogether/kirby">kirby project</a> parsing logs for <a href="http://rubygems.org/">rubygems.org</a>.</em></p> Bundler v2.3: Locking the version of Bundler itself https://bundler.io/blog/2022/01/23/bundler-v2-3.html 2022-01-23T16:07:00+00:00 2025-10-20T08:26:09+00:00 David Rodríguez <p>2021 saw a fair amount of development in the RubyGems &amp; Bundler repositories. We tried to release more often than ever to catch and fix bugs and distribute our improvements as early as possible to our users. That has led to 33 patch-level versions in the Bundler 2.x series released about a year ago.</p> <p>Our goal for Bundler 2.3 was to implement a long-wanted feature of being able to fully control the version of Bundler itself an application runs. There’s a long story with this feature, because it was shipped a few years ago in a manner that was too strict and ended up causing more harm than good, so had to be partially reverted.</p> <h2 id="so-how-did-things-work-before-bundler-23">So, how did things work before Bundler 2.3?</h2> <p>Up until now, RubyGems would try to activate the version of Bundler recorded in the <code>Gemfile.lock</code> file if already installed, and would fall back to the highest version installed otherwise. That’s better than nothing, but it did not ensure the exact version in the lockfile was always used, which led to workarounds like <a href="https://bundler.io/blog/2019/05/14/solutions-for-cant-find-gem-bundler-with-executable-bundle.html">manually parsing the lockfile and then installing that version</a>.</p> <h2 id="and-how-do-they-work-now">And how do they work now?</h2> <p>In Bundler 2.3 and up (if you also have RubyGems 3.3 or higher), running <code>bundle install</code> will use the exact version from the BUNDLED WITH section of the lockfile. If that version is not installed before you run <code>bundle install</code>, the running version of Bundler will install the locked version, and then run your original command using the newly-installed locked version.</p> <p>So, if you have a lockfile ending with</p> <div class="highlight"><pre class="highlight plaintext"><code>BUNDLED WITH 2.2.33 </code></pre></div> <p>and you only have Bundler 2.3.5 installed, you’ll see the following output when running <code>bundle install</code>.</p> <div class="highlight"><pre class="highlight plaintext"><code>$ bundle install Bundler 2.3.5 is running, but your lockfile was generated with 2.2.33. Installing Bundler 2.2.33 and restarting using that version. Fetching gem metadata from https://rubygems.org/. Fetching bundler 2.2.33 Installing bundler 2.2.33 ... </code></pre></div> <p>After that all your commands will automatically use Bundler 2.2.33, as specified by your lockfile. If you want to upgrade the Bundler version used by your application, you can run <code>bundle update --bundler</code>, and your lockfile will be regenerated using the latest version. From that moment, all users of the lockfile will automatically pick up the new version, no matter whether they have a newer or older version installed instead.</p> <p>But..</p> <h2 id="why-are-we-doing-this">Why are we doing this?</h2> <p>Being able to lock the version of Bundler itself, just like Bundler is able to lock other dependencies, has been a goal of the Bundler team for years. There are a number of benefits of locking your dependencies, like avoiding dependency nightmares where your application breaks due to third party releases, or avoiding “works on my machine” issues. Bundler has a ton of features and edge cases, and</p> <ul> <li> <p>We sometimes introduce regressions when trying to improve things. Locking the version of Bundler prevents those issues from hitting you.</p> </li> <li> <p>Once in a while we need to put a security fix out there. Being able to lock the Bundler version allows you to ensure that every user of your application gets a secure version of Bundler.</p> </li> <li> <p>Occasionally, you might want to use a new feature of the Bundler DSL in your Gemfile. However, old versions of Bundler don’t understand this feature and you don’t want to suddenly break things for the users of yours that use those old versions. With version locking this is no longer a concern. Bundler is now able to upgrade itself to the version that your application understands.</p> </li> </ul> <p>All in all, we aim to provide a less surprising, less error prone and more consistent experience when using Bundler, and let each application be in control of the version that they use, and the moment that they upgrade.</p> <h2 id="whats-coming-next">What’s coming next?</h2> <p>Future enhancements to this feature might include:</p> <ul> <li>Full support for <code>gem "bundler", "&lt;arbitrary_requirement&gt;"</code> in <code>Gemfile</code>.</li> <li>Automatic update of Bundler when running <code>bundle install</code> without a lockfile.</li> <li>Automatic update of Bundler when running <code>bundle update</code>.</li> </ul> <p>In other words, our end goal is to be able to treat Bundler just like any other dependency of your application.</p> A more secure bundler: We fixed our source priorities. https://bundler.io/blog/2021/02/15/a-more-secure-bundler-we-fixed-our-source-priorities.html 2021-02-15T11:33:00+00:00 2025-10-20T08:26:09+00:00 David Rodríguez <blockquote> <p><strong>NOTE</strong>: Whereas the issue was initially fixed in bundler 2.2.10, it had to be reverted due to several problems caused by the initial approach. A proper fix was finally released with bundler 2.2.18.</p> </blockquote> <h2 id="what-happened">What happened?</h2> <p>Last week <a href="https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610">an article about “Dependency Confusion”</a> hit the news, where a developer was able to make thousands of dollars on bug bounty programs from big tech companies, by pushing libraries to public repositories that ended up unintentionally being installed into these companies servers.</p> <p>The developer was able to expose (in a non-malicious way) a vulnerability present in well-known dependency managers, where given a library name they will end up preferring installing it from a public source rather than from a private source. This is not secure because the name in the public source is controlled by the first person claiming it, whereas the name in the private source is controlled by the private source owner.</p> <p>Unfortunately, Bundler had this vulnerability.</p> <p>There’s good news though:</p> <h2 id="things-were-safe-on-the-rubygemsorg-side">Things were safe on the rubygems.org side</h2> <p>The rubygems.org organization, in collaboration with <a href="https://diffend.io">diffend.io</a>, have a pretty good malicious code detection system. In fact, the only reason this developer was able to make all this money by getting these gems installed in companies private servers is because our system detected them, flagged them for us, and we determined them to be non-malicious, and only for research purposes. If those gems had been malicious, we wouldn’t have allowed them.</p> <p>Check out the <a href="https://mensfeld.pl/2021/02/rubygems-dependency-confusion-side-of-things/">more detailed blog post</a> from our diffend.io friends about what happened in the rubygems.org side of things, and how things were secure.</p> <h2 id="the-issue-has-been-fixed-in-bundler-2210">The issue has been fixed in bundler 2.2.10</h2> <p>We have shipped bundler 2.2.10 with a fix, and now whenever you specify a block source in your <code>Gemfile</code>, bundler will prioritize it when resolving direct dependencies specified inside, and also transitive dependencies of those. So in the following situation both <code>my-private-gem</code> and <code>my-another-private-gem</code> will be picked up from <code>https://my-private-server</code>, even if someone pushes a higher version with the same name to <code>rubygems.org</code>:</p> <div class="highlight"><pre class="highlight ruby"><code><span class="c1"># my-private-gem.gemspec</span> <span class="c1"># ...</span> <span class="n">gem</span><span class="p">.</span><span class="nf">dependency</span><span class="p">(</span><span class="s2">"my-another-private-gem"</span><span class="p">)</span> </code></pre></div> <div class="highlight"><pre class="highlight ruby"><code><span class="c1"># Gemfile</span> <span class="n">source</span> <span class="s2">"https://rubygems.org"</span> <span class="n">source</span> <span class="s2">"https://my-private-server"</span> <span class="k">do</span> <span class="n">gem</span> <span class="s2">"my-private-gem"</span> <span class="k">end</span> </code></pre></div> <p>Make sure you upgrade your bundler version either by running <code>gem install bundler</code>, or by upgrading rubygems through <code>gem update --system</code> (which will install bundler 2.2.10 as a default gem).</p> <h2 id="final-notes">Final notes</h2> <p>The bundler team had actually been aware of this issue for a while, but unfortunately lacks resources to take care of everything we need to take care, so the fix was postponed for too long. Maintaining the rubygems.org infrastructure and its client libraries requires a big amount of work and we barely manage to keep up with it. So, if your company really needs us to stay on top of these issues, please consider funding <a href="https://rubytogether.org/">RubyTogether</a> ❤️.</p> <p>That’s all for today,</p> <p>Happy bundling!</p> <hr /> <p>Deivid, André and the RubyGems team</p>