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

Add support for Rails 8.0 #2705

Merged
merged 1 commit into from
Nov 22, 2024
Merged

Add support for Rails 8.0 #2705

merged 1 commit into from
Nov 22, 2024

Conversation

nickcharlton
Copy link
Member

@nickcharlton nickcharlton commented Nov 8, 2024

We needed to:

  • Bring over quite a few things from rails app:update, which hopefully should make future upgrades easier,
  • Fix a change to the enum ActiveModel signature, which changed between Rails 6.0 and 7.0,
  • Add a version check from 7.0 for raise_on_missing_callback_actions,
  • Make a few changes to CI (on top of Separate Appraisal runs from primary test runs #2712) to adjust the Ruby versions we run CI against.

https://rubyonrails.org/2024/11/7/rails-8-no-paas-required

Closes #2703

@nickcharlton
Copy link
Member Author

So far, this is just a quick first-pass at opening up support, so we can make a little bit of progress with each additional change.

As of right now, we're stuck here, as rails-i18n is missing Rails 8.0 support: svenfuchs/rails-i18n#1130

$ setup
The Gemfile's dependencies are satisfied
>> bundle check --gemfile='/Users/nickcharlton/projects/thoughtbot/administrate/gemfiles/rails60.gemfile' || bundle install --gemfile='/Users/nickcharlton/projects/thoughtbot/administrate/gemfiles/rails60.gemfile' --retry 1
The Gemfile's dependencies are satisfied
>> bundle check --gemfile='/Users/nickcharlton/projects/thoughtbot/administrate/gemfiles/rails61.gemfile' || bundle install --gemfile='/Users/nickcharlton/projects/thoughtbot/administrate/gemfiles/rails61.gemfile' --retry 1
The Gemfile's dependencies are satisfied
>> bundle check --gemfile='/Users/nickcharlton/projects/thoughtbot/administrate/gemfiles/rails70.gemfile' || bundle install --gemfile='/Users/nickcharlton/projects/thoughtbot/administrate/gemfiles/rails70.gemfile' --retry 1
The Gemfile's dependencies are satisfied
>> bundle check --gemfile='/Users/nickcharlton/projects/thoughtbot/administrate/gemfiles/rails80.gemfile' || bundle install --gemfile='/Users/nickcharlton/projects/thoughtbot/administrate/gemfiles/rails80.gemfile' --retry 1
Bundler can't satisfy your Gemfile's dependencies.
Install missing gems with `bundle install`.
Fetching gem metadata from https://rubygems.org/..........
Resolving dependencies...
Could not find compatible versions

Because rails-i18n < 0.1.6 depends on activesupport ~> 3
  and rails-i18n >= 0.1.6, < 4.0.0 depends on i18n ~> 0.5,
  rails-i18n < 4.0.0 requires activesupport ~> 3 or i18n ~> 0.5.
And because rails-i18n >= 4.0.0, < 4.0.6 depends on i18n ~> 0.6,
  rails-i18n < 4.0.6 requires activesupport ~> 3 or i18n >= 0.5, < 1.A.
And because rails-i18n >= 4.0.6, < 5.1.0 depends on i18n ~> 0.7
  and rails-i18n >= 5.1.0, < 6.0.0 depends on railties >= 5.0, < 6,
  rails-i18n < 6.0.0 requires activesupport ~> 3 or i18n >= 0.5, < 1.A or railties >= 5.0, < 6.
And because rails-i18n >= 6.0.0, < 7.0.1 depends on railties >= 6.0.0, < 7
  and activesupport >= 6.1.0 depends on i18n >= 1.6, < 2,
  if activesupport >= 6.1.0 and rails-i18n < 7.0.1 then railties >= 5.0, < 7.
And because rails-i18n >= 7.0.1 depends on railties >= 6.0.0, < 8
  and rails >= 8.0.0 depends on activesupport = 8.0.0,
  rails >= 8.0.0 requires railties >= 5.0, < 8.
So, because rails >= 8.0.0 depends on railties = 8.0.0
  and rails80.gemfile depends on rails ~> 8.0,
  version solving has failed.

@mpvosseller
Copy link

@nickcharlton looks like the rails-i18n gem has been updated & released. 🎉

@nickcharlton
Copy link
Member Author

With rails-i18n released, I've been able to run through and do a bunch more of the Rails 8.0 upgrade.

I've done a bunch of it, now I'm going to wait for CI to fail and see what else we need to do.

@nickcharlton
Copy link
Member Author

I'm left fighting with Ruby, Rails versions and testing the combination along with Appraisal on CI.

However, those are details in the scheme of getting this PR merged. If someone would like to test it out on their Rails 8.0 upgrade, feel free to go ahead — I'd be especially interested if there are any issues you see which might mean this takes longer than getting CI right.

@nickcharlton
Copy link
Member Author

I'd started down the path of messing about with running Appraisals differently, because it was failing for various reasons. But remembered I'd actually started on this back in Feb as #2524.

I've now merged that, so we're back in Ruby vs. Rails expected compatibility.

It's time to drop some Ruby versions ahead of cutting the final version of v1, but unless this takes longer than today, I'd like to do that after this PR is merged. We'll see how it goes.

@januszm
Copy link
Contributor

januszm commented Nov 18, 2024

Failing specs are only for Ruby 3.1 and won't be possible to fix I guess:

activesupport-8.0.0 requires ruby version >= 3.2.0, which is incompatible with ...

To complete this PR we just might need to drop support for Ruby 3.1 in the next release? Can't wait for this PR to be merged

@nickcharlton
Copy link
Member Author

I'd been trying a couple of different ideas for fixing CI — as it stands currently, I'm stuck on the following:

  1. We need Appraisal to be installed to run appraisal install,
  2. We can't bundle the main Gemfile because it won't support older versions of Ruby with the Rails 8 dependencies in place,
  3. We can't run Appraisal outside the Gemfile because we hit other issues

I'm going to give it a little more time, but not much before giving in and dropping incompatible Rubies (I'm stubborn, but even that has limits!). We're so close to releasing a significant breaking change anyway (in v1) holding off dropping versions over 3 years old seems a bit much.


I was chatting with @louis-antonopoulos last night, who's working on a brand new Rails 8 application, which started off with Propshaft (as that's now the default). I'll open a new issue for this, but it's something we're going to have to do (but not necessarily in this PR).

@nickcharlton nickcharlton added this to the v1.0.0 milestone Nov 19, 2024
@nickcharlton nickcharlton added the dependencies changes or issues relating to a dependency label Nov 19, 2024
@nickcharlton
Copy link
Member Author

Quite a successful time this afternoon looking at running CI against the different versions of Rails we want. I ended up doing what Appraisal usually does in CI, but manually. This works to a point — but you can't run the schema on older versions of Rails. So if we take this approach, we need a solution to that.

I'm on the fence at the moment about this. I do think the tradeoff of doing things this way is going to be helpful long-term, from seeing it fail the way it does, it's given me confidence it's actually running properly. But it's much more complex.

nickcharlton added a commit that referenced this pull request Nov 21, 2024
With Rails 8, the minimum version of Ruby becomes 3.2. Unless we drop
support for prior Ruby versions (and also Rails versions), the way in
which we were approaching CI can't work. Maintaining support for older
Rails is not difficult because of Administrate itself, but how we
approach testing so it feels unreasonable to drop support (which if we
didn't test against it, we would effectively be doing) because it made
CI harder to do. And we _can_ make it work, so we will.

Previously, we ran the setup for the project as usual, and then ran
setup for the Appraisals. This served two functions:

1. Make Appraisal available in the bundle,
2. Setup the database for running tests against

However, in the CI matrix, we support multiple different versions of
Ruby (3.0 and up to 3.3). As we try and add Rails 8.0, this means we
can't run `bundle install` on those versions of Ruby below 3.2 as it's a
dependency constraint on Rails itself.

From experiments, we also can't:

1. Install Appraisal outside of the bundle, because it references gems
   in a way that Bundler is there to solve,
2. Load newer `schema.rb` files in older versions of Rails. Rails 7
   introduced versioned schemas, and future schema versions can't be run
   with older versions of Rails.

Instead, what we _can_ do is run the project setup inside a container
configured to use the database in the CI environment, then manually do
what Appraisal is doing to avoid issues bundling.

This container will always use the current development version of Ruby
(3.2.2, at the time of this commit) taken from the `.ruby-version` file,
in which we run just enough to setup the database and ensure the later
tests can run against it.

It's unlikely that Administrate would do something which wasn't
supported at the database level, but not impossible. However these tests
would catch that (from experience: Rails falls back to a string on
unknown types, so it's even less likely to fail).

Extracted from #2705.
nickcharlton added a commit that referenced this pull request Nov 21, 2024
With Rails 8, the minimum version of Ruby becomes 3.2. Unless we drop
support for prior Ruby versions (and also Rails versions), the way in
which we were approaching CI can't work. Maintaining support for older
Rails is not difficult because of Administrate itself, but how we
approach testing so it feels unreasonable to drop support (which if we
didn't test against it, we would effectively be doing) because it made
CI harder to do. And we _can_ make it work, so we will.

Previously, we ran the setup for the project as usual, and then ran
setup for the Appraisals. This served two functions:

1. Make Appraisal available in the bundle,
2. Setup the database for running tests against

However, in the CI matrix, we support multiple different versions of
Ruby (3.0 and up to 3.3). As we try and add Rails 8.0, this means we
can't run `bundle install` on those versions of Ruby below 3.2 as it's a
dependency constraint on Rails itself.

From experiments, we also can't:

1. Install Appraisal outside of the bundle, because it references gems
   in a way that Bundler is there to solve,
2. Load newer `schema.rb` files in older versions of Rails. Rails 7
   introduced versioned schemas, and future schema versions can't be run
   with older versions of Rails.

Instead, what we _can_ do is run the project setup inside a container
configured to use the database in the CI environment, then manually do
what Appraisal is doing to avoid issues bundling.

This container will always use the current development version of Ruby
(3.2.2, at the time of this commit) taken from the `.ruby-version` file,
in which we run just enough to setup the database and ensure the later
tests can run against it.

It's unlikely that Administrate would do something which wasn't
supported at the database level, but not impossible. However these tests
would catch that (from experience: Rails falls back to a string on
unknown types, so it's even less likely to fail).

Extracted from #2705.
nickcharlton added a commit that referenced this pull request Nov 21, 2024
With Rails 8, the minimum version of Ruby becomes 3.2. Unless we drop
support for prior Ruby versions (and also Rails versions), the way in
which we were approaching CI can't work. Maintaining support for older
Rails is not difficult because of Administrate itself, but how we
approach testing so it feels unreasonable to drop support (which if we
didn't test against it, we would effectively be doing) because it made
CI harder to do. And we _can_ make it work, so we will.

Previously, we ran the setup for the project as usual, and then ran
setup for the Appraisals. This served two functions:

1. Make Appraisal available in the bundle,
2. Setup the database for running tests against

However, in the CI matrix, we support multiple different versions of
Ruby (3.0 and up to 3.3). As we try and add Rails 8.0, this means we
can't run `bundle install` on those versions of Ruby below 3.2 as it's a
dependency constraint on Rails itself.

From experiments, we also can't:

1. Install Appraisal outside of the bundle, because it references gems
   in a way that Bundler is there to solve,
2. Load newer `schema.rb` files in older versions of Rails. Rails 7
   introduced versioned schemas, and future schema versions can't be run
   with older versions of Rails.

Instead, what we _can_ do is run the project setup inside a container
configured to use the database in the CI environment, then manually do
what Appraisal is doing to avoid issues bundling.

This container will always use the current development version of Ruby
(3.2.2, at the time of this commit) taken from the `.ruby-version` file,
in which we run just enough to setup the database and ensure the later
tests can run against it.

It's unlikely that Administrate would do something which wasn't
supported at the database level, but not impossible. However these tests
would catch that (from experience: Rails falls back to a string on
unknown types, so it's even less likely to fail).

We also need to remove the Ruby version specification from the generated
Appraisal gemfiles, as otherwise these won't install. Whilst they seemed
to be valid outside of this way of running things, here, they are not.
We just use `sed` to remove it in place, as it can be discarded later
and removing it would cause problems with Heroku deployment of the demo
app.

Extracted from #2705.
nickcharlton added a commit that referenced this pull request Nov 21, 2024
With Rails 8, the minimum version of Ruby becomes 3.2. Unless we drop
support for prior Ruby versions (and also Rails versions), the way in
which we were approaching CI can't work. Maintaining support for older
Rails is not difficult because of Administrate itself, but how we
approach testing so it feels unreasonable to drop support (which if we
didn't test against it, we would effectively be doing) because it made
CI harder to do. And we _can_ make it work, so we will.

Previously, we ran the setup for the project as usual, and then ran
setup for the Appraisals. This served two functions:

1. Make Appraisal available in the bundle,
2. Setup the database for running tests against

However, in the CI matrix, we support multiple different versions of
Ruby (3.0 and up to 3.3). As we try and add Rails 8.0, this means we
can't run `bundle install` on those versions of Ruby below 3.2 as it's a
dependency constraint on Rails itself.

From experiments, we also can't:

1. Install Appraisal outside of the bundle, because it references gems
   in a way that Bundler is there to solve,
2. Load newer `schema.rb` files in older versions of Rails. Rails 7
   introduced versioned schemas, and future schema versions can't be run
   with older versions of Rails.

Instead, what we _can_ do is run the project setup inside a container
configured to use the database in the CI environment, then manually do
what Appraisal is doing to avoid issues bundling.

This container will always use the current development version of Ruby
(3.2.2, at the time of this commit) taken from the `.ruby-version` file,
in which we run just enough to setup the database and ensure the later
tests can run against it.

It's unlikely that Administrate would do something which wasn't
supported at the database level, but not impossible. However these tests
would catch that (from experience: Rails falls back to a string on
unknown types, so it's even less likely to fail).

We also need to remove the Ruby version specification from the generated
Appraisal gemfiles, as otherwise these won't install. Whilst they seemed
to be valid outside of this way of running things, here, they are not.
We just use `sed` to remove it in place, as it can be discarded later
and removing it would cause problems with Heroku deployment of the demo
app.

Finally, we inline the previously extracted Action from #2524. The
intent was to reduce duplication, but the order of operations are now so
different it's not worth it and it would only be used in one place.

Extracted from #2705.

Re-inline extracted Action
nickcharlton added a commit that referenced this pull request Nov 21, 2024
With Rails 8, the minimum version of Ruby becomes 3.2. Unless we drop
support for prior Ruby versions (and also Rails versions), the way in
which we were approaching CI can't work. Maintaining support for older
Rails is not difficult because of Administrate itself, but how we
approach testing so it feels unreasonable to drop support (which if we
didn't test against it, we would effectively be doing) because it made
CI harder to do. And we _can_ make it work, so we will.

Previously, we ran the setup for the project as usual, and then ran
setup for the Appraisals. This served two functions:

1. Make Appraisal available in the bundle,
2. Setup the database for running tests against

However, in the CI matrix, we support multiple different versions of
Ruby (3.0 and up to 3.3). As we try and add Rails 8.0, this means we
can't run `bundle install` on those versions of Ruby below 3.2 as it's a
dependency constraint on Rails itself.

From experiments, we also can't:

1. Install Appraisal outside of the bundle, because it references gems
   in a way that Bundler is there to solve,
2. Load newer `schema.rb` files in older versions of Rails. Rails 7
   introduced versioned schemas, and future schema versions can't be run
   with older versions of Rails.

Instead, what we _can_ do is run the project setup inside a container
configured to use the database in the CI environment, then manually do
what Appraisal is doing to avoid issues bundling.

This container will always use the current development version of Ruby
(3.2.2, at the time of this commit) taken from the `.ruby-version` file,
in which we run just enough to setup the database and ensure the later
tests can run against it.

It's unlikely that Administrate would do something which wasn't
supported at the database level, but not impossible. However these tests
would catch that (from experience: Rails falls back to a string on
unknown types, so it's even less likely to fail).

We also need to remove the Ruby version specification from the generated
Appraisal gemfiles, as otherwise these won't install. Whilst they seemed
to be valid outside of this way of running things, here, they are not.
We just use `sed` to remove it in place, as it can be discarded later
and removing it would cause problems with Heroku deployment of the demo
app.

Finally, we inline the previously extracted Action from #2524. The
intent was to reduce duplication, but the order of operations are now so
different it's not worth it and it would only be used in one place.

Extracted from #2705.

Re-inline extracted Action
nickcharlton added a commit that referenced this pull request Nov 21, 2024
With Rails 8, the minimum version of Ruby becomes 3.2. Unless we drop
support for prior Ruby versions (and also Rails versions), the way in
which we were approaching CI can't work. Maintaining support for older
Rails is not difficult because of Administrate itself, but how we
approach testing so it feels unreasonable to drop support (which if we
didn't test against it, we would effectively be doing) because it made
CI harder to do. And we _can_ make it work, so we will.

Previously, we ran the setup for the project as usual, and then ran
setup for the Appraisals. This served two functions:

1. Make Appraisal available in the bundle,
2. Setup the database for running tests against

However, in the CI matrix, we support multiple different versions of
Ruby (3.0 and up to 3.3). As we try and add Rails 8.0, this means we
can't run `bundle install` on those versions of Ruby below 3.2 as it's a
dependency constraint on Rails itself.

From experiments, we also can't:

1. Install Appraisal outside of the bundle, because it references gems
   in a way that Bundler is there to solve,
2. Load newer `schema.rb` files in older versions of Rails. Rails 7
   introduced versioned schemas, and future schema versions can't be run
   with older versions of Rails.

Instead, what we _can_ do is run the project setup inside a container
configured to use the database in the CI environment, then manually do
what Appraisal is doing to avoid issues bundling.

This container will always use the current development version of Ruby
(3.2.2, at the time of this commit) taken from the `.ruby-version` file,
in which we run just enough to setup the database and ensure the later
tests can run against it.

It's unlikely that Administrate would do something which wasn't
supported at the database level, but not impossible. However these tests
would catch that (from experience: Rails falls back to a string on
unknown types, so it's even less likely to fail).

We also need to remove the Ruby version specification from the generated
Appraisal gemfiles, as otherwise these won't install. Whilst they seemed
to be valid outside of this way of running things, here, they are not.
We just use `sed` to remove it in place, as it can be discarded later
and removing it would cause problems with Heroku deployment of the demo
app.

Finally, we inline the previously extracted Action from #2524. The
intent was to reduce duplication, but the order of operations are now so
different it's not worth it and it would only be used in one place.

Extracted from #2705.
nickcharlton added a commit that referenced this pull request Nov 21, 2024
With Rails 8, the minimum version of Ruby becomes 3.2. Unless we drop
support for prior Ruby versions (and also Rails versions), the way in
which we were approaching CI can't work. Maintaining support for older
Rails is not difficult because of Administrate itself, but how we
approach testing so it feels unreasonable to drop support (which if we
didn't test against it, we would effectively be doing) because it made
CI harder to do. And we _can_ make it work, so we will.

Previously, we ran the setup for the project as usual, and then ran
setup for the Appraisals. This served two functions:

1. Make Appraisal available in the bundle,
2. Setup the database for running tests against

However, in the CI matrix, we support multiple different versions of
Ruby (3.0 and up to 3.3). As we try and add Rails 8.0, this means we
can't run `bundle install` on those versions of Ruby below 3.2 as it's a
dependency constraint on Rails itself.

From experiments, we also can't:

1. Install Appraisal outside of the bundle, because it references gems
   in a way that Bundler is there to solve,
2. Load newer `schema.rb` files in older versions of Rails. Rails 7
   introduced versioned schemas, and future schema versions can't be run
   with older versions of Rails.

Instead, what we _can_ do is run the project setup inside a container
configured to use the database in the CI environment, then manually do
what Appraisal is doing to avoid issues bundling.

This container will always use the current development version of Ruby
(3.2.2, at the time of this commit) taken from the `.ruby-version` file,
in which we run just enough to setup the database and ensure the later
tests can run against it.

It's unlikely that Administrate would do something which wasn't
supported at the database level, but not impossible. However these tests
would catch that (from experience: Rails falls back to a string on
unknown types, so it's even less likely to fail).

We also need to remove the Ruby version specification from the generated
Appraisal gemfiles, as otherwise these won't install. Whilst they seemed
to be valid outside of this way of running things, here, they are not.
We just use `sed` to remove it in place, as it can be discarded later
and removing it would cause problems with Heroku deployment of the demo
app.

Finally, we inline the previously extracted Action from #2524. The
intent was to reduce duplication, but the order of operations are now so
different it's not worth it and it would only be used in one place.

Extracted from #2705.
@nickcharlton nickcharlton changed the base branch from main to nc-prepare-ci-for-rails-8 November 21, 2024 17:26
@nickcharlton nickcharlton force-pushed the nc-support-rails-8 branch 2 times, most recently from 363e1ea to 108308c Compare November 21, 2024 18:00
@nickcharlton nickcharlton marked this pull request as ready for review November 21, 2024 18:05
@nickcharlton
Copy link
Member Author

This is now ready to go. It took some re-thinking around CI, which I'm glad I did.

I'm going to merge this in tomorrow morning so I can take another look at it, but it's working fine so far.

nickcharlton added a commit that referenced this pull request Nov 22, 2024
With Rails 8, the minimum version of Ruby becomes 3.2. Unless we drop
support for prior Ruby versions (and also Rails versions), the way in
which we were approaching CI can't work. Maintaining support for older
Rails is not difficult because of Administrate itself, but how we
approach testing so it feels unreasonable to drop support (which if we
didn't test against it, we would effectively be doing) because it made
CI harder to do. And we _can_ make it work, so we will.

Previously, we ran the setup for the project as usual, and then ran
setup for the Appraisals. This served two functions:

1. Make Appraisal available in the bundle,
2. Setup the database for running tests against

However, in the CI matrix, we support multiple different versions of
Ruby (3.0 and up to 3.3). As we try and add Rails 8.0, this means we
can't run `bundle install` on those versions of Ruby below 3.2 as it's a
dependency constraint on Rails itself.

From experiments, we also can't:

1. Install Appraisal outside of the bundle, because it references gems
   in a way that Bundler is there to solve,
2. Load newer `schema.rb` files in older versions of Rails. Rails 7
   introduced versioned schemas, and future schema versions can't be run
   with older versions of Rails.

Instead, what we _can_ do is run the project setup inside a container
configured to use the database in the CI environment, then manually do
what Appraisal is doing to avoid issues bundling.

This container will always use the current development version of Ruby
(3.2.2, at the time of this commit) taken from the `.ruby-version` file,
in which we run just enough to setup the database and ensure the later
tests can run against it.

It's unlikely that Administrate would do something which wasn't
supported at the database level, but not impossible. However these tests
would catch that (from experience: Rails falls back to a string on
unknown types, so it's even less likely to fail).

We also need to remove the Ruby version specification from the generated
Appraisal gemfiles, as otherwise these won't install. Whilst they seemed
to be valid outside of this way of running things, here, they are not.
We just use `sed` to remove it in place, as it can be discarded later
and removing it would cause problems with Heroku deployment of the demo
app.

Finally, we inline the previously extracted Action from #2524. The
intent was to reduce duplication, but the order of operations are now so
different it's not worth it and it would only be used in one place.

Extracted from #2705.
Base automatically changed from nc-prepare-ci-for-rails-8 to main November 22, 2024 09:50
We needed to:

* Bring over quite a few things from `rails app:update`, which hopefully
  should make future upgrades easier,
* Fix a change to the `enum` `ActiveModel` signature, which changed
  between Rails 6.0 and 7.0,
* Add a version check from 7.0 for `raise_on_missing_callback_actions`,
* Make a few changes to CI (on top of #2712) to adjust the Ruby versions
  we run CI against.

https://rubyonrails.org/2024/11/7/rails-8-no-paas-required

Closes #2703
@nickcharlton nickcharlton merged commit 09babbf into main Nov 22, 2024
22 checks passed
@nickcharlton nickcharlton deleted the nc-support-rails-8 branch November 22, 2024 09:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies changes or issues relating to a dependency
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Rails 8.0 support
3 participants