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

Allow rails 7 gems in gemspec #715

Merged
merged 7 commits into from
Jun 3, 2024
Merged

Conversation

jrafanie
Copy link
Member

@jrafanie jrafanie commented Jan 12, 2024

Allow rails 7 gems in gemspec

Depends on:

  • Allow rails 7 gems in gemspec activerecord-id_regions#33
  • New id_regions release (0.4.0)
  • Extracted backward compatible changes: Backward compatible rails 7 changes #735
  • Fix failures creating associations in migration specs due to ActiveRecord::AssociationTypeMismatch errors. Rails 7 only. (associations classes not matching stub models)
  • Fix "secrets" related test failures with rails 7 (mock/stubs on stub models)
  • Cleanup ENV stubbing 20180606155924_move_ansible_container_secrets_into_database (workaround inability to mock/stub stub models).

The commits should be reviewable one by one.

Rails 7 changed the way migrations are run. The migration class
constant is now removed and the file is reloaded between migrations.

This means tests should not use expect/allow on migration stub classes
as the constant stubbed is not the same constant the migration is run against.

Additionally, comparisons of objects created before the migration with ones
after will also not work. In that case, you can assert by id or other
attributes instead of comparing objects.

Rails also checks association classes are correct and will also not match
expectations. For example, instead of using host to create or query
the host association, use host_id instead. This also works with has_manys
such as miq_product_feature_ids.

See rails/rails#42198

@jrafanie jrafanie changed the title Allow rails 7 gems in gemspec [WIP] Allow rails 7 gems in gemspec Jan 17, 2024
@miq-bot miq-bot added the stale label Apr 22, 2024
@miq-bot
Copy link
Member

miq-bot commented Apr 22, 2024

This pull request has been automatically marked as stale because it has not been updated for at least 3 months.

If these changes are still valid, please remove the stale label, make any changes requested by reviewers (if any), and ensure that this issue is being looked at by the assigned/reviewer(s).

@jrafanie jrafanie force-pushed the allow_rails_7 branch 2 times, most recently from 8e80b26 to 5f6d70a Compare May 14, 2024 16:11
@jrafanie jrafanie changed the title [WIP] Allow rails 7 gems in gemspec Allow rails 7 gems in gemspec May 14, 2024
@miq-bot miq-bot removed the wip label May 14, 2024
@kbrock
Copy link
Member

kbrock commented May 14, 2024

rails 7.0 supports ruby 3.0 and 3.1 - so at least according to that, it should work

@jrafanie
Copy link
Member Author

Oh, these are fun errors... looks like our migration_stub method is returning a cached constant and any associations you define in your migration "stub" fail under rails 7 because it's not a refresh association class.

@kbrock
Copy link
Member

kbrock commented May 14, 2024

sigh. ping if you need to pair on this.
no ideas at this time

@kbrock kbrock self-assigned this May 15, 2024
@jrafanie jrafanie added wip and removed stale labels May 22, 2024
@jrafanie jrafanie changed the title Allow rails 7 gems in gemspec [WIP] Allow rails 7 gems in gemspec May 22, 2024
@jrafanie jrafanie force-pushed the allow_rails_7 branch 2 times, most recently from 3ae12a5 to 7e1b854 Compare May 24, 2024 17:57
@jrafanie jrafanie force-pushed the allow_rails_7 branch 3 times, most recently from 6e4c5d8 to d641800 Compare May 29, 2024 15:40
@jrafanie
Copy link
Member Author

Ok, all green, now to clean up the ENV stubbing migration 20180606155924_move_ansible_container_secrets_into_database

"~>7.0.8"
else
# Default local bundling to use this version for generating migrations
"~>6.1.4"
Copy link
Member Author

Choose a reason for hiding this comment

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

We're still defaulting to rails 6.1 for new migrations.

if Rails.env.test? && ENV['CA_CERT_FILE']
ENV['CA_CERT_FILE']
else
CA_CERT_FILE
Copy link
Member Author

@jrafanie jrafanie May 29, 2024

Choose a reason for hiding this comment

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

These methods were added to inject different behavior in test vs production. This is because we can't inject this behavior into the migration stub classes. See a9ac761

Copy link
Member

@kbrock kbrock May 30, 2024

Choose a reason for hiding this comment

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

can we change the definition of CA_CERT_FILE instead?

CA_CERT_FILE = ENV[] || "const".freeze

and do these need to be test only?

Copy link
Member

Choose a reason for hiding this comment

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

no. ignore

can we just do:

def ca_cert_file
  ENV.fetch("CA_CERT_FILE", "/run/secrets/kubernetes.io/serviceaccount/ca.crt")
end

or maybe ENV[].presence || ""

Copy link
Member Author

Choose a reason for hiding this comment

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

and do these need to be test only?

Yes, my objective was to not change the migration to add test code into it. I think what is here is a fair enough workaround to avoid test code in migrations while still being able to work with rails 7 neutering the ability to do allow/expect on the stub migration models.

Copy link
Member Author

Choose a reason for hiding this comment

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

def ca_cert_file
  ENV.fetch("CA_CERT_FILE", "/run/secrets/kubernetes.io/serviceaccount/ca.crt")
end

I was trying not to change the behavior of production migrations. While the proposed code reads, I really didn't want to change the behavior of past migrations.

@@ -111,7 +117,9 @@
end

def expect_request
expect(described_class).to receive(:read_token).with(token_path).and_return("totally-a-token")
token.write("totally-a-token")
token.close
Copy link
Member Author

Choose a reason for hiding this comment

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

Avoid the expectation on the migration stub constant since it's been removed and re-loaded by the migration.

Copy link
Member

Choose a reason for hiding this comment

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

I also like avoiding expect all together.

👍

miq_request_stub.create!(:type => 'ServiceTemplateProvisionRequest', :miq_approvals => [miq_approval_stub.create!])
miq_request_stub.create!(:type => 'MiqProvisionRequest', :miq_approval_ids => [miq_approval_stub.create!.id])
miq_request_stub.create!(:type => 'MiqHostProvisionRequest', :miq_approval_ids => [miq_approval_stub.create!.id])
miq_request_stub.create!(:type => 'ServiceTemplateProvisionRequest', :miq_approval_ids => [miq_approval_stub.create!.id])
Copy link
Member Author

Choose a reason for hiding this comment

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

avoid calling the association methods because rails does a class lookup check which will fail with rails 7 since our stub class constant has been removed by rails 7 by the time this is run and so it doesn't match the expected association class object.

@@ -97,7 +97,8 @@
:type => "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::VaultCredential"
)
expect(auth.manager_ref).to be_nil
expect(described_class).to_not receive(:pg_connection)
allow(PG::Connection).to receive(:new).and_call_original
expect(PG::Connection).to_not receive(:new).with(a_hash_including(:dbname => "awx"))
Copy link
Member Author

Choose a reason for hiding this comment

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

Again, avoid expectations on the migration class constant as it's been removed and re-loaded by the time these expectations are reached.

@jrafanie jrafanie changed the title [WIP] Allow rails 7 gems in gemspec Allow rails 7 gems in gemspec May 29, 2024
@jrafanie jrafanie removed the wip label May 29, 2024
@jrafanie
Copy link
Member Author

Ok, all green and cleaned up. The commits should be reviewable one by one.

Rails 7 changed the way migrations are run.  The migration class
constant is now removed and the file is reloaded between migrations.

This means tests should not use expect/allow on migration stub classes
as the constant stubbed is not the same constant the migration is run against.

Additionally, comparisons of objects created before the migration with ones
after will also not work.  In that case, you can assert by id or other
attributes instead of comparing objects.

Rails also checks association classes are correct and will also not match
expectations.  For example, instead of using host to create or query
the host association, use host_id instead.  This also works with has_manys
such as miq_product_feature_ids.

See https://www.github.com/rails/rails/pull/42198
Rails 7 changed the way migrations are run.  The migration class
constant is now removed and the file is reloaded between migrations.

This means tests should not use expect/allow on migration stub classes
as the constant stubbed is not the same constant the migration is run against.

Additionally, comparisons of objects created before the migration with ones
after will also not work.  In that case, you can assert by id or other
attributes instead of comparing objects.

Rails also checks association classes are correct and will also not match
expectations.  For example, instead of using host to create or query
the host association, use host_id instead.  This also works with has_manys
such as miq_product_feature_ids.

See https://www.github.com/rails/rails/pull/42198
Rails 7 changed the way migrations are run.  The migration class
constant is now removed and the file is reloaded between migrations.

This means tests should not use expect/allow on migration stub classes
as the constant stubbed is not the same constant the migration is run against.

Additionally, comparisons of objects created before the migration with ones
after will also not work.  In that case, you can assert by id or other
attributes instead of comparing objects.

Rails also checks association classes are correct and will also not match
expectations.  For example, instead of using host to create or query
the host association, use host_id instead.  This also works with has_manys
such as miq_product_feature_ids.

See https://www.github.com/rails/rails/pull/42198
Rails 7 changed the way migrations are run.  The migration class
constant is now removed and the file is reloaded between migrations.

This means tests should not use expect/allow on migration stub classes
as the constant stubbed is not the same constant the migration is run against.

Additionally, comparisons of objects created before the migration with ones
after will also not work.  In that case, you can assert by id or other
attributes instead of comparing objects.

Rails also checks association classes are correct and will also not match
expectations.  For example, instead of using host to create or query
the host association, use host_id instead.  This also works with has_manys
such as miq_product_feature_ids.

See https://www.github.com/rails/rails/pull/42198
Rails 7 changed the way migrations are run.  The migration class
constant is now removed and the file is reloaded between migrations.

This means tests should not use expect/allow on migration stub classes
as the constant stubbed is not the same constant the migration is run against.

Additionally, comparisons of objects created before the migration with ones
after will also not work.  In that case, you can assert by id or other
attributes instead of comparing objects.

Rails also checks association classes are correct and will also not match
expectations.  For example, instead of using host to create or query
the host association, use host_id instead.  This also works with has_manys
such as miq_product_feature_ids.

See https://www.github.com/rails/rails/pull/42198
@miq-bot
Copy link
Member

miq-bot commented May 29, 2024

Checked commits jrafanie/manageiq-schema@ae07b43~...9d49ecc with ruby 2.7.8, rubocop 1.56.3, haml-lint 0.51.0, and yamllint
35 files checked, 0 offenses detected
Everything looks fine. ⭐

@Fryguy
Copy link
Member

Fryguy commented May 29, 2024

Can you explain why we need the id changes? There are a gazillion of them. Are the relationships lost or something in the cached stubs?

jrafanie added a commit to jrafanie/manageiq-schema that referenced this pull request May 29, 2024
We already dropped support for rails 6 and lower so
these conditionals are not needed.

Discovered when working on rails 7 support in:
ManageIQ#715
@jrafanie
Copy link
Member Author

jrafanie commented May 29, 2024

Can you explain why we need the id changes? There are a gazillion of them. Are the relationships lost or something in the cached stubs?

Sure, I had it in each commit. Good idea. I just added it to the description:

Rails 7 changed the way migrations are run. The migration class
constant is now removed and the file is reloaded between migrations.

This means tests should not use expect/allow on migration stub classes
as the constant stubbed is not the same constant the migration is run against.

Additionally, comparisons of objects created before the migration with ones
after will also not work. In that case, you can assert by id or other
attributes instead of comparing objects.

Rails also checks association classes are correct and will also not match
expectations. For example, instead of using host to create or query
the host association, use host_id instead. This also works with has_manys
such as miq_product_feature_ids.

See rails/rails#42198

@kbrock
Copy link
Member

kbrock commented May 30, 2024

@jrafanie so you are converting from relations to ids so we can avoid defining relations all together? (e.g.: ext_management_system => ems to ems_id => ems.id)

Seems those are very non-rails specific and can be pulled out of here?

@jrafanie
Copy link
Member Author

@jrafanie so you are converting from relations to ids so we can avoid defining relations all together? (e.g.: ext_management_system => ems to ems_id => ems.id)

Not specifically. I think that's beyond the scope here. The problem is that the association itself has logic to verify the class for the association. This verification doesn't work if you're trying to create an association with an object that is not the expected constant. This worked in 6.1 because the migration was loaded only once and the stub model constant remained. With rails 7, the migration stub model constants are removed and the migration is loaded again, so the classes aren't equivalent. What I'm doing here is avoiding the association method when I'm creating or comparing objects.

The migrations that define the associations can still use those association methods but I'm trying to avoid them in the tests for the issues found with rail 7.

@kbrock kbrock merged commit 428a044 into ManageIQ:master Jun 3, 2024
5 checks passed
@jrafanie jrafanie deleted the allow_rails_7 branch June 3, 2024 20:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants