From 45367bb6e7f05f7c33cb83657663da2d036fd2b6 Mon Sep 17 00:00:00 2001 From: Schneems Date: Fri, 13 Dec 2024 17:00:44 -0600 Subject: [PATCH] Add support for pre-release ruby versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-releases in ruby use either `-` or `.` and touch the last number, versus patch identifiers start with `p`. This commit now captures identifiers such as `.rc1` or `.preview2` The state of tooling is confusing, as different tools manipulate values differently: ``` $ cat Gemfile source 'https://rubygems.org' ruby "3.4.0-rc1" gem 'rake' ⛄️ 3.4.0 🚀 /private/tmp/aa82068ba3124d84c76d7faf156888a5 (main) $ cat Gemfile.lock GEM remote: https://rubygems.org/ specs: rake (13.2.1) PLATFORMS arm64-darwin-23 ruby DEPENDENCIES rake RUBY VERSION ruby 3.4.0.rc1 BUNDLED WITH 2.5.23 ``` Here's some more context: - https://github.com/heroku/docker-heroku-ruby-builder/blob/175b5c15104cb809e1a0adc2c2a9902f94083954/lib/version_parts.rb#L1-L57 - https://github.com/heroku/docker-heroku-ruby-builder/blob/a41f31c72a74df6bcb4f9266e12192b0af83da98/shared/src/download_ruby_version.rs#L73-L93 Our versions are stored on S3 like this: ``` s3://heroku-buildpack-ruby/heroku-24/arm64/ruby-3.4.0.rc1.tgz ``` --- commons/src/gemfile_lock.rs | 74 ++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/commons/src/gemfile_lock.rs b/commons/src/gemfile_lock.rs index 455222de..9249b692 100644 --- a/commons/src/gemfile_lock.rs +++ b/commons/src/gemfile_lock.rs @@ -118,8 +118,9 @@ impl FromStr for GemfileLock { fn from_str(string: &str) -> Result { let bundled_with_re = Regex::new("BUNDLED WITH\\s (\\d+\\.\\d+\\.\\d+)") .expect("Internal error: Bad regex"); // Checked via clippy - let main_ruby_version_re = Regex::new("RUBY VERSION\\s ruby (\\d+\\.\\d+\\.\\d+)") - .expect("Internal error: Bad regex"); // Checked via clippy + let main_ruby_version_re = + Regex::new("RUBY VERSION\\s ruby (\\d+\\.\\d+\\.\\d+((-|\\.)\\S*\\d+)?)") + .expect("Internal error: Bad regex"); // Checked via clippy let jruby_version_re = Regex::new("\\(jruby ((\\d+|\\.)+)\\)").expect("Internal error: Bad regex"); // Checked via clippy @@ -152,6 +153,75 @@ impl FromStr for GemfileLock { mod tests { use super::*; + #[test] + fn test_does_not_capture_patch_version() { + let info = GemfileLock::from_str( + r" +RUBY VERSION + ruby 3.3.5p100 + +BUNDLED WITH + 2.3.4 +", + ) + .unwrap(); + + assert_eq!( + info.bundler_version, + BundlerVersion::Explicit("2.3.4".to_string()) + ); + assert_eq!( + info.ruby_version, + RubyVersion::Explicit("3.3.5".to_string()) + ); + } + + #[test] + fn test_rc_dot_version() { + let info = GemfileLock::from_str( + r" +RUBY VERSION + ruby 3.4.0.rc1 + +BUNDLED WITH + 2.3.4 +", + ) + .unwrap(); + + assert_eq!( + info.bundler_version, + BundlerVersion::Explicit("2.3.4".to_string()) + ); + assert_eq!( + info.ruby_version, + RubyVersion::Explicit("3.4.0.rc1".to_string()) + ); + } + + #[test] + fn test_preview_version() { + let info = GemfileLock::from_str( + r" +RUBY VERSION + ruby 3.4.0.preview2 + +BUNDLED WITH + 2.3.4 +", + ) + .unwrap(); + + assert_eq!( + info.bundler_version, + BundlerVersion::Explicit("2.3.4".to_string()) + ); + assert_eq!( + info.ruby_version, + RubyVersion::Explicit("3.4.0.preview2".to_string()) + ); + } + #[test] fn test_parse_gemfile_lock() { let info = GemfileLock::from_str(