Migrate From Travis CI
This document provides an overview of how to migrate from Travis CI to CircleCI.
The example build configurations referenced throughout this article are based on this example JavaScript repository.
Prerequisites
This document assumes that:
- You have an account with CircleCI that is linked to a repository. If you do not have an account, consider reading our Getting Started Guide.
- You understand the Basic Concepts in CircleCI.
Why migrate to CircleCI?
- Scaling Concurrency: You can run up to 80 concurrent jobs on our monthly Performance Plan or even more on a Custom Plan. Travis CI has capped concurrencies of 1, 2, 5, and 10 on each of their plans.
- Resource Classes: vCPU & RAM are configurable within CircleCI jobs to strategically speed up builds and spend credits, whereas these values are fixed on Travis CI.
- Parallelization by Timing: On top of running many jobs concurrently, CircleCI offers built-in test splitting across multiple environments by timing. This dramatically reduces wall clock time for large test suites to finish. You must implement this manually in Travis CI.
- Orbs: Rather than proprietary integrations, CircleCI offers orbs, which are reusable, templated configuration. On top of connecting to services and tools, orbs can be used to standardize and templatize configuration for your team and organization as well. Visit the registry.
Configuration files
Both Travis CI and CircleCI make use of a configuration file to define your workflows and jobs. The only difference is that your CircleCI configuration will live in .circleci/config.yml
at the root of your repository.
Below, you’ll find a side-by-side comparison of different configuration declarations.
Travis CI | Circle CI | Description |
---|---|---|
language:, os: | docker, machine, macos, windows | CircleCI doesn’t assume dependencies or commands based on a language; instead, choose an executor and use run: steps as shown below to execute commands you require (e.g., install, build, test). |
dist: | machine | Our Linux VM executor is a Ubuntu VM. You can specify versions in the config |
cache: | restore_cache:, save_cache: | Use the restore and save cache features to control caching in the builds |
before_cache | run: | If you want to run any commands before you cache, simply place a run: step before your cache step(s) in CircleCI |
before_install: | run: | CircleCI doesn’t separate commands into stages or types. Use run: steps to specify any commands and order them per your needs. See documentation for usage of conditional steps |
install: | run: | ” (see above) |
before_script | run: | ” (see above) |
script: | run: | ” (see above) |
after_script: | run: | ” (see above) |
deploy: | run: | Use a run: step to run needed commands for deployment. See our Deployment overview page for links to examples. |
env: | environment: | Use the environment: element to specify environment variables |
matrix: | matrix: | CircleCI also offers matrix syntax under our workflows configuration. |
stage: | requires: | Use the requires: element to define job dependencies and control concurrent jobs in workflows |
Building on pushing code
The example repository linked above is a basic application for creating, reading, updating, and deleting articles. The app is built with the MERN
stack and there are tests present on the client as well as the REST API that should run whenever code is pushed.
To get tests running for this example repository, the beginnings of a simple Travis Configuration might look like the following example:
language: node_js
services: mongodb
before_install:
- npm i -g npm@5
node_js:
- "5"
cache: npm
For basic builds, a Travis CI configuration will leverage a language’s best known dependency and build tools and will abstract them away as default commands (which can be overridden) in a job lifecycle. In this case, when the build runs, Travis CI will automatically run npm install
for the install
step, and run npm start
for the script
step.
If a user needs more control with their CI environment, Travis CI uses hooks to run commands before/after the install
and script
steps. In the example above, a “before hook” is used to specify that the npm version be pinned to 5
. Hooks can execute shell scripts as well, which users will sometimes store in a .travis
folder at the root of their repository.
The following CircleCI configuration to achieve the same results is excerpted from the example repository:
version: 2.1
workflows:
build:
jobs:
- build
jobs:
build:
working_directory: ~/mern-starter
docker:
- image: cimg/node:17.2.0 # Primary execution image
- image: mongo:3.4.4 # Service/dependency image
steps:
- checkout
- run:
name: update-npm
command: 'sudo npm install -g npm@5'
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
name: install-npm-wee
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
paths:
- ./node_modules
- run:
name: test
command: npm test
In the config above, no language is specifically required, and the user is able to specify any number of steps
that can be run, with no restrictions on step order. By leveraging Docker, specific Node.js and MongoDB versions are made available in each command
that gets run.
Caching dependencies
With CircleCI you have control over when and how your config caches and restore dependencies. In the above example, the CircleCI .circleci/config.yml
checks for a dependency cache based specifically on a checksum of the package-lock.json
file. You can set your cache based on any key (not just package-lock.json
) as well as set a group of cache paths to defer to in the declared order. Refer to the caching dependencies document to learn about customizing how your build creates and restores caches.
In a Travis Configuration, dependency caching occurs in your build after the script
phase and is tied to the language you are using. In our case, by using the cache: npm
key in .travis.yml
, dependencies will default to caching node_modules
.
Environment variables
Both Travis and CircleCI enable the use of environment variables in your builds.
In your CircleCI .circleci/config.yml
you can put environment variables directly in your build config in a step, a job, or a container. These variables are public and unencrypted. With Travis CI, it is possible to include encrypted environment variables directly in your config (if you install the travis
gem).
Setting environment variables in the web application
If you’ve used Travis CI’s repository settings, you’ll be comfortable setting your environment variables in CircleCI’s project settings page. Read the docs for setting environment variable in a single project.
With CircleCI, it is also possible to securely set environment variables across all projects using contexts.
In addition, CircleCI has several built-in environment variables.
Artifacts uploading
With Travis CI you can upload build artifacts either manually using AWS S3 or as an attachment to a GitHub Release.
On CircleCI, artifact uploading occurs in a step in your config:
- run:
name: test
command: npm test
- run:
name: code-coverage
command: './node_modules/.bin/nyc report --reporter=text-lcov'
- store_artifacts: # < stores test-results.xml, available in the web app or through the api.
path: test-results.xml
prefix: tests
- store_artifacts:
path: coverage
prefix: coverage
- store_test_results:
path: test-results.xml
After an artifact is successfully uploaded, you can view it in the Artifacts tab of the Job page in your browser, or access them through the CircleCI API. Read the documentation on artifact uploading to learn more.
Advanced tooling
More advanced configuration on Travis might make use of a Build Matrix (a configuration that specifies running multiple concurrent jobs) or Build Stages (grouping jobs into stages that can run concurrently as well as having sequential jobs rely on the success of previous jobs.)
With CircleCI you can use workflows in your .circleci/config.yml
to define a collection of jobs and their run order, whether leveraging concurrency, fan-in or fan-out builds, or sequentially-dependant builds. Workflows allow complex and fine-grained control over your build configuration.