We jumped on the GitHub Action train early. It’s a really exciting step forward for GitHub, and we anxiously await their release. As soon as I was granted beta access I began experimenting and saw they would be able to ease the onboarding process for packtracker users. It specifically prevents our users from having to modify their own project configuration, and be a turn key service to track webpack bundle analysis.

This is a huge win for onboarding.

While GitHub Actions are great, they are not generally available yet, and GitHub hasn’t been forthcoming when to expect them to be.

In my search for a more generally applicable solution, I also found that CircleCI is starting to introduce a similar concept, Orbs.

CircleCI orbs are shareable packages of configuration elements, including jobs, commands, and executors.

The phrase “sharable packages of configuration elements” seemed at first like it would fall short of helping our users in the same way. CircleCI configuration isn’t really the problem. The useful bit of GitHub Actions is that they provide a full Docker execution environment. The key understanding that I failed to see initially is that CircleCI’s executors can be exactly that.

Executors define the environment in which the steps of a job will be run.

If you are not familiar with CircleCI executors, they can be declared as docker containers… Any docker container, even those you create and publish. While CircleCI isn’t nearly as ubiquitous as GitHub, it still covers a lot of our users and potential users.

Leveraging our GitHub Action

GitHub Action before adding CircleCI Orb

Since we had already built a Dockerfile for use with our GitHub Action, I set out to re-use that work to create a common core that could be used for both our GitHub Action and our CircleCI Orb.

The first step in the process was to create a base image that both services would use. In this image we installed all the software we needed, and copied our scripts into the image root directory. From here, we would build and publish it.

FROM node:11-slim

RUN apt-get update && apt-get install jq git yarn -y && rm -rf /var/lib/apt/lists/*

COPY ./entrypoint.sh /entrypoint.sh
COPY ./report.js /report.js

Notice we specifically removed the LABEL instruction, as well as the ENTRYPOINT instruction required by our GitHub Action. We put this file in the repository as Dockerfile.base.

With the base image published, we then created our GitHub Action Dockerfile, using the FROM instruction using the base image above, reintroducing the LABEL instruction, and ENTRYPOINT we removed above.

FROM packtracker/report:x.y.z

LABEL "com.github.actions.name"="Report to packtracker.io"
LABEL "com.github.actions.description"="Report your webpack build stats to the packtracker.io service."
LABEL "com.github.actions.icon"="upload-cloud"
LABEL "com.github.actions.color"="#363636"

ENTRYPOINT ["/entrypoint.sh"]

So now, we’ve not modified the behavior of our GitHub Action at all, but now we have a base image that can also be used as a CircleCI executor.

With the base image in place, containing all software and scripts we need, creating our Orb definition is a breeze. Creating a job to checkout the code, copy the script in place, and execute it.

This all goes in the orb.yml file that is used to build and publish the Orb.

version: 2.1

executors:
  reporter:
    docker:
      - image: packtracker/report:x.y.z

jobs:
  report:
    description: ...
    parameters:
      project_root:
        description: The path to the directory containing your package.json
        type: string
        default: ""
      webpack_config:
        description: The path to your webpack configuration file (if present)
        type: string
        default: "webpack.config.js"
    environment:
      PT_PROJECT_ROOT: << parameters.project_root >>
      WEBPACK_CONFIG_PATH: << parameters.webpack_config >>
    executor: reporter
    steps:
      - checkout
      - run:
          name: "Reporting to packtracker.io"
          command: /entrypoint.sh

As you can see above, we also map the Orb’s parameters directly to the environment variables that our script expects.

And without much code, we have been able to leverage our existing scripts and Docker usage to quickly package the behavior of our GitHub Action as a CircleCI Orb!

GitHub Action after adding CircleCI Orb