Over the Thanksgiving holiday, I took some time to familiarize myself with GitHub Actions and set up a couple of workflows. Here's a quick review of what it takes to run rspec tests using GitHub Actions for a Rails project and a few of my observations.
But first, what are GitHub Actions?
GitHub Actions are small, composable tasks that can be combined to create a workflow. These workflows allow you to plug your team or project's software development lifecycle (SDLC) right into your codebase. You can build, test, package, release, publish, and deploy with these workflows and you can automate the other parts of your process like assigning reviewers or sending notifications to Slack or linting files or checking code coverage.
My First Stab
My first stab at a workflow for running rspec tests went like this:
- From the Actions tab in GitHub, click "Set up this workflow" for the suggested Ruby workflow.
- Configured to run on pull requests to the master branch (or any pushes to that branch that has a pull request created)
- Updated to use my specific version of
ubuntu-18.04
and ruby 2.5.7 - Changed
bundle exec rake
to bebundle exec rspec spec
- Commit and create a pull request to master for this branch
- Watch the action triggered!
- And fail. WOMP WOMP. 😞
The first failure was that Ruby 2.5.7 is not available on the virtual machine.
##[error]Version 2.5.7 not found
After a little digging, I found that (at this precise moment) the ubuntu-18.04
virtual machine only supports Ruby 2.5.5. This project depends on the latest security patched version 2.5.7. The standard actions/setup-ruby
that GitHub suggested won't work. Instead, I found a different one from the marketplace (where this person also encountered this same issue) to install the specific and correct version of Ruby. With this action, I was able to use the right version of Ruby as well as cache it with actions/cache
. It's still a bit pokey, but it worked.
The next roadblock was not being able to find the right bundler version that my Gemfile requires:
Could not find 'bundler' (1.17.3) required by your Gemfile.lock
Whoops. Adding -v 1.17.3
to the bundler install fixed that one.
And then it failed while trying to install the pg
gem:
An error occurred while installing pg (1.0.0), and Bundler cannot continue.
Make sure that `gem install pg -v '1.0.0' --source 'https://rubygems.org/'`
succeeds before bundling.
To solve this problem, we can pull a container with postgresql into our workflow using the services
block, which can be used to host other services like databases or caching in another container.
In our workflow file, it looks like this:
services:
postgres:
image: postgres:10.11
ports: ["5432:5432"]
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
Then we have to install the postgresql client:
- name: Install PostgreSQL 10 Client
run: |
sudo apt-get -yqq install libpq-dev
Note: My original build error with not being able to install the pg
gem was because this libpq-dev
package wasn't available.
And set up the database:
- name: Setup Database
env:
PGHOST: localhost
PGUSER: postgres
RAILS_ENV: test
run: |
gem install bundler -v 1.17.3
bundle install --jobs 4 --retry 3
bin/rails db:setup
Depending on your needs here, you might need bin/rails db:create db:schema:load
instead.
Adding these last three blocks (service
, installing the postgresql client, and setting up the database), our tests now run!
Commit your .github/workflows/ruby.yml
changes. If you're using the GitHub Actions editor, you'll automagically create a pull request with this change and your action will be triggered. If you making these changes locally, push them up and create a pull request and you'll see the action in action.
The Final Version
Not patient enough to follow along or want to just see the final version? Here ya go! This file is located in: .github/workflows/ruby.yml
name: Run Rspec Tests
on:
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-18.04
services:
postgres:
image: postgres:10.11
ports: ["5432:5432"]
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v1
- name: Cache Ruby
uses: actions/cache@preview
id: cache
with:
path: ~/local/rubies
key: ruby-2.5.7
- name: Set up Ruby 2.5.7
uses: clupprich/ruby-build-action@master
id: ruby
with:
ruby-version: 2.5.7
cache-available: ${{ steps.cache.outputs.cache-hit == 'true' }}
- name: Print ruby version
run: ${{ steps.ruby.outputs.ruby-path }} --version
- name: Install PostgreSQL 10
run: |
sudo apt-get -yqq install libpq-dev
- name: Setup Database
env:
PGHOST: localhost
PGUSER: postgres
RAILS_ENV: test
run: |
gem install bundler -v 1.17.3
bundle install --jobs 4 --retry 3
bin/rails db:create db:schema:load
- name: Build and test with rspec
env:
PGHOST: localhost
PGUSER: postgres
RAILS_ENV: test
run: |
gem install bundler -v 1.17.3
bundle install --jobs 4 --retry 3
bundle exec rspec spec
Some Observations
The editor is... wonky and annoying but until I have a good grasp of what I want to do, I'll stick with it. It kept getting in my way as I typed and copy/pasted steps. Also, all the documentation is right there in the sidebar along with the full docs here.
I like that with GitHub Actions I don't have to jump to another tool or service to run tests and view results. I like that the workflows are right there alongside and versioned with my code. It feels much less clunky for my brain and for the actual setup without that extra jump to another tool like Circle CI.
There is a marketplace for actions others have already written. But as you can see by searching for slack
, there's a boatload of actions to choose from, so who knows about that quality! There are some requirements to getting into the Marketplace and getting verified, but the first couple I tried out were hard to flaky.
Whether or not you choose to use GitHub Actions in your project probably also depends on what other tools you have in your toolbox. If you're already using Heroku Pipelines with CI, then this approach might not make any more sense.
What's next?
If you're confident enough in how your codebase is tested, the next step might be to do automatic deploys to your app when a pull request is merged to master. Or maybe you'll send a Slack notification when a build starts, succeeds, or fails!
Top comments (3)
What's the difference between this and Travis ci ?
Great question! I'm not familiar with all the ins and outs of Travis CI, but you can accomplish much of the same thing with both -- automating your software development lifecycle from build, test, package, release, publish, to deployment. One of the arguments for GitHub Actions vs something like a Travis CI or Circle CI is having the automated process defined and versioned right alongside your code.
It was the very first question in my head during reading about Actions.
Even more, I'm pretty sure that under the hood Github Actions uses at least some of Travi's infrastructure/components.