Skip to content

Fixes #39361 - Add Ruby 3.3 support to Foreman#11004

Open
ofedoren wants to merge 6 commits into
theforeman:developfrom
ofedoren:feat-39361-ruby-3.3
Open

Fixes #39361 - Add Ruby 3.3 support to Foreman#11004
ofedoren wants to merge 6 commits into
theforeman:developfrom
ofedoren:feat-39361-ruby-3.3

Conversation

@ofedoren
Copy link
Copy Markdown
Member

@ofedoren ofedoren commented May 27, 2026

From my local testing it seems we don't need much, thus opening as is to see what CI thinks of it.

Also, please note: we don't drop Ruby 3.0 support, so don't treat this PR as "we can finally use Ruby 3.1-3 new features". We can't :/

@ofedoren ofedoren requested a review from a team as a code owner May 27, 2026 14:37
erb.location = source_name, 0
erb.result(get_binding)
rescue ::SyntaxError => e
new_e = SyntaxError.new(name: source_name, message: e.message)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not necessary, just so it's more obvious what we raise and expect.

assert_equal '2'.to_json, @response.body

post :preview, params: { :template => '<%= 1+ -%>', :id => template }, session: set_session_user
assert_includes @response.body, 'parse error on value'
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message is now different, I decided to use a small, but noticable fragment.

Comment thread .rubocop.yml
inherit_from: .rubocop_todo.yml

AllCops:
TargetRubyVersion: 2.7
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be extracted, but since we're at it...

Comment thread Gemfile
gem 'validates_lengths_from_database', '~> 0.5'
gem 'friendly_id', '>= 5.4.2', '< 6'
gem 'secure_headers', '>= 6.3', '< 8'
gem 'safemode', '>= 1.4', '< 2'
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before 2.0 safemode was not Ruby 3.3 ready.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, packit failure is expected, we need a PR to foreman-packaging which bumps the version for rpm/devel

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to split safemode 2 into its own PR? I don't think there's any blocker to merging that, other than some coordination with packaging.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, I've extracted that into #11007

box = Safemode::Box.new(scope, allowed_helpers, source_name)
erb = ERB.new(source_content, trim_mode: '-')
box.eval(erb.src, allowed_variables)
rescue ::Racc::ParseError => e
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is due to changes of underlying parser in safemode.

@ofedoren
Copy link
Copy Markdown
Member Author

Based on https://community.theforeman.org/t/ruby-3-3-support-across-the-foreman-ecosystem/46602/6 we keep this open till 04.06.2026 and then should have a better picture with how to proceed.

Comment thread app/lib/foreman/http_proxy.rb Outdated
@ofedoren ofedoren force-pushed the feat-39361-ruby-3.3 branch from 59cd415 to 9ffd17d Compare May 29, 2026 15:02
@ofedoren
Copy link
Copy Markdown
Member Author

da88ba9 is for historical or "get the idea" reason

9ffd17d is the fix for da88ba9. After more reviews or if asked, I'll merge them into one.

Comment thread app/models/concerns/host_common.rb Outdated
# We only save a value into the image_file field if the value is not the default path, (which was placed in the entry when it was displayed,)
# and it is not a directory, (ends in /)
value = ((default_image_file == file) || (file.to_s =~ /\/\Z/) || file == "") ? nil : file
value = ((default_image_file == file) || /\/\Z/.match?(file) || file == "") ? nil : file
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this equivalent to:

Suggested change
value = ((default_image_file == file) || /\/\Z/.match?(file) || file == "") ? nil : file
value = (default_image_file == file || file.end_with?('/') || file.empty?) ? nil : file

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed it is, updated.

is_int = (value =~ /\A[-+]?\d+\z/) || value.is_a?(Integer)
is_int = value.to_s.match?(/\A[-+]?\d+\z/) || value.is_a?(Integer)
is_pg = ActiveRecord::Base.connection.adapter_name.downcase.starts_with? 'postgresql'
# Once Postgresql 8 support is removed (used in CentOS 6), this could be replaced to only keep the first form (working well with PG 9)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Speaking of old comments ...

def cast_facts(table, key, operator, value)
is_int = (value =~ /\A[-+]?\d+\z/) || value.is_a?(Integer)
is_int = value.to_s.match?(/\A[-+]?\d+\z/) || value.is_a?(Integer)
is_pg = ActiveRecord::Base.connection.adapter_name.downcase.starts_with? 'postgresql'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fun fact: we dropped non-PG in Foreman 2.0.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've dropped that. Also it now seems that we don't need || value.is_a?(Integer), so dropped that as well.

@ofedoren ofedoren force-pushed the feat-39361-ruby-3.3 branch from 0e95553 to 60d6b7e Compare June 1, 2026 12:28
@stejskalleos stejskalleos self-assigned this Jun 1, 2026
@ogajduse
Copy link
Copy Markdown
Member

ogajduse commented Jun 1, 2026

@ofedoren #11007 is merged. Feel free to rebase if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants