Irish Chess Union Upgrades to Rails 8.1

Irish Chess Union Upgrades to Rails 8.1

Founded in 1912, the Irish Chess Union (ICU) is the governing body for chess across the island of Ireland. It has about 2,500 members and run entirely by volunteers.

Its website, icu.ie opens a new window , has been maintained by webmaster Jonathan O’Connor since 2015. Earlier this year, Jonathan reached out to us. He wanted help taking the ICU’s Rails application from 7.0 to 8.1.

We used Claude Code and our open source Claude Code Rails Upgrade Skill opens a new window to get it done. We also recorded the sessions as a video series, so other teams could see the methodology in practice.

In this article, we’ll walk through the upgrade, one version at a time, and share what Jonathan thought of the process.

The Irish Chess Union homepage at icu.ie

Here was our challenge

The ICU’s application was built and is maintained by professionals, just not on the clock. Everyone involved works on it nights and weekends, as volunteers. It was written mostly by Mark Orr, a ratings officer who had just retired and wanted to give back to the community.

That project became learning Ruby on Rails and building the ICU a website from scratch. He wrote about 90% of the code that’s still running today. Jonathan took over as webmaster in 2015.

He’d learned Ruby a few years earlier, on a six-week trip to Rwanda building credit card payment systems. Rails’ conventions weren’t as disorienting to him as they are to developers who come to it cold.

He kept the application current on his own for a while. When he upgraded it from Rails 3 to 5, he did it the patient way: bumping the Gemfile one patch version at a time, running the test suite, and fixing whatever the deprecation warnings in the logs pointed at.

His colleague Ben Murray later carried it from 5.0 to 7.0. Then Jonathan tried to take it from 7.0 to 7.1 by himself. The same approach that had worked for years stopped working.

He’d been away from daily Rails work since 2016. The deprecation warnings piled up faster than he could make sense of them.

“It was a lot harder,” he said. Eventually it became impossible to tell which warnings actually mattered.

Here’s how we solved it

We used the same methodology we’ve documented for years: dual-boot the app opens a new window with the next_rails opens a new window gem, and upgrade one minor Rails version at a time, never skipping a hop.

For the ICU, that meant an unhurried climb from 7.0 to 7.1, then 7.2, then 8.0, and finally 8.1. Each hop got its own pull request. Each one had a green test suite against both Rails versions before we merged it and moved to the next.

Here’s what that looks like under the hood, for anyone who hasn’t dual-booted a Ruby app before:

How dual booting works: two Gemfiles, two Rails versions, verified independently

Before we touched the Rails version at all, we spent some time on groundwork.

We set up GitHub Actions, so the ICU had CI for the first time. We patched the Docker configuration, so the app could build against either Gemfile.

That kind of scaffolding is easy to underestimate. It’s usually what makes the rest of the upgrade boring, in a good way.

This was also a great opportunity to share with the community how we leverage our open source Claude Code Rails Upgrade Skill, instead of just publishing it and hoping people would try it themselves. In 3 different pairing sessions, we drove Claude to use the skill to handle the mechanical work that happens in every upgrade project.

Claude handled a lot of the mechanical work in each hop: previewing what rails app:update would change, running the test suite against both Gemfiles, and flagging deprecation warnings before they piled up.

Our engineers, Henrique Medeiros opens a new window , Ariel Juodziukynas opens a new window , Aysan Isayo opens a new window , and Juan Vasquez opens a new window , made the judgment calls the skill is deliberately not built to make on its own.

One of those calls was a small shim in the ICU’s codebase. Even Jonathan, after nearly a decade of maintaining the app, said he never would have found it on his own.

“There’s one thing I would never have found, even if I kept working at trying to figure out how to do the upgrade myself, and that was this shim in our code,” Jonathan said. “I think that’s one of the places where you earn your keep, because these are tricks that people won’t know, since they’re not doing upgrades every day.”

Part of why the rest of the upgrade went smoothly is that the ICU’s codebase is, in Jonathan’s own words, unusually well-behaved.

No monkeypatches. No reopened core classes. No weird code in weird places.

And on top of that: A real test suite with both model and integration coverage.

None of that is guaranteed for an application built by a single volunteer. But Mark Orr and Jonathan had both stuck close to the Rails way, and it showed in how predictable each hop turned out to be.

The ICU never had to pause its own work, either.

Jonathan’s small team of volunteer contributors kept shipping features throughout the upgrade. The app’s Stripe integration, the dependency that worried us most going in since it handles ICU’s membership payments, never broke stride.

See the results

Now the ICU is current on Rails 8.1.

“I didn’t notice any issues at all. There were no breakages at all. You made maybe seven or eight pull requests, probably thirty or forty commits over that time, and they just fitted seamlessly into all our changes. Nothing ever broke. And thank you so much for setting up our Docker, because now we have our tests running on GitHub, which is brilliant.”


Jonathan O’Connor, Webmaster, Irish Chess Union

Here’s one of those pull requests, upgrading the app to Rails 7.2:

Pull request #157, upgrading the ICU application to Rails 7.2

Eight pull requests, somewhere around thirty to forty commits, and zero breakages.

That’s not a coincidence. It’s what a sequential, dual-booted upgrade against a clean codebase and a stable test suite looks like when it goes right.

There’s also a quieter story here, about who can afford this kind of work.

A volunteer-run federation with no engineering budget to speak of got a five-version Rails upgrade done. Not because the work got easier, but because one senior engineer driving Claude Code and our upgrade skill can now get much closer to what it used to take two.

This is a real shift we’re seeing across our upgrade engagements, and it’s a big part of why an organization like the ICU can now afford this kind of work at all.

If you’re trying to make this case internally, here’s some advice on how to pitch a Rails upgrade to your boss opens a new window .

Watch the pairing sessions

We recorded four sessions from this project, so you can watch the actual pairing work instead of just reading about it.

Part 1: Setting up CI

Henrique Medeiros and I spend about an hour setting up CI for the ICU’s application: wiring up GitHub Actions and using Claude Code to work through the setup issues that came up along the way:

Part 2: Dual booting and API compatibility

Henrique and I dig into dual booting and the API differences between Rails 7.0 and 7.1.

We set up next_rails and a Gemfile symlink strategy, chase down a few gem compatibility issues using RailsBump.org opens a new window , and configure GitHub Actions and Docker to run the test suite against both Rails versions:

Part 3: Upgrading to Rails 7.2, and getting ready for 8.0

Juan Vasquez and I carry the app from Rails 7.1 to 7.2, while preparing the codebase for Rails 8.0.

We walk through how the upgrade skill checks the current patch version, confirms dual boot is set up, and generates an upgrade report, then track down a Capybara and Selenium WebDriver compatibility issue opens a new window that turns out to have nothing to do with Rails itself:

Recap: A quick recap of the entire upgrade project

Jonathan and I talk about the project end to end: the ICU’s volunteer culture, why the upgrade stalled at Rails 7.1, the results, and Jonathan’s own take on where AI helps and where he still won’t let it near ICU’s data.

Keep an eye out for the Easter egg: a shim in the ICU’s codebase that Jonathan says he’d never have thought of himself.

Conclusion

The ICU’s upgrade worked because the methodology did the heavy lifting, not the AI on its own. Our AI tooling certainly help speed things up! 🚀

Dual booting, sequential hops, a deprecation-first approach: none of that is new.

What’s new is that Claude Code, guided by a skill that encodes those opinions, can now execute most of it, while our engineers focus on the handful of judgment calls, like that one shim, that still need a human who’s done this before.

It’s worth saying plainly: this went smoothly in part because the ICU’s codebase was clean and well-tested.

A messier application, full of monkeypatches and flaky tests, would have taken longer.

Has your team been putting off a Rails upgrade? Let’s talk opens a new window and get your up to the latest stable versions of Ruby and Rails!

References

All of the pull requests below were merged into the ICU’s master branch, and the full history is public:

You can find the ICU’s full application source code at github.com/irishchessunion/icu_www_app opens a new window , and our own upgrade skill at github.com/ombulabs/claude-code_rails-upgrade-skill opens a new window .

If you want the version-by-version details behind each hop, our Rails Upgrade Series opens a new window covers every jump from 2.3 onward.

Get the book