Circle-CI 2.0 for Open Source Projects

Published Mar 20, 2018Last updated Apr 24, 2018
Circle-CI 2.0 for Open Source Projects

Travis-CI is still the most popular CI system used by the free and open source projects, especially due to its open cutler and the fact that in theory Travis-CI is itself open source.

The popularity of Travis-CI has its price.
As more and more open source projects are using the free Travis-CI service and more projects are running more tests, it takes longer to have all the tests executed.

I still think that Travis-CI is a great service, especially now that it supports build stages.

Here I am presenting Circle-CI as a way to leverage the offers provided by the Circle-CI to the open source community.

I suggest running half your builds on Travic-CI and the other half on Circle-CI.. and if you need Windows, run the Windows tests on Appevyor as Appveyor is also free for open source projects.

Circle-CI resources for Open Source

For open source projects, Circle-CI team is generous enough and provide the following resources for free:

  • 4 parallel Linux docker builds (after you enable the Open Source features)
  • Seed plan for macOS builds (after to send an email to Circle-CI billing)

Travis-CI also has macOS builds for open source projects, but the queues were always long on Travis-CI.

So far, on Circle-CI the builds spent no more than 5 seconds in the queue, whole on Travis-CI it was hours. Maybe Travis-CI is better now.

Activating the Open Source features

Assuming that you have enabled Circle-CI for your project (repository), by default you will not get all the resources available for open source projects.

They need to be enabled from the Advances Settings page of your repo.
The URL looks like https://circleci.com/gh/ORG-NAME/REPO-NAME/edit#advanced-settings

You might want to enable the followings:

  • Free and Open Source - to get 4 Linux dockers instead of 1.
  • Build forked pull requests - to allow external contributors to run the tests as part of a PR
  • Only build pull requests (optional)- to not waste resource with commits pushed outside of a PR.

When you enable builds for PR, make sure to disable Pass secrets to builds from forked pull requests so that you will not leak the secrets.

Don't forget to include the Circle-CI badge in the README file of your repo.
The URL for getting the code for the bake looks like https://circleci.com/gh/ORG-NAME/REPO-NAME/edit#badges

Once you are set, don't forget to add access to Circle-CI administration to the other developers from your community.
In this way the can tweak Circle-CI even when you are not around.
The URL looks like https://circleci.com/team/gh/ORG-NAME.

Notifications in Circle-Ci

If you are familiar with Travis-CI you might want to tweak the notifications.

Circle-Ci provides all the usual notifications features (email, Slack, IRC).
For now, these configurations are not available from the YAML config file and you will need to configure them from the Circle-CI UI.

The configuration for the email notifications are found in your personal account (even for the project notifications), so check them out at https://circleci.com/account/notifications

Example of a Python project on Linux and macOS

I will not go too much into details here as the Circle-CI version 2.0 documentation is pretty good.

For Linux, Circle-CI is all about Docker.
Instead of having a fixed OS (like old Ubuntu 12.04 or 14.04), you can run it in any docker container.
As I start, I suggest using one of the prebuild images and start with a simple example.

One thing that I want to show you here, is that you can use the macOS builds, for anything, not only for XCode projects.
For this example, I am keeping it simple and use the Python version provided by macOS.
You have full control of the macOS system so you can install Homebrew and roll your own environment.

Another great feature is the workflow functionality is great.
You can use it to do a lot of nice things, especially for deployment.
In this example, I am going with a simple example, in which the tests are executed only after the static checkers are green.

Most of the time, if you forget to define a variable, or your code violates a coding standard, you end up with a stupid build and the final build will fail anyway.
You will need to re-run the tests anyway, so why waste testing time?

Here is how the workflow looks for this example:

circle-ci.png

Here is the full working example. That is all. Happy testing!

version: 2

jobs:
  static_checkers:
    working_directory: ~/static-checkers
    docker:
      - image: circleci/python:2.7
    steps:
      # Get the source.
      - checkout

      - run:
          name: Prepare the environment.
          command: |
            python --version
            pip install -q --user --ignore-installed --upgrade virtualenv
            pip install -q tox --user
            echo 'export PATH=~/.local/bin:$PATH' >> $BASH_ENV

      # Run each checker in a separate step.
      - run:
          name: Check the release notes.
          command: |
            tox -r -e newsfragment
      - run:
          name: Check manifest-checker.
          command: |
            tox -r -e manifest-checker
      - run:
          name: Check pyflakes.
          command: |
            tox -r -e pyflakes


  #
  # Documentation tests are slow so we execute them in a separate job.
  #
  documentation:
    working_directory: ~/documentation
    docker:
      - image: circleci/python:2.7
    steps:
      # Get the source.
      - checkout

      - run:
          name: Prepare the environment.
          command: |
            python --version
            pip install -q --user --ignore-installed --upgrade virtualenv
            pip install -q tox --user
            echo 'export PATH=~/.local/bin:$PATH' >> $BASH_ENV

      - run:
          name: Check the narrative documentation.
          command: |
            tox -r -e narrativedocs

      - run:
          name: Check the API documentation.
          command: |
            tox -r -e apidocs


  #
  # We run pyflakes with Python 3 .
  #
  pyflakes3:
    working_directory: ~/pyflakes3
    docker:
      - image: circleci/python:3.6
    steps:
      # Get the source.
      - checkout

      - run:
          name: Prepare the environment.
          command: |
            python --version
            pip install -q --user --ignore-installed --upgrade virtualenv
            pip install -q tox --user
            echo 'export PATH=~/.local/bin:$PATH' >> $BASH_ENV

      - run:
          name: Check the API documentation.
          command: |
            tox -r -e pyflakes3

  #
  # MacOS with Python2.7 and default reactor.
  #
  macos_py27_default_reactor:
    macos:
      # We don't use the xcode, but we need to put something here.
      xcode: "9.0"

    working_directory: ~/repo

    steps:
      # Get the source.
      - checkout

      - run:
          name: Prepare the macOS environment.
          command: |
            python --version
            pip install -q --user --ignore-installed --upgrade virtualenv
            pip install -q tox --user
            echo 'export PATH=/usr/local/bin:$PATH:/Users/distiller/Library/Python/2.7/bin' >> $BASH_ENV

      # Run tests with tox without any cached dependencies.
      - run:
          name: Test with the default reactor.
          command: |
            tox -r -e py27-alldeps-withcov-posix twisted


# First we run the static checkers, and only if they pass we spin the macOS.
# in this way we should save some macOS minutes.
workflows:
  version: 2
  all-tests:
    jobs:
      - static_checkers
      - macos_py27_default_reactor:
          requires:
            - static_checkers
      - documentation:
          requires:
            - static_checkers
      - pyflakes3:
          requires:
            - static_checkers

Discover and read more posts from Adi Roiban
get started