ruby/setup-ruby or actions/cache - caching Ruby gems on Github Actions
Tags: ruby, github, testing, rails
Published: 2021-04-06 18:51:25

How to start CI build faster by loading Ruby gems from cache on Github Actions? You can start running your tests for a Ruby on Rails project quicker if you manage to set up all dependencies in a short amount of time. Caching can be helpful with that. Ruby gems needed for your project can be cached by Github Actions and thanks to that they can be loaded much faster when you run a new CI build.

You will learn how to configure Github Actions using:

* [actions/cache](https://github.com/actions/cache) - it's a popular solution to cache Ruby gems.
* [ruby/setup-ruby](https://github.com/ruby/setup-ruby) - it's a solution to install a specific Ruby version and cache Ruby gems with bundler. Two features in one action.

## actions/cache - just cache dependencies

[Actions/cache](https://github.com/actions/cache) is a popular solution that can be used to save data into the cache and restore it during the next CI build. It's often used for Ruby on Rails projects that also use `actions/setup-ruby` for managing the Ruby version on Github Actions.

Let's look at the Github Actions caching config example using `actions/cache`.

```yaml
# .github/workflows/main.yml
name: Main
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - uses: actions/cache@v2
        with:
          path: vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-

      - name: Bundle install
        env:
          RAILS_ENV: test
        run: |
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
```

* You need to specify a directory path that will be cached. It's `vendor/bundle` in our case.
* You also generate a unique cache `key` based on the OS version and `Gemfile.lock` file. When you change the operating system version or you install a new gem and `Gemfile.lock` changes then as a result the new `key` value will be generated.
* You need to configure the bundler to install all your Ruby gems to the directory `vendor/bundle`.
* You can use bundler options:
  * `--jobs 4` - install gems using parallel workers. This allows faster gems installation.
  * `--retry 3` - makes 3 attempts to connect to Rubygems if there is a network issue (for instance temporary downtime of Rubygems.org)

If you would like to see the full YAML config for the Github Actions and Rails project you can take a look at some of our articles:

* [How to run RSpec on GitHub Actions for Ruby on Rails app using parallel jobs](https://docs.knapsackpro.com/2019/how-to-run-rspec-on-github-actions-for-ruby-on-rails-app-using-parallel-jobs)
* [GitHub Actions CI config for Ruby on Rails project with MySQL, Redis, Elasticsearch - how to run parallel tests](https://docs.knapsackpro.com/2019/github-actions-ci-config-for-ruby-on-rails-project-with-mysql-redis-elasticsearch-how-to-run-parallel-tests)
* [How to run slow RSpec files on Github Actions with parallel jobs by doing an auto split of the spec file by test examples](https://docs.knapsackpro.com/2020/how-to-run-slow-rspec-files-on-github-actions-with-parallel-jobs-by-doing-an-auto-split-of-the-spec-file-by-test-examples)
* [Cucumber BDD testing using Github Actions parallel jobs to run tests quicker](https://docs.knapsackpro.com/2021/cucumber-bdd-testing-using-github-actions-parallel-jobs-to-run-tests-quicker)

## ruby/setup-ruby - install Ruby and cache gems

In the previous section, we mentioned the `actions/setup-ruby` is often used with Ruby on Rails projects. The `actions/setup-ruby` has been deprecated so it's recommended to use `ruby/setup-ruby` action nowadays. It already has caching feature that you could use. Let's see how.

```yaml
# .github/workflows/main.yml
name: Main
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    - uses: ruby/setup-ruby@v1
      with:
        # Not needed with a .ruby-version file
        ruby-version: 2.7
        # runs 'bundle install' and caches installed gems automatically
        bundler-cache: true

    # run RSpec tests
    - run: bundle exec rspec
```

As you can see using `ruby/setup-ruby` for managing the Ruby version and gems caching is much simpler. You just add an option `bundler-cache: true` and that's it.

You can read in [`ruby/setup-ruby` documentation](https://github.com/ruby/setup-ruby#caching-bundle-install-automatically):

"It is also possible to cache gems manually, but this is not recommended because it is verbose and very difficult to do correctly. There are many concerns which means using `actions/cache` is never enough for caching gems (e.g., incomplete cache key, cleaning old gems when restoring from another key, correctly hashing the lockfile if not checked in, OS versions, ABI compatibility for ruby-head, etc). So, please use `bundler-cache: true` instead..."

## Summary

You saw 2 ways of caching Ruby gems on Github Actions. There are also other ways to make your CI build faster like running tests in parallel. You can learn more about [test parallelisation here](https://docs.knapsackpro.com/2020/how-to-speed-up-ruby-and-javascript-tests-with-ci-parallelisation) or simply check the [Knapsack Pro](https://knapsackpro.com/?utm_source=devto&utm_medium=blog_post&utm_campaign=devto-how-to-load-ruby-gems-from-cache-on-github-actions) homepage.