Migrating from Github Actions

This document provides an overview of how to migrate from Github Actions to CircleCI.

Why Migrate to CircleCI?

CircleCI is a first-class CI tool. CI/CD has been our specialization since the company’s founding 8 years ago. On top of the features you would expect from any CI/CD tool, what sets us apart are the following productivity-boosting features:

  1. Advanced Caching - On top of normal dependency caching, CircleCI offers caching specific to Docker image layers. This means subsequent builds of your Docker images will run faster, cutting even more time off your commit-to-deploy workflows.

  2. SSH Into Builds - CircleCI offers the ability to securely SSH into a build environment to tail logs, work with files, and directly interact with an environment. This is highly useful for debugging failing builds.

  3. Resource Classes - you can use various different sizes of executor on our platform, great for adjusting according to lighter or heavier workloads on a node.

  4. Test Parallelism - our platform provides not only concurrent job execution but also the ability to split tests between parallel environments. You can dramatically cut build times by splitting workloads between different containers.

We have various other features that set our solution apart. Sign up for a free account today and try us out, or if you are interested in CircleCI for your team, contact our sales team to set up a trial.

Concepts

Jobs and Workflows

Both Github Actions and CircleCI share similar concepts around "jobs" and "workflows". A workflow is an end-to-end flow of connected jobs, which in turn consist of commands to achieve an atomic task (e.g. "run unit tests" or "build a Docker image").

CircleCI differs primarily in configuration syntax, setting up workflow and job dependencies in a separate section as opposed to inline in the job.

Github CircleCI
name: My GitHub Actions Workflow

on: [push]

jobs:
  job_1:
    runs-on: ubuntu-latest
    steps:
      # job steps
  job_2:
    needs: job_1
    runs-on: ubuntu-latest
    steps:
      # job steps
jobs:
  job_1:
    executor: my-ubuntu-exec
    steps:
      # job steps
  job_2:
    executor: my-ubuntu-exec
    steps:
      # job steps

workflows:
  my_workflow:
    jobs:
      - job_1
      - job_2:
          requires:
            - job_1

Actions vs. Orbs

"Actions" in Github are reusable commands or tasks to run inside a job. However, they are written for execution inside a Docker container or coded as individual steps using JavaScript. This adds additional work and limits the scope in which they can be applied.

CircleCI offers similar functionality in our orbs. The primary difference is that CircleCI orbs are just packaged, reusable YAML, so you can orbify reusable jobs, executors, or commands, and use them however you see fit in any of your jobs or workflows.

Github offers browsing of Actions in their Marketplace; CircleCI has an Orb Registry as well as an Integrations Page containing numerous Certified, Partner, and community orbs / integrations.

Runners vs. Executors

In GitHub, you can specify your builds to run in Linux, macOS, and Windows environments via a runs-on key in the YAML, and if you want to run anything in a container, you specify an additional container key.

In CircleCI, you have the same choice of environments (called Executors), with additional options and features for Docker.

For each of the executor types, you have a choice of different versions which will subsequently have various versions of base software installed.

See the table in the next section to compare configuration.

Configuration Comparison

Github Config CircleCI Config

Specifying execution environment. While container execution is specified separately in Github,
docker is its own class of executor in CircleCI.

# Choosing an Operating System
runs-on: ubuntu-latest # or windows, etc.

# If running steps on a container
container:
  image: openjdk:11.0-jdk
# Docker (container) Executor
docker:
  - image: circleci/openjdk:11.0-jdk
    auth:
      username: mydockerhub-user
      password: $DOCKERHUB_PASSWORD  # context / project UI env-var reference

# Linux Ubuntu Executor
machine: true

# macOS Executor
macos:
  xcode: 11.3.0

# Windows Executor
# NOTE: Orb declaration needed. See docs
executor: win/vs2019

Specifying dependencies/services. All images specified after the first in CircleCI are treated as dependencies.

jobs:
  build:
    runs-on: ubuntu-latest

    # Main container
    container:
      image: openjdk:11.0-jdk

    # Dependency Service(s)
    services:
      postgres:
        image: postgres:10.8
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: postgres
jobs:
  build:
    docker:
      # Primary Executor
      - image: circleci/openjdk:11.0-jdk
        auth:
          username: mydockerhub-user
          password: $DOCKERHUB_PASSWORD  # context / project UI env-var reference

      # Dependency Service(s)
      - image: postgres:10.8
        auth:
          username: mydockerhub-user
          password: $DOCKERHUB_PASSWORD  # context / project UI env-var reference
        environment:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: postgres

Specifying steps to run in a job. Similar functionality, different syntax.

jobs:
  build:
    # runner config here

    steps:
      - name: Build with Gradle
        run: ./gradlew build
jobs:
  build:
    # executor config here

    steps:
      - run:
          name: Build with Gradle
          command: ./gradlew build

Using shared tasks (Actions for Github, orbs for CircleCI). In CircleCI, you declare orbs at the top level
and then refer to them by name in config, similar in concept to Python or JavaScript imports.

jobs:
  build:
    # runner config here

    steps:
      - name: Slack Notify
        uses: rtCamp/action-slack-notify@v1.0.0
        env:
          SLACK_COLOR: '#32788D'
          SLACK_MESSAGE: 'Tests passed'
          SLACK_TITLE: Slack Notify GA
          SLACK_USERNAME: Bobby
          SLACK_WEBHOOK: # WEBHOOK
orbs:
  slack-orb: circleci/slack@3.4.0

jobs:
  build:
    # executor config here

    steps:
      - slack-orb/notify:
          color: '#32788D'
          message: Tests passed
          title: Testing Slack Orb
          author_name: Bobby
          webhook: # WEBHOOK

Using conditional steps in the workflow. CircleCI offers basic conditions on steps (e.g., on_success [default],
on_success, on_failure) as well as conditional steps based on parameters. We also have conditional jobs, and
currently conditional, parameterized workflows and pipelines are in preview.

jobs:
  build:
    # environment config here

    steps:
      - name: My Failure Step
        run: echo "Failed step"
        if: failure()
      - name: My Always Step
        run: echo "Always step"
        if: always()
jobs:
  build:
    # executor config here

    steps:
      - run:
          name: My Failure Step
          command: echo "Failed step"
          when: on_fail
      - run:
          name: My Always Step
          command: echo "Always step"
          when: always

For more configuration examples on CircleCI, visit our Tutorials and Example Projects pages.

Since the configuration between Github Actions and CircleCI is similar, it should be fairly trivial to migrate your jobs and workflows. However, for best chances of success, we recommend migrating over items in the following order: