bundler-cache: true — the one-option Ruby cache in GitHub Actions
Ruby has the tidiest dependency-cache story in all of GitHub Actions: one option on the setup action installs your gems and caches them. If your workflow runs bundle install as its own step, you're doing it the hard way.
The one option
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true # runs bundle install AND caches gemsbundler-cache: true replaces a separate bundle install step: it installs with --deployment-style settings, caches the installed gems keyed on Gemfile.lock + Ruby version, and restores in seconds on later runs. Delete your manual install step — running both does the work twice. jekyll uses exactly this across its CI matrix.
Requirements that trip people
- Check in
Gemfile.lock. The cache key hashes it; without a lockfile the action refuses to cache (and your builds aren't reproducible anyway). For gems, generate it in CI or usecache-versionto bust manually. - Don't combine with
actions/cacheon the same directory — two restores fight; pick one owner for the gem cache. - Native extensions: cached gems are compiled per OS/arch, so a matrix across ubuntu/macos keeps separate caches automatically — nothing to configure, just don't share keys across OSes if you hand-roll.
Version matrix, same option
strategy:
matrix:
ruby: ['3.1', '3.2', '3.3']
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- run: bundle exec rakeEach leg caches independently per Ruby version. Pair with a concurrency group and timeouts and you've covered the big three. See how popular Ruby repos run CI →
These hide across however many workflow files you have, which is exactly why nobody sits down and fixes them. Point GitSpider at your repo and it flags which patterns apply, with the fix for each.
Scan your repo free