Josh Branchaud
Posted on May 30, 2021
I'm working with a client to urgently upgrade their Rails app from the Heroku-16 stack to the Heroku-18 stack. Heroku has already end-of-life'd the Heroku-16 stack at the beginning of this month. And in a few days, on June 1st, they will completely turn off support patches and new builds of Heroku-16 apps.
The Heroku-18 stack is supported until April 2023 (source).
The minimum Ruby version supported by the Heroku-18 is Ruby 2.4.10 (source).
Testing the Ruby Upgrade Locally
Install the target Ruby version:
$ asdf install ruby 2.4.10
Switch to that Ruby version:
$ asdf local ruby 2.4.10
$ ruby --version
ruby 2.4.10p364 (2020-03-31 revision 67879) [x86_64-darwin19]
Install an older version of bundler (pre 2.x):
$ gem install bundler:1.17.3
Install all the app's gems with for the new Ruby version using the specific version of bundler:
$ bundle _1.17.3_ install
Start up the server locally (connected to whatever DB makes sense) and try things out:
$ bundle exec rails s
Deploying a Preview App
A Preview App is a great way to get this app up and running in a production-like environment. This is an opportunity to further kick the tires of the app. Are there particularities of the production environment and settings or of Heroku that make this app not work? If so, it is best to find out here rather than in production.
This will involve deploy a branch with a new Ruby version to a Preview app on a newer Heroku stack.
Here is a Heroku guide on upgrading the stack of an app.
The recommended way to do this is to create a branch for your app, alter the stack in app.json
and then deploy a preview app (actually called Review Apps) to Heroku. It will use the stack version specified in that JSON file.
{
"stack": "heroku-18"
}
Deploying the Changes to Production
I initially tried to push the Ruby upgrade changes and the app.json
Stack changes directly to production. This led to the Ruby upgrade changes being deployed on the old stack. Despite the changes made to app.json
, Heroku doesn't upgrade the stack for an existing app that way.
An existing app’s stack cannot be changed using app.json. The stack specified is only applied to newly created apps that are a Review App, a Heroku CI test run app, or an app created using a Heroku Buttons. source
Fortunately, the Ruby upgrade changes deployed fine to the existing stack. And the app was able to build and deploy the existing stack because we are still 2 days out from the full deprecation.
How I should have done it was to first set the stack for the app using the Heroku CLI.
$ heroku stack:set heroku-18 -a <app name>
Heroku will apply that stack upgrade on the next build. So once that is set, I should have then pushed up the Ruby upgrade changes.
Because I did it out of order, I had to trigger another production deploy by pushing up an empty commit.
$ git commit --allow-empty -m "Upgrading to heroku-18"
Once that empty commit is on the main branch, I then pushed that directly to the remote's main branch (git push origin main
). This works because I have GitHub integrated with Heroku so that any changes pushed to the main
branch will trigger a deploy. If that wasn't the case, you can trigger a deploy the Heroku way by pushing to the Heroku remote (git push heroku main
).
If you enjoy my writing, consider joining my newsletter or following me on twitter.
Cover photo by Charlota Blunarova on Unsplash
Posted on May 30, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.