Rails 7 upgrade

As promised in Path to Ruby 3.0, 3.1, EL9 and Ubuntu 22.04 - #44 by ekohl there would be a follow up project to upgrade from Rails 6.1 to Rails 7(.1).

The primary motivation is to remain up to date. Rails 6.1 will at some point be out of security support.

This RFC won’t go into detail how exactly we’ll solve things, because we partly don’t know. Instead, we’ll start with 3 major milestones that we need to achieve.

For background, Ruby & Rails Compatibility Table - FastRuby.io | Rails Upgrade Service has a nice list of version compatibility. Even Rails 7.1 still works with Ruby 2.7 (though 3.2 is recommended) so we don’t expect problems with the platforms we deploy on.

Convert the loader to Zeitwerk

This has been long known as something to resolve. Feature #29991: Enable Zeitwerk autoload mode for Rails 6+ - Foreman was opened almost 4 years ago and in the mean time work has been done. It must be resolved because the other way will be dropped.

This is aimed to land in Foreman 3.12. 3.11 will branch in less than a month and we don’t expect to resolve the outstanding issues in time, especially taking in mind that we need some time to stabilize things.

Upgrade to Rails 7.0

Previously a tracker was created for this: Tracker #34647: Rails 7.0 Tracker - Foreman

I already opened a PR that at least gets a basic version running (Rails 7 & Ruby 3.1 by ekohl · Pull Request #9328 · theforeman/foreman · GitHub) and have been using it to split off work that could already be merged. The main pain point was Zeitwerk.

One thing it doesn’t do (yet) is update the defaults to Rails 7.0 defaults. We’ll also need to update the packages. The official upgrading guide is a good starting point:

If all goes well, this could land quickly after Zeitwerk. Possibly in 3.12.

Upgrade to Rails 7.1

This is the latest version. I haven’t done a lot of research on how, but the official guide is, again, a good starting point.

Given the building on uncertainty, I don’t know when this will land.

Sidekiq 7

A big unknown is Sidekiq 7. We’re on 6 now, but it must be checked of this will continue to work with Rails 7. It could significantly increase the scope of this project.

2 Likes

Quick first update.

While we opened a few PRs in the past, @ofedoren has submitted Fixes #29991 - Enable Zeitwerk by ofedoren · Pull Request #10131 · theforeman/foreman · GitHub which is our closest attempt to date. Still work in progress and plugins will likely need work as well.

To keep track, I just created a project. I also started to review open issues on Feature #29991: Enable Zeitwerk autoload mode for Rails 6+ - Foreman.

It’s been a while since the last update because I forgot to set the calendar event as recurring.

@ofedoren has since expanded Fixes #29991 - Enable Zeitwerk by ofedoren · Pull Request #10131 · theforeman/foreman · GitHub and opened PRs to various plugins:

Many of those PRs actually address issues that Fixes #33895 - Set up Zeitwerk inflector by ekohl · Pull Request #10076 · theforeman/foreman · GitHub will introduce. In the short term @ekohl will update Fixes #33895 - Set up Zeitwerk inflector by ekohl · Pull Request #10076 · theforeman/foreman · GitHub to see if HTTP as an acronym is a good idea, or if it breaks too much.

We’ll continue to work on those, but because of availability it may be a bit slower in the coming weeks. Looking at Foreman’s 3.11 schedule the expected GA date is 2024-06-18 so we’ve agreed to aim for merging Zeitwerk shortly after that. In due time we’ll make a proper announcement that we’re going to break plugins.

Because people were off I haven’t updated, but today we decided on a plan to move forward with Zeitwerk. Zeitwerk merge imminent summarizes that so I won’t repeat it here.

After a small break in meetings due to PTO and awaiting branching we started to meet again today.

@ekohl tested Rails 7 & Ruby 3.1 by ekohl · Pull Request #9328 · theforeman/foreman · GitHub rebased on the Zeitwerk patches and found it doesn’t work (registries break). This means Rails 7’s Zeitwerk is a bit different than in Rails 6. @ofedoren will look into this.

We’re still aiming at merging in the first week of September, soon after branching. @ekohl might take PTO around that time, but will ensure someone with sufficient permissions stands by to merge things in various repos.

@ofedoren has been testing with Rails 7 and confirmed my findings: we need additional work around the registries and move them to initializers. He’ll verify if such a change also works with Rails 6.

Rails 7 also introduced some new defaults and some of them break Foreman. Currently identifying which ones and what the best solution is (revert to the old value or change application code).

The original goal was to merge Zeitwerk soon after branching. The current plan is:

  • This week: finish up the Zeitwerk code (either Rails 7 compatible or Rails 6-only) (mostly on @ofedoren)
  • Monday September 2nd: build RPMs in COPR and try to do a full end-to-end test (mostly on @ekohl)
  • Tuesday: hold a go/no-go meeting

That Tuesday there’s also work going on for Foreman 3.12.0-rc2 so it’s probably best to merge things on Wednesday if we decide to proceed.

We had this meeting and decided to proceed with it once the CVE releases were out (which are now officially announced; please go upgrade if you’re affected).

By now @ofedoren has updated all PRs with the correct Foreman 3.13 requirement and removed all temporary commits.

These are the PRs we are going to merge in order. Note tier 2 or higher has dependencies on some plugins. Until a release is available with Zeitwerk enabled, they will fail CI.

This means plugin authors should prepare releases once this is out. They will require at least Foreman 3.13 so you’ll need stable branches for Foreman 3.12 and older.

Edit: a few plugins were missed and the list has been updated

3 Likes

@aruzicka, @ofedoren and I just discussed it and we’ll start merging this later today.

We’ll follow the above list in order. It should be noted that we also need releases after, both for CI (which uses gems) and nightly (which uses packages).

Looking ahead to Rails 7 @ofedoren found some issues with plugins and routes. He thinks Introduce Journey::Ast to avoid extra ast walks by composerinteralia · Pull Request #39935 · rails/rails · GitHub has changed it in a way that breaks for us, but isn’t sure if that’s a bug in Rails or in our code.

I’ve updated the list with checkboxes for “merged” and “released”.

rh_cloud is the only one unmerged, and I am chasing people to do releases :slight_smile:

Thanks to @evgeni’s hard work we now have passing pipelines for most pipelines. foreman-plugins-nightly-deb-test-pipeline [Jenkins] had 1 failure, but that was an infra issue. Given 3/4 did pass, I’m assuming it’ll work.

luna-nightly-rpm-pipeline [Jenkins] at the time of writing is still running. We can see it failed on NameError: uninitialized constant AddSatelliteURLToConfig and that was renamed in foreman_virt_who_configure. That makes me think version 0.5.21 wasn’t present yet when it started.

And foreman_rh_cloud is still open.

1 Like

Further update: I was pulling translations and saw these errors/warnings. These are in the order it executed, so fairly random.

foreman_snapshot_management

2024-09-13T22:09:30 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constants UI and UI::HostDescription.

foreman_leapp

2024-09-13T22:09:37 [W|app|] Setting is not initialized yet, requested value for remote_execution_workers_pool_size will be always nil
2024-09-13T22:09:30 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constants HostMix, HasManyCommon, StripWhitespace, Parameterizable, AuditAssociations::AssociationsDefinitions, ApplicationRecord, EncryptValue, PermissionName, URLSchemaValidator, RegexpValidator, ArrayTypeValidator, ArrayHostnamesIpsValidator, EmailValidator, Setting, ForemanLeapp::TemplateHelper, UI, and UI::HostDescription.

This one is a surprise to me, because we did submit a patch for this repo. Running rae zeitwerk:check:

Hold on, I am eager loading the application.

WARNING: The following directories will only be checked if you configure
them to be eager loaded:

  /home/ekohl/dev/foreman-plugins/foreman_leapp/app/models/auth_sources
  /home/ekohl/dev/foreman-plugins/foreman_leapp/app/models/compute_resources
  /home/ekohl/dev/foreman-plugins/foreman_leapp/app/models/fact_names
  /home/ekohl/dev/foreman-plugins/foreman_leapp/app/models/lookup_keys
  /home/ekohl/dev/foreman-plugins/foreman_leapp/app/models/operatingsystems
  /home/ekohl/dev/foreman-plugins/foreman_leapp/app/models/parameters
  /home/ekohl/dev/foreman-plugins/foreman_leapp/app/models/taxonomies
  /home/ekohl/dev/foreman-plugins/foreman_leapp/app/models/mail_notifications
  /home/ekohl/dev/foreman_leapp/test/

You may verify them manually, or add them to config.eager_load_paths
in config/application.rb and run zeitwerk:check again.

foreman_rh_cloud

2024-09-13T22:09:37 [W|app|] Setting is not initialized yet, requested value for remote_execution_workers_pool_size will be always nil
2024-09-13T22:09:37 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constants Actions, Actions::ObservableAction, HostMix, HasManyCommon, StripWhitespace, Parameterizable, AuditAssociations::AssociationsDefinitions, ApplicationRecord, EncryptValue, PermissionName, URLSchemaValidator, RegexpValidator, ArrayTypeValidator, ArrayHostnamesIpsValidator, EmailValidator, and Setting.

We haven’t merged the patch yet.

foreman_salt

2024-09-13T22:24:00 [W|app|] Setting is not initialized yet, requested value for remote_execution_workers_pool_size will be always nil
2024-09-13T22:24:00 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constants HostMix, HasManyCommon, StripWhitespace, Parameterizable, AuditAssociations::AssociationsDefinitions, ApplicationRecord, EncryptValue, PermissionName, URLSchemaValidator, RegexpValidator, ArrayTypeValidator, ArrayHostnamesIpsValidator, EmailValidator, and Setting.

Here we also merged a patch but zeitwerk:check shows:

Hold on, I am eager loading the application.

WARNING: The following directories will only be checked if you configure
them to be eager loaded:

  /home/ekohl/dev/foreman-plugins/foreman_salt/app/models/auth_sources
  /home/ekohl/dev/foreman-plugins/foreman_salt/app/models/compute_resources
  /home/ekohl/dev/foreman-plugins/foreman_salt/app/models/fact_names
  /home/ekohl/dev/foreman-plugins/foreman_salt/app/models/lookup_keys
  /home/ekohl/dev/foreman-plugins/foreman_salt/app/models/operatingsystems
  /home/ekohl/dev/foreman-plugins/foreman_salt/app/models/parameters
  /home/ekohl/dev/foreman-plugins/foreman_salt/app/models/taxonomies
  /home/ekohl/dev/foreman-plugins/foreman_salt/app/models/mail_notifications

You may verify them manually, or add them to config.eager_load_paths
in config/application.rb and run zeitwerk:check again.

Otherwise, all is good!

foreman_ansible

2024-09-13T22:09:43 [W|app|] Setting is not initialized yet, requested value for remote_execution_workers_pool_size will be always nil
2024-09-13T22:09:43 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constants HostMix, HasManyCommon, StripWhitespace, Parameterizable, AuditAssociations::AssociationsDefinitions, ApplicationRecord, EncryptValue, PermissionName, URLSchemaValidator, RegexpValidator, ArrayTypeValidator, ArrayHostnamesIpsValidator, EmailValidator, and Setting.

This looks the same as others. We’re starting to see a trend that they all pull in foreman_remote_execution.

foreman_theme_satellite

2024-09-13T22:09:45 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constant ForemanThemeSatellite::RendererMethods.

We patched here, so this is surprising

foreman_remote_execution

2024-09-13T22:09:47 [W|app|] Setting is not initialized yet, requested value for remote_execution_workers_pool_size will be always nil
2024-09-13T22:09:47 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constants HostMix, HasManyCommon, StripWhitespace, Parameterizable, AuditAssociations::AssociationsDefinitions, ApplicationRecord, EncryptValue, PermissionName, URLSchemaValidator, RegexpValidator, ArrayTypeValidator, ArrayHostnamesIpsValidator, EmailValidator, and Setting.

This is what we saw previously in plugins that pulled in REX. Running zeitwerk:check:

Hold on, I am eager loading the application.

WARNING: The following directories will only be checked if you configure
them to be eager loaded:

  /home/ekohl/dev/foreman-plugins/foreman_remote_execution/app/models/auth_sources
  /home/ekohl/dev/foreman-plugins/foreman_remote_execution/app/models/compute_resources
  /home/ekohl/dev/foreman-plugins/foreman_remote_execution/app/models/fact_names
  /home/ekohl/dev/foreman-plugins/foreman_remote_execution/app/models/lookup_keys
  /home/ekohl/dev/foreman-plugins/foreman_remote_execution/app/models/operatingsystems
  /home/ekohl/dev/foreman-plugins/foreman_remote_execution/app/models/parameters
  /home/ekohl/dev/foreman-plugins/foreman_remote_execution/app/models/taxonomies
  /home/ekohl/dev/foreman-plugins/foreman_remote_execution/app/models/mail_notifications

You may verify them manually, or add them to config.eager_load_paths
in config/application.rb and run zeitwerk:check again.

Otherwise, all is good!

Note those are Foreman locations, not REX itself. Not sure what it exactly is.

foreman_azure_rm

2024-09-13T22:09:59 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constants HostMix, HasManyCommon, StripWhitespace, Parameterizable, AuditAssociations::AssociationsDefinitions, ApplicationRecord, DirtyAssociations, Taxonomix, EncryptValue, Encryptable, PermissionName, Authorizable, EnsureNotUsedBy, ComputeResource, ForemanAzureRm::VMExtensions, ForemanAzureRm::VMExtensions::ManagedVM, and ForemanAzureRm::AzureRm.

Here we had patches, but there are certainly foreman_azure_rm specific classes.

foreman_kubevirt

2024-09-13T22:10:05 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constants HostMix, HasManyCommon, StripWhitespace, Parameterizable, AuditAssociations::AssociationsDefinitions, ApplicationRecord, DirtyAssociations, Taxonomix, EncryptValue, Encryptable, PermissionName, Authorizable, EnsureNotUsedBy, ComputeResource, and ForemanKubevirt::Kubevirt.
2024-09-13T22:10:05 [W|app|] Foreman-Kubevirt: skipping engine hook (expected file /home/ekohl/dev/foreman_kubevirt/app/models/concerns/fog_extensions/kubevirt/vmnic.rb to define constant FogExtensions::Kubevirt::Vmnic, but didn't)

Here we thought we didn’t need a patch, but there are kubevirt specifics so a patch is probably still needed.

foreman_proxmox

2024-09-13T22:09:30 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constants UI and UI::HostDescription.
2024-09-13T22:09:33 [W|app|] Failed to load Proxmox extension uninitialized constant ForemanFogProxmox

A patch will be needed to become compatible.

foreman_leapp

2024-09-13T22:09:30 [W|app|] DEPRECATION WARNING: Initialization autoloaded the constants HostMix, HasManyCommon, StripWhitespace, Parameterizable, AuditAssociations::AssociationsDefinitions, ApplicationRecord, EncryptValue, PermissionName, URLSchemaValidator, RegexpValidator, ArrayTypeValidator, ArrayHostnamesIpsValidator, EmailValidator, Setting, ForemanLeapp::TemplateHelper, UI, and UI::HostDescription.

Here I finally notice HostMix is specifically mentioned.

This is this week’s summary. Next week we’ll continue.

Is our goal to eventually land on Rails 7.2? And if so, what are seeing as the path to get there (e.g. 7.0 then 7.2)?

@ofedoren and I just had another sync up.

First on the practical matter: I’ll be out of the office for the next 2 weeks. @ofedoren may also take time off in October.

Then for the current status. We’re almost to the point where Luna passes again. Then there may be still some other things to clean up before 3.13 releases, but we feel the Zeitwerk change is in good shape now.

@ofedoren is working on upgrading to Rails 7.0 in Fixes #37825 - Upgrade Rails to 7.0 by ofedoren · Pull Request #10299 · theforeman/foreman · GitHub and there’s only 1 test failure remaining:

ActiveRecord::SubclassNotFound: Invalid single-table inheritance type: Nic::Managed is not a subclass of Nic::Bond

This is a failure we also sometimes saw with Zeitwerk, but it’s unclear where it exactly comes from. Ongoing investigation.

With core is mostly working, the plugins are being investigated. REX and OpenSCAP are the first 2 to look at.

Then we spoke about Rails 7.1 and beyond. At the time we didn’t look at it in detail, but added an action item to investigate Ruby 2.7 compatibility. To answer the question: Articles on Compatibility at FastRuby.io | Rails Upgrade Service tells us Rails 7.1 is still Ruby 2.7 compatible, but 7.2 needs Ruby 3.1.

Right now we have:

OS Ruby Notes
Debian 11 Ruby 2.7 We’d like to drop it and move to Debian 12, but that’s blocked
Debian 12 Ruby 3.1 Blocked on Puppetserver being available. Otherwise Debian 12 support is ready. Reportedly that’s worked on, but it’s taking forever
Ubuntu 20.04 Ruby 2.7 This meeting reminded me we should deprecate 20.04 in Foreman 3.12 and drop it in 3.13. We already support Ubuntu 22.04
Ubuntu 22.04 Ruby 3.0
Ubuntu 24.04 Ruby 3.2 Not yet supported by Foreman
EL 8 Ruby 2.7 Will be dropped with Foreman 3.13
EL 9 Ruby 3.0 Newer versions available in modules, but we’d like to avoid modules as long as we can
EL 10 Ruby 3.3 Not yet supported by Foreman

As you can see, requiring Ruby 3.1+ will require some OS updates. So for this effort I’d first like to focus on Rails 7.1. We may deliver Rails 7.0 in Foreman 3.13 and 7.1 in 3.14, or jump straight to 7.1 in 3.14. Around early to mid October we’ll see where we are. Stabilization week for Foreman 3.13 starts at the end of October.

4 Likes

Just a small error in your table I think. Second entry of Ubuntu 22.04 should be Ubuntu 24.04, correct?

Yes, corrected now.