I'm reading about workflow/actions/CI and trying to understand how github actions work.
I have this workflow on github actions (I chose one available on Github) for Ruby on Rails.
name: "Ruby on Rails CI"
on:
push:
branches: ["master"]
pull_request:
branches: ["master"]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11-alpine
ports:
- "5432:5432"
env:
POSTGRES_DB: rails_test
POSTGRES_USER: rails
POSTGRES_PASSWORD: password
env:
RAILS_ENV: test
DATABASE_URL: "postgres://rails:password@localhost:5432/rails_test"
steps:
- name: Checkout code
uses: actions/checkout@v3
# Add or replace dependency steps here
- name: Install Ruby and gems
uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
with:
bundler-cache: true
# Add or replace database setup steps here
- name: Set up database schema
run: bin/rails db:schema:load
# Add or replace test runners here
- name: Run tests
run: bin/rails test:system
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install Ruby and gems
uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
with:
bundler-cache: true
# Add or replace any other lints here
- name: Lint Ruby files
run: rubocop --parallel
And I'm receiving this error during the lint ruby files step.
Run rubocop --parallel
rubocop --parallel
shell: /usr/bin/bash -e {0}
/home/runner/work/_temp/ba9b7df9-2b25-4f55-acc3-8349cc07d754.sh: line 1: rubocop: command not found
Error: Process completed with exit code 127.
My gemfile it's updated with rubocop gems. Also already run a bundle to install.
gem 'rubocop', require: false
gem 'rubocop-rails', require: false
I did try changing in the test/lint job the line rubocop --parallel
to bundle exec rubocop --parallel
, but received another error related to another gem rubocop-discourse.
Everything is normal locally when I use the same commands.
After some testing, removing the line bundler-cache: true from the lint steps made it work. I don't know why, and I still want to understand why. Also, I kept only the rubocop and rubocop-rails in the install.
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.1.2
- run: gem install rubocop rubocop-rails
- name: Rubocop Lint
run: rubocop --parallel
In the GitHub runner, the workflow;
name: "rubocop lint"
on: workflow_dispatch
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install Ruby and gems
uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
with:
ruby-version: 3.1.2
bundler-cache: true
- run: echo $PATH | tr ':' '\n'
- run: bundle info rubocop
- run: gem which rubocop
- name: Lint Ruby files
run: rubocop --parallel
with the Gemfile
source "https://rubygems.org"
gem 'rubocop', require: false
gem 'rubocop-rails', require: false
will show that gem binaries are added to the path at /opt/hostedtoolcache/Ruby/3.1.2/x64/bin
, but that the bundle install
run inside the action installed the gems to the vendor path;
/home/runner/work/<repo>/<repo>/vendor/bundle/ruby/3.1.0/gems/rubocop-1.52.1
This path can usually be configured, but it's being hard set in the action, here, to $pwd/vendor/bundle
. So using the cache means you'll have to use bundle exec
.
Bundler knows where these gems and their binaries are installed at, but because they are being installed in the vendor path, they are not in the system wide gem binaries /opt/hostedtoolcache/Ruby/3.1.2/x64/bin
Removing bundler-cache: true
and adding the step - run: gem install rubocop rubocop-rails
means the gems will be installed at the system path, i.e. their binaries are available at the ruby bin path.
In terms of understanding why one works and the other doesn't, that's why. gem install
is installing to the gem home, and the action is setting the installation location to the vendor folder, which is not in the path.
If bundle exec rubocop
is giving a different error, that'd be related to some other component of your project -- bundle exec
would be the canonical way of invoking the executable script installed by bundler