CircleCI

(config.yml 작성방법)

 

 

 

CircleCI는 개발자가 코드를 개발할 때 생산성을 높여주는 CI 도구 중 하나이다. CI는 Continuous Integration의 약자로 지속적인 통합이라는 의미를 가진다. CI 툴을 사용하는 목적은 개발자의 코드의 품질을 좋게 만드는 것으로, CI 툴은 개발자의 코드가 미리 정의해둔 조건들에 만족하는지를 판단하고 이에 따라 코드를 통합시킴으로써 코드의 품질을 유지할 수 있는 기능들을 제공하고 있다.

 

Github 저장소를 만들고 올려둔, 개발 중인 프로젝트에 CI 툴인 CircleCI를 적용하면 달라지는 것들?

 

예)

  • Lint 실행과 Test 코드 실행에 대한 성공여부를 Slack 메시지로 전달받을 수 있다.

  • Circle Ci는 사용자가 Push를 할 때마다, 적용되는 코드에 Lint 적용이 되었는지 판단한다.

  • Circle Ci는 테스트가 모두 통과한 코드에 대해 자동으로 Tag를 만든다.

 

개발자가 실무에서 많이 사용하는 대표적인 CI 툴로는 CircleCI, Jenkins, TravisCI가 있다. 이 중에서 무료로 사용할 수 있는 CI인 CircleCI에 대해 포스팅해보려 한다. 이 글의 목적은 CircleCI에 대해 전부를 설명하는 것이 아닌, CircleCI를 처음 사용하면서 원하는 기능에 대한 자세한 설정이나 설명들을 찾아보기 전에 기본적인 구성을 알기 위함이기 때문에, 설명이 부족할 수 있다. 자세한 내용을 원한다면 CircleCI 공식 사이트 혹은 아래 참조로 추가해둔 사이트를 살펴보기 바란다.

 

CircleCI를 사용하면, 프로젝트 내에 .circleci 라는 디렉토리가 만들어지고, 그 안에 config.yml 이라는 파일이 있는데, 이 파일에 개발자는 자동화하기를 원하는 CI 기능들을 작성하게 된다. 따라서 CircleCI를 사용할 때는 config.yml이라는 파일을 어떻게 작성하는지를 알면 사용법의 반 이상은 이해하고 있는 것이라고 생각한다. CircleCI의 어떤 버전 사용하냐에 따라 config.yml에서 내에서 사용할 수 있는 내용이 약간 차이가 있는데. 현재  글에서는 CircleCI의 버전은 2.1을 바탕으로 설명하고 있으니 참고바란다. 또한 이 글은 Github와 CircleCI를 연동해서 사용하는 것을 전제로 가정하고 설명하는 것도 참고바란다. 가장 먼저 아래 작성된 config.yml 파일의 샘플을 살펴보자.

 

config.yml

version: 2.1

excutors:
    node-executor: 
        docker: 
            - image: circleci/node:8
    ruby-executor: 
        docker: 
            - image: ruby

jobs:
    build:
        executor: node-executor
        steps:
            - checkout
            - restore_cache:
                keys:
                    - dep-bundle-{{ checksum "package.json" }}
            - run: npm install
            - save_cache:
                key: dep-bundle-{{ checksum "package.json" }}
                    - /repo/node_modules
            - run: npm run lint && npm run test && npm run downloadsolc && npm run make-mock-compiler && npm run setupremix && npm run build
            - run: ./ci/browser_tests.sh

    a_test:
        executor: ..
        steps:
            - checkout
            - ...

workflows:
    version: 2
    build_and_others:
        jobs:
            - build
            - a_test:
                requires:
                    - build
                filters:
                    branches:
                        only: master

 

version : CI 버전으로 2.1을 사용하였다.

 

executors : 개발자가 정의한 작업을 실행시킬 환경을 정의하고 그 안에서 함께 실행되어야 하는 프로그램에 대한 이미지를 정의한다. (ex, docker, macOS) 이 곳에 정의한 executor는 작업(job) 내용을 작성할 때 실행환경을 적는 executor라는 필드에서 사용된다.

 

jobs : 자동화 하고 싶은 작업(job)으로, 네이밍은 개발자가 직접 정의한다. 여기서 알아둘어야 할 점은 job을 정의한 것일뿐, 모든 job들을 어떤 방법으로 실행시킬지에 대해서는 workflow 항목에서 정의한다는 것이니 혼동하지 말자. (ex, build, a_test)

executor : executors에 정의해둔 개발 환경 중에 작업에 필요한 환경에 대해 직접 정의한 이름을 작성한다.

steps : 작업(job)에 대해 실행할 내용들을 차례로 작성한다.

restore_cache : 캐시(cache)를 복원한다. 작업이 실행되기 전에, 다른 작업(job)에서 save_cache 을 통해 캐시에 저장된 것이 있다면 이를 사용하기 위해 복원시킨다.

save_cache : 캐시(cache)를 저장한다. 이때 캐싱으로 사용하기 위해 저장시킨 내용은 다른 job들에서도 사용된다. 아래 예시로 작성한 config.yml에선, nodeJS 프로젝트에서 dependency 라이브러리들이 저장되는 디렉토리가 node_module인데, 이 디렉토리를 캐싱해두고 다른 작업(job)들에서도 사용할 수 있도록 하는 것이다. 참고로, nodeJS 프로젝트의 node_module디렉토리는 maven 프로젝트의 .m2 디렉토리와 동일한 역할이므로 maven 프로젝트라면 .m2가 될 것이다.

run  : 실행할 명령(command)이다. 예제에서는 npm 라이브러리들을 다운로드하는 npm install 이라는 명령을 실행시키거나 lint 라이브러리를 실행시키는 npm run lint 라는 명령을 실행시키는 등의 작업들을 예시로 작성하였다.

 

workflows : 앞에서 각 작업(job)들을 모두 정의했다면, 이 작업들을 어떤 조합으로 어떤 조건에서 어떤 순서로 동작할지를 정의한다.

requires : 현재 작업(job)을 수행하기 이전에 선행되어야할 작업 목록을 작성한다.

filter : 현재 작업(job)이 실행되기 위한 조건을 작성한다. 예를 들면, Github의 특정 Branch(ex, master, dev)만 실행할 수 있도록 제한할 수 있다. 예제에서는 master 브런치의 조건에서만 실행시키도록 작성했다.

 

각 항목들에 대한 설명으로 이해가 부족한 부분이 있을 것 같다. 글쓴이의 경우 예제 코드에서 작성된 내용 중에 직관적으로 이해가 가지 않았던 부분으로, CircleCI 에서 지원하는 기능 중에 executor와 cache 이 두 가지 관련 항목에 대해서 조금 더 설명해본다.

 

 

CircleCI Executor ?

executors와 executor항목과 관련된 것이다. Github에 오픈되어 올려둔 많은 프로젝트들을 보면, 대부분이 docker 환경을 사용하고 이 환경 내에 원하는 image를 적용해서 사용하고 있다. 하지만, docker 외에도 macOS, windows, linux를 더 지원하고 있고, 각 OS는 CircleCI에서 제공하는 가상 머신(Virtual Machine) 위에서 동작된다. 결과적으로 executor의 값을 변경해서 다른 원하는 OS 환경에서 테스트가 가능하다는 것이다. 

 

 

[ circleci - executor using docker ]
[ cicleci - executor using macos ]

 

 

CircleCI Cache ? 

config.yml 작성이 완료됬다면, 개발자가 정의해둔 작업(job)들이 많이 있는 것을 볼 수 있다. 이 파일에 작성된 각각의 작업들(jobs)은 서로 다른 프로젝트가 아닌, 하나의 동일한 프로젝트를 서로 다른 형태로 테스트하도록 정의한 것이다. 이 말은 정의해둔 서로 다른 작업들이 동일한 코드와 리소스들을 공유하고 있다는 것이기 때문에, 각 작업을 수행할 때마다 다른 작업에서 처리된 내용들을 그대로 써도 되는 부분들이 많다는 것이다. 따라서 CircleCI는 각 작업의 내용들에 대해 다른 작업(job)에서도 그대로 빠르게 사용할 수 있도록 cache라는 기능을 제공하고 있는 것이다. 아래 그림처럼 workflow에 정의된 작업들이 수행될 때 캐시가 그대로 다음 작업의 실행에 영향을 미치게 함으로써 테스트의 속도를 높일 수 있다. 이 cache는 restore_cache와 save_cache항목으로 설정할 수 있다.

 

 

[ circleci - cache ]

 

 

참고

Restoring Cache 설명 link

CircleCI Executors 설명 link

CircleCI 2.1 Docs 문서 link

Github의 어떤 nodeJS Project 중 .circleci/config.yml 파일 (CircleCI 2.1 사용) link

Github의 어떤 nodeJS Project 중 .circleci/config.yml 파일 (CircleCI 2.0 사용) link

Github의 어떤 maven Project 중 .circleci/config.yml 파일 (CircleCI 2.0 사용) link