# Migrating our CI to Github Actions

And how we did that in Tourlane

Now in Tourlane we are switching our deployment system to use GitHub Actions. So, in this post, we are sharing our experience with the tool so far, and how we are migrating our projects, little by little to the tool.

## What is CI/CD?

Martin Fowler, one of the original authors of the Agile Manifesto, describes them like this in this book:

Continuous Integration (CI) is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early.

Continuous Delivery (CD) is the natural extension of Continuous Integration: an approach in which teams ensure that every change to the system is releasable, and that we can release any version at the push of a button. Continuous Delivery aims to make releases boring, so we can deliver frequently and get fast feedback on what users care about.

##What are Github Actions

GitHub has just released a version of its own CI/CD tool, which is called GitHub Actions. More information can be found in this blog post. It helps you to:

orchestrate any workflow, based on any event, while GitHub manages the execution, provides rich feedback, and secures every step along the way.

For Tourlane, it looked a quite convenient tool to use — We already use GitHub for repository storage and collaboration, thus Actions facilitates the efforts of integrating the tools.

## How we used to do it before

At the beginning of the company, we used to use Jenkins as a CI tool to deploy our applications. But then we switched to CircleCI because at that point it looked simple, faster and cheaper.

So after that, even though each repository has its own specific rules, we basically used to use CircleCI to handle our continuous integrations. We had a file under the .circleci folder, called config.yml. Also, we had some environment keys configured for each project.

On top of that, we have organized Makefiles that made the task of migrating even easier, so in the end, just had to migrate the commands to GitHub Actions’ own config file.

The structure of the configuration didn’t have to change much, where we also have a file to coordinate how the build process should be and manage the deploy when in a staging/master branch.

## Why we decided to switch

CircleCI served us well (and still is) but we decided to experiment with Github Actions in order to have a single platform where our codebase and CI/CD setup live as it makes onboarding easier as its one less tool to onboard new developers. While Github Actions is still new it comes with a lot of integrations that made our workflows faster and simpler.

## How are doing it now

We started the migration slowly, first migrating some projects with fewer dependencies until we move to a project with more needs, this was the result:

name: CI

on: [push]

jobs:
test:
runs-on: ubuntu-latest
container:
image: ruby:2.6.5

services:
<db_service_name>:
image: postgres:10.6
ports: ['5432:5432']
options: >-
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@master

- uses: actions/cache@v1
with:
path: /usr/local/bundle
key: v1-gem-cache-${{ hashFiles('**/Gemfile.lock') }} restore-keys: v1-gem-cache - name: Install dependencies env: BUNDLE_GITHUB__COM:${{ secrets.BUNDLE_GITHUB__COM }}:x-oauth-basic
run: "make deps"

- name: Lint
run: "make lint"

- name: Test
env:
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }} RAILS_ENV: "test" DATABASE_URL: "postgres://postgres@<db_service_name>:5432/<db_name>" run: "make test" deploy: if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/staging' runs-on: ubuntu-latest needs: test env: AWS_ACCESS_KEY_ID:${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION:${{ secrets.AWS_DEFAULT_REGION }}

steps:
- uses: actions/checkout@master

- name: Build Docker image
env:
BUNDLE_GITHUB__COM: ${{ secrets.BUNDLE_GITHUB__COM }}:x-oauth-basic run: "make build" - name: Deploy to staging if: github.ref == 'refs/heads/staging' run: DEPLOYER=${GITHUB_ACTOR} make deploy_to_staging

- name: Deploy to production

### Using the cache action

When we were sure that the CI we setup is running as we want, we set up the caching action in order to make it run faster in the next time we trigger it again. The cache action will attempt to restore a cache based on a key we provide.

### Database service name

When configuring the service for the database, you need to make sure that the name of the service matches the name you set up when configuring the database URL.

### No support for private Docker Images

We used to use private docker images, and GitHub Actions doesn’t allow private images to run in its CI, yet. Also, that made us rethink why we don’t push our image to Docker Hub.

### Private gems

In our projects, we use some private gems to handle some authentication, and those led us to configure BUNDLE_GITHUB__COM in order to use those, and this needs to be set up in the setting/secrets on your repository.

## Resources

1. Workflow syntax for GitHub Actions: https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions

And that’s all folks! This is a summary of how we migrate our CI service to Github Actions!