Migrating from Travis CI to GitHub Actions
Tags: wordpress, github
Published: 2020-12-10 00:47:53

I maintain an open source WordPress theme called [Garrick](https://boldoak.design/work/garrick/) which I also use to power my family blog. (This is known as "dogfooding," in case you're wondering.) It's my third WordPress theme which I've developed from scratch, more or less, not counting the starter theme used as the base. (The first two used Underscores, while Garrick is built on [Justin Tadlock's Mythic](https://github.com/justintadlock/mythic).) Since the very start of my WordPress theme development journey, however, the one thing that hasn't changed is my use of Travis CI to validate file changes. In that regard, to my mind, this is the end of an era.

Travis CI recently announced a [change in their pricing plans](https://blog.travis-ci.com/2020-11-02-travis-ci-new-billing) which make things a little more difficult for open source maintainers. Garrick is a small enough project where it isn't really affected, but I've [seen this happen](https://eichefam.net/2016/10/14/all-that-you-love-will-be-refactored-away/) enough times to know that it's better, wherever possible, to not depend on third parties for functionality that may suddenly be removed or crippled in some way.

Since Garrick is actively maintained and hosted on GitHub, it makes sense to migrate the CI functionality to [GitHub Actions](https://github.com/features/actions), GitHub's relatively new workflow automation system. It can do more than just CI/CD; in fact, I built an action to [automate bundling a release](https://boldoak.design/blog/automatically-creating-the-release-for-a-wordpress-theme/) zip file whenever a new release is created.

The Travis config I use is relatively simple. Since the WordPress theme uses Composer and npm to manage dependencies, the config must install them first. The theme already has scripts set up to validate the PHP files using phpcs, Sass using Stylelint, and JavaScript using ESLint. I simply reuse those within the Travis config. Here is an example (edited for brevity):

```yml
language:
  - php
jobs:
  fast_finish: true
  include:
    - php: 7.4
      env: SNIFF=1
before_install:
  - if [[ "$SNIFF" == 1 ]]; then nvm install --lts; fi
  - composer install
  - if [[ "$SNIFF" == 1 ]]; then npm install; fi
script:
  - composer validate --no-check-all --strict
  - if [[ "$SNIFF" == 1 ]]; then npm run lint:php; fi
  - if [[ "$SNIFF" == 1 ]]; then npm run lint:scripts; fi
  - if [[ "$SNIFF" == 1 ]]; then npm run lint:styles; fi
```

Setting up an equivalent GitHub Action was pretty simple. I clicked on the Actions tab, then clicked on "New Workflow." Choosing "set up a workflow yourself" allows you to start with a sample `.yml` file, which is what I did. It took a little bit of trial and error to get it right, but the resulting config runs validation on every update, including on all branches, not just on the master.

While Travis makes things a little easier to use PHP and Composer, doing the same on GitHub Actions requires manual setup. There exists an action for running `npm install`; there is also one for composer, but I found that installing the composer dependencies can be done just by calling the command directly. So in the interest of limiting my action dependencies, I opted for that.

```yml
on:
  push:
  pull_request:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: bahmutov/npm-install@v1
    - run: |
        composer install --optimize-autoloader
    - run: |
        composer validate --no-check-all --strict
    - run: |
        npm run lint:php
    - run: |
        npm run lint:scripts
    - run: |
        npm run lint:styles
```

I do want to talk for a moment about when the action runs. GitHub's sample action has this:

```yml
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
```

I didn't want the action to run _only_ on the main branch, since I do want validation on all branches. So I tried this:

```yml
on: [push, pull_request]
```

That resulted in the action actually being run _twice_. After rereading the documentation, I ended up with this:

```yml
on:
  push:
  pull_request:
```

That results in only running the action once, for any branch. It's not exactly intuitive, since it looks (to me, at least) like some configuration is missing. But it works, so I'm not going to argue with that.

So all that was left to be done at this point was to delete the old Travis config. Good bye Travis CI, hello GitHub Action.