Ruby in GitHub Actions
The workflow file
The two big hosts describe a pipeline in the same way. This lesson
writes the GitHub file; the next one writes
the GitLab file.
GitHub reads workflows from .github/workflows/.
One YAML file describes when the pipeline runs and what each job does.
For the project from the previous lesson the whole file is ten lines of
YAML plus the step list:
name: CI
on:
push:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: "3.4"
bundler-cache: true
- run: bundle exec rake test
Three things carry the work. actions/checkout
copies the repository into the runner.
ruby/setup-ruby installs the chosen
Ruby and, with
bundler-cache: true, runs
bundle install and caches the result keyed on
Gemfile.lock. The last step is the command from
the previous lesson.
The trigger is the on block: every push and every
pull request. A workflow that runs on a branch nobody merges is noise; a
workflow that runs only on tags misses the bug before the release.
Check that it parses
A YAML file that does not parse fails before any job starts, and the error points at a line rather than at the mistake. Ruby can parse the file with the standard library, which is the quickest check before a push:
ruby -ryaml -e 'YAML.load_file(ARGV[0])' .github/workflows/ci.yml
No output means the file parsed. To see something useful, ask for one value:
ruby -ryaml -e 'p YAML.load_file(ARGV[0])["jobs"]["test"]["steps"].size' .github/workflows/ci.yml
3
Three steps, as written. One Ruby quirk shows up if you print the whole document: the YAML 1.1 parser reads the key on as the boolean true. GitHub parses the file with its own rules and reads it as a string, so the workflow works; the Ruby dump is the odd one out.
The same steps by hand
The workflow has no secret sauce: it installs and it tests. Run the same two commands locally and compare:
Install the gems
bundle install
Fetching gem metadata from https://rubygems.org/...
Resolving dependencies...
Fetching minitest 5.27.0
Installing minitest 5.27.0
Bundle complete! 2 Gemfile dependencies, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Run the tests
bundle exec rake test
Run options: --seed 8918
# Running:
...
Finished in 0.001315s, 2281.3081 runs/s, 3041.7441 assertions/s.
3 runs, 4 assertions, 0 failures, 0 errors, 0 skips
The output above is from running these two commands locally; the runner log is the same text with timestamps around it. When a job fails, this is the section of the log to read first: the failing command and the lines above it, not the top of the page.
What to watch for
bundler-cache: true only helps when
Gemfile.lock is committed. Without the lock file
the cache key changes on every run and the job reinstalls the same gems
every time, which looks like a slow pipeline rather than a missing file.
Pin the Ruby version in the workflow rather than saying latest. A new
Ruby release then arrives as an intentional change with a failing matrix
entry, not as a pipeline that went red during the weekend.
Next: Ruby in GitLab CI
Article author: Arthur Isaev