Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #37825 - Upgrade Rails to 7.0 #10299

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from

Conversation

ofedoren
Copy link
Member

Based on #10131, but with additional commit needed for Rails upgrade.

Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

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

In #9328 I also updated spring. Is that not needed? I recall running into it, but that could have been a Ruby thing or I was just looking at changelogs.

@@ -5,7 +5,7 @@ module Token
included do
has_one :token, :foreign_key => :host_id, :dependent => :destroy, :inverse_of => :host, :class_name => 'Token::Build'

scope :for_token, ->(token) { joins(:token).where(:tokens => { :value => token }).where("expires >= ?", Time.now.utc.to_s(:db)).select('hosts.*') }
scope :for_token, ->(token) { joins(:token).where(:tokens => { :value => token }).where("expires >= ?", Time.now.utc.to_fs(:db)).select('hosts.*') }
Copy link
Member

Choose a reason for hiding this comment

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

TIL: there's .to_fs in Rails. I wonder if Rails is smart enough to understand

Suggested change
scope :for_token, ->(token) { joins(:token).where(:tokens => { :value => token }).where("expires >= ?", Time.now.utc.to_fs(:db)).select('hosts.*') }
scope :for_token, ->(token) { joins(:token).where(:tokens => { :value => token }).where("expires >= ?", Time.now.utc).select('hosts.*') }

Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

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

Have you tried if moving the settings into initializers works with Rails 6.1?

Comment on lines 94 to +95
class ::FakePlugin; end
class ::FakePlugin::FakeModel; end
class ::FakePlugin::FakeModel < ApplicationRecord; end
Copy link
Member

Choose a reason for hiding this comment

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

Should this even be

module FakePlugin
  class FakeModel < ApplicationRecord
  end
end

@ofedoren ofedoren force-pushed the rails-7.0 branch 2 times, most recently from b2971c8 to c93acc6 Compare September 16, 2024 14:10
@ofedoren ofedoren changed the title Rails 7.0 Fixes #37825 - Upgrade Rails to 7.0 Sep 16, 2024
@ofedoren ofedoren marked this pull request as ready for review September 16, 2024 15:02
@ofedoren ofedoren requested a review from a team as a code owner September 16, 2024 15:02
@ekohl ekohl mentioned this pull request Sep 17, 2024
@ofedoren
Copy link
Member Author

There left only one test failure, I'm looking into it, for now I've got no clue :/

Apart from that, it's ready unless we want to be more correct and apply/incorporate these changes: https://railsdiff.org/6.1.7.8/7.0.8.4

@ofedoren
Copy link
Member Author

Now it fails due to ldap_fluff, since it's locked on active_support < 7 (https://github.com/theforeman/ldap_fluff/blob/master/ldap_fluff.gemspec#L21). Weird that it didn't fail before...

Also, @ekohl and @adamruzicka or maybe @ShimShtein, since you have more experience with the codebase and Rails, could you please help me get why the test fails? I'll be out for the next week (30.09 - 06.10), so I hope we won't waste that week.

Regarding the test: I think it's due to code reloading happening somewhere in the test:units suit since running each of test/models, test/helpers and test/unit separately works, it works even if run rails test test/models test/helpers test/unit, which is the same what rake test:units does. Setting test_order = :sorted doesn't help. Also, I've noticed that for some reason it can pass twice in a row, but another run would fail.

app/models/nic/base.rb Outdated Show resolved Hide resolved
@ofedoren
Copy link
Member Author

ofedoren commented Oct 9, 2024

Finally, it's green and with minimal changes needed. Ready for full review.

@@ -15,13 +15,5 @@ def new(attributes = nil, &block)
super
end
end

def save(*args, **kwargs)
Copy link
Member

Choose a reason for hiding this comment

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

So this was the whole problem? That it set an instance variable on the class? That looks nasty and I wonder how that worked in the past.

From reading the Rails source I get the impression should handle this itself.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it seems so. I couldn't find a reason why we did that at the first place, so I hope removing doesn't break anything.

I'm still going to try basic processes (CRUDing a virtual host, running jobs, some Katello-related stuff, oscap, etc) to verify PRs after everything open is green.

@ekohl
Copy link
Member

ekohl commented Oct 22, 2024

As noted in a meeting, the failure may be due to nulldb:

- 'assets:precompile RAILS_ENV=production DATABASE_URL=nulldb://nohost'

Copy link
Member

@ekohl ekohl left a comment

Choose a reason for hiding this comment

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

@ofedoren I see you now disable spring for integration tests and enable bootsnap for tests. Do you consider the issue resolved with that?

Additionally, is there a way we could use spring for integration tests? Possibly by explicitly stopping the server `

@@ -10,7 +10,8 @@
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Disable reloading for integration tests
config.cache_classes = ARGV.grep(/test\/integration/).any?
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be the other way around? Only enable it when it's none??

Also, https://github.com/rails/spring?tab=readme-ov-file#enable-reloading notes it needs to be false for spring to work.

Another note: https://github.com/rails/spring?tab=readme-ov-file#temporarily-disabling-spring says:

If you're using Spring binstubs, but temporarily don't want commands to run through Spring, set the DISABLE_SPRING environment variable.

@ofedoren
Copy link
Member Author

ofedoren commented Nov 1, 2024

@ofedoren I see you now disable spring for integration tests and enable bootsnap for tests. Do you consider the issue resolved with that?

I'd say so, yes. Mostly because of spring being disabled for integrations. I don't think bootsnap did anything though. I just enabled that since it should be quite safe and maybe help us in the future.

Additionally, is there a way we could use spring for integration tests? Possibly by explicitly stopping the server

How that will help except for running integration tests on local dev setup? I mean, the whole point of spring for tests is to reduce time between individual calls/runs after the first one. In CI it doesn't matter, since there is only one (the first) run. For local dev runs it makes life easier, thus I've tried to leave the cache_classes set to false for other test types (e.g. units). Integration test suite takes a long time anyway, it easier to use CI for that then wait for local results. Moreover, we didn't have reloading for tests ever before.

Honestly, I'm quite surprised that reloading for units/functionals seems to work at all. I'd say reloading was (and still is) mostly unsupported within Foreman and even if it worked, it kidna shouldn't (I might be wrong though, just an impression).

Also, https://github.com/rails/spring?tab=readme-ov-file#enable-reloading notes it needs to be false for spring to work.

Yes, cache_classes set to false is the same as enable_reloading set to true starting Rails 7.1. Spring with Rails 7.0 forces reloading to be set to true for test environment as well, which is per my opinion weird: dev env with reloading makes sense to make and see the changes faster, but the test environment should rather mimic prod env otherwise what's the point to write something just to see a green circle.

If you're using Spring binstubs, but temporarily don't want commands to run through Spring, set the DISABLE_SPRING environment variable.

Yeap, noticed that too and I thought to use that for CI workflow, but then it would make devs use it for their runs, which I've tried to avoid. This PR (the commit with spring conditionally disabled) tries to make as little invasive changes as possible without changing any already existing workflows: spring is not nuked, it can be still used by devs (although it won't work properly anyway), it's even supported for most test suits (except integrations), no additional env variables must be set to run commands.

I'd love having code reloading working properly, but it seems it's quite complicated to make it work in Foreman (I might lack deeper knowledge about Rails internals though, so if anyone wants to fix that, please do. Fresh eyes make miracles). I disabled spring for integration tests since reloading takes too much time (although it shouldn't) causing timeouts, messes up constant ids, which leads to errors such as organization_obj.class <= Organization #=> false.

Without this patch Ansible-related scopes for Host::Managed.includes()
would look like:
[ { host_ansible_roles: :ansible_roles }, { ansible_role: [{ ansible_variables:
[:lookup_values] }] } ], which for some reason worked before Rails 7.
After this patch, it looks like:
[ { host_ansible_roles: { ansible_role: [{ ansible_variables:
[:lookup_values] }] } } ].
# Rails 7.0 changed this to OpenSSL::Digest::SHA256
# We'd probably need a rotator:
# https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html#key-generator-digest-class-changing-to-use-sha256
config.active_support.hash_digest_class = OpenSSL::Digest::SHA1
Copy link
Member Author

Choose a reason for hiding this comment

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

This is tricky one, I've noticed that only when Katello started failing with some hashes not being matched.

Although, this is safe for now, I'd say we need to migrate from SHA1 since RHEL9 won't support it for cert signing purposes at least: https://bugs.ruby-lang.org/issues/19307
(https://github.com/Katello/katello/pull/11155/files#diff-f6f4727f55ce6e9824ffc740bc9494410dd954416f3bbf50799f38b6738e9fcfL49)
and Rails' defaults to SHA256 for caching already.

If we change this now, we'd probably need that (https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html#key-generator-digest-class-changing-to-use-sha256) thingy as well as some changes in Katello since I've noticed it heavily utilizes https://github.com/Katello/katello/blob/master/app/lib/katello/util/data.rb#L9 for creating some labels/ids? https://github.com/Katello/katello/blob/master/app/models/katello/content_view_environment.rb#L117, which will break with SHA256. Although, we can fix it in Katello itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

2 participants