what is it?

a continuous integration and continuous delivery platform that can be used to implement devops practices

getting started

  • follow the steps here to get a circleci project set up
  • add a .circleci/config.yml file to the bitbucket/github/etc repository

config.yml recipes

not an exhaustive list

test a python project

.circleci/config.yml
version: 2.1
 
jobs:
  run-tests:
    executor: python/default
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: |
            cd app
            python3 -m venv venv
            . venv/bin/activate
            pip install -r requirements_dev.txt
      - run:
          name: Test with pytest
          command: |
            cd app
            cp .env.dev.template .env
            . venv/bin/activate
            pytest
 
workflows:
  build-and-release-application:
    jobs:
      - run-tests
  • version: intended to be used in order to issue warnings for deprecation/breaking changes
  • jobs: a workflow is comprised of one or more uniquely named jobs, that are specified in the jobs map.
  • workflows: used for orchestrating all jobs

it might not be necessary to cd into the python project directory to install dependencies and runs tests.. it all depends on the project structure, if the docker config is present in the root dir, etc

build image and push to GCP

.circleci/config.yml
version: 2.1
 
orbs:
  gcp-gcr: circleci/[email protected]
 
executors:
  default-docker:
    docker:
      - image: google/cloud-sdk:latest
 
jobs:
  build-and-push-image:
    executor: default-docker
    steps:
      - checkout
      - setup_remote_docker:
          version: default
          docker_layer_caching: true
      - gcp-gcr/gcr-auth
      - gcp-gcr/build-image:
          registry-url: eu.gcr.io
          image: ${CIRCLE_PROJECT_REPONAME}
          tag: ${CIRCLE_SHA1}
          dockerfile: Dockerfile
      - gcp-gcr/push-image:
          registry-url: eu.gcr.io
          image: ${CIRCLE_PROJECT_REPONAME}
          tag: ${CIRCLE_SHA1}
      - gcp-gcr/tag-image:
          registry-url: eu.gcr.io
          image: ${CIRCLE_PROJECT_REPONAME}
          source-tag: ${CIRCLE_SHA1}
          target-tag: latest
 
workflows:
  build-and-release-application:
    jobs:
      - build-and-push-image:
          context:
            - Google - Develop
          filters:
            branches:
              only:
                - develop
                - staging
                - production
  • orbs: shareable packages of circleci configuration you can use to simplify your builds. example above uses the google container registry orb
  • executors: define the execution environment in which the steps of a job will be run, allowing you to reuse a single executor definition across multiple jobs
  • context: a mechanism for securing and sharing environment variables across projects. this means the build-and-push-image job has access to the envvars defined by the Google - Develop context
  • filters: run this job only if these conditions are true. can filter on branches or tags
  • CIRCLE_PROJECT_REPONAME: built-in env var, the name of the repository of the current project
  • CIRCLE_SHA1: built-in env var, the SHA1 hash of the last commit of the current build

jobs can interact with each other

.circleci/config.yml
workflows:
  build-and-release-application:
    jobs:
      - run-tests
      - build-and-push-image:
          context:
            - Google - Develop
          filters:
            branches:
              only:
                - develop
                - staging
                - production
          requires:
            - run-tests

execution environments

docker

limits your runs to what is possible from within a Docker container, which is usually sufficient.

circleci has a exhaustive collection of convenience images that can be used directly or via orb abstraction

machine

run your jobs in the linux virtual machine execution environment by using the machine executor and specifying a linux image

.circleci/config.yml
jobs:
  build:
	machine:
      image: ubuntu-2204:2024.05.1

a situation where a machine executor would work better than docker is integration testing using a testcontainers instance of postgresql; a container is being spun up just to have a throwaway database for testing, that can be discarded afterwards, without polluting dev or staging dbs

resource_class

for both docker and machine executors, the resource class can be changed, if so required