connect Firebase Project in CircleCI

도입

RxSocialLogin 의 업데이트를 준비하다가, Demo 앱에 google-services.json 을 추가할 일이 생겼다. 해당 파일은 민감한 정보를 담고 있기에 레포, 특히 공개 레포에는 올리면 안 되는 정보로 .gitignore 에 추가하고 푸시를 진행했다.

그리고 몇 분 후, CircleCI 에서 빌드 오류 메일이 오게 되는데 내용은 google-services.json 가 누락되어 작업을 진행할 수 없다는 내용이었다.

이미 CircleCI docs 페이지 내 관련 내용이 있었지만 문서가 완전하지는 않아 여기에 정리해두려 한다.

과정

먼저, google-services.json 을 gitignore에 추가하여 Git에 올라가지 않게 한다.

그 다음, 터미널에서 google-services.json 이 있는 폴더까지 가서 openssl base64 -in google-services.json -out google-services-encrypted를 실행한다.

해당 커맨드를 실행하여 나온 google-service-encrypted 파일 내용을 복사한다.

그리고 CircleCI 내 프로젝트 설정에 들어가 Environment Variables에 들어간다. 그 다음, ‘Add Variable’를 누르고 Name 로는 GOOGLE_SERVICES_JSON, Value 로는 3번에서 복사한 base64를 붙여넣고 ‘Add Variable’를 누른다.

환경변수를 추가하였으면 프로젝트로 돌아가 CircleCI의 설정 파일인 config.yml 에 아래 내용을 추가한다. (적용된 전체 파일은 https://github.com/WindSekirun/RxSocialLogin/blob/1.0.0-dev/.circleci/config.yml 를 참고하면 된다.)

- run :
name: decrypt google-service.json for CI process
command: echo $GOOGLE_SERVICES_JSON | base64 --decode --ignore-garbage > ${HOME}/${CIRCLE_PROJECT_REPONAME}/app/google-services.json

반영된 내용을 푸시하면 빌드가 성공한다.

마무리

참고로, ${HOME}${CIRCLE_PROJECT_REPONAME}는 CircleCI 내부에 정의된 환경변수로 각각 /home/ubuntu, 프로젝트의 이름을 나타낸다.

 

resolve local.properties in CircleCI

도입

Insert resValue in gradle file(https://blog.uzuki.live/insert-resvalue-in-gradle-file/) 이 글에서 local.properties 에 개인 정보를 넣고 가져오는 방법을 소개했는데, 이 방법을 사용하고 난 후에 CircleCI 에 반영하면 빌드 에러가 나온다.

바로 이 문제인데, local.properties 가 없어서 발생하는 문제였다.

해결 방법

해결 방법은 해당 ocal.properties 파일을 CI 단계에서 생성하면 되는데, 이는 CircleCI 의 설정 파일인 config.yml 을 수정하면 된다.

version: 2
jobs:
  build:
    working_directory: ~/RxSocialLogin
    docker:
      - image: circleci/android:api-26-alpha
    environment:
      JVM_OPTS: -Xmx3200m
    steps:
      - checkout
      - run :
          name: display directory
          command: ls -la
      - restore_cache:
          key: jars-{{ checksum "build.gradle" }}-{{ checksum  "library/build.gradle" }}
      - run:
          name: Download Dependencies
          command: ./gradlew androidDependencies
      - save_cache:
          paths:
            - ~/.gradle
          key: jars-{{ checksum "build.gradle" }}-{{ checksum  "library/build.gradle" }}
      - run:
          name: Run Tests
          command: ./gradlew lint test
      - store_artifacts:
          path: library/build/reports
          destination: reports
      - store_test_results:
          path: library/build/test-results

위 코드가 현재 사용중인 config.yml 의 모습이다. 여기에서 resotre_cahce 하기 전에 커맨드를 넣으면 되는데, 형식은 다음과 같다.

- run :
    name: {표시될 이름}
    command: {실제 Shell 커맨드}

여기서는 local.properties 를 생성할 것이므로 touch local.properties 를 적어주면 된다.

version: 2
jobs:
  build:
    working_directory: ~/RxSocialLogin
    docker:
      - image: circleci/android:api-26-alpha
    environment:
      JVM_OPTS: -Xmx3200m
    steps:
      - checkout
      - run :
          name: display directory
          command: ls -la
      - run :
          name: touch local.properties
          command: touch local.properties
      - restore_cache:
          key: jars-{{ checksum "build.gradle" }}-{{ checksum  "library/build.gradle" }}
      - run:
          name: Download Dependencies
          command: ./gradlew androidDependencies
      - save_cache:
          paths:
            - ~/.gradle
          key: jars-{{ checksum "build.gradle" }}-{{ checksum  "library/build.gradle" }}
      - run:
          name: Run Tests
          command: ./gradlew lint test
      - store_artifacts:
          path: library/build/reports
          destination: reports
      - store_test_results:
          path: library/build/test-results

적용한 것이 위 config.yml 이며 커밋하면 바로 해당 부분이 통과된다.

Migrate CircleCI 1.0 to CircleCI 2.0 (CI/CD for Android)

 

CircleCI 2.0이 나온지 아마 3개월 정도 지났는데,  슬슬 1.0에서 올려야 될 타이밍인 것 같아서 CircleCI 1.0 에서 2.0으로 올리는 방법을 정리하려고 한다

1.0과 2.0의 차이점

기존 CircleCI 1.0에 비해 2.0은 이미 빌드되어 있는 Docker Image를 사용한다. 그와 동시에 캐시 기능도 확실히 제공하기 때문에 1.0에 비해 더 빠른 속도를 제공한다.

왼쪽이 1.0, 오른쪽이 2.0인데 확실히 봐도 속도가 빨라졌음을 알 수 있다.

마이그레이션 방법

기존 circle.yml 삭제

general:
    artifacts:
        - /home/ubuntu/RichUtilsKt/app/build/outputs/apk/

machine:
    environment:
        ANDROID_HOME: /usr/local/android-sdk-linux
        GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"'

dependencies:
    pre:
        - echo y | android update sdk --no-ui --all --filter tools,platform-tools,android-26
        - echo y | android update sdk --no-ui --all --filter build-tools-26.0.2
    override:
        - ANDROID_HOME=/usr/local/android-sdk-linux

compile:
    override:
       - (./gradlew dependencies):
                  timeout: 360

test:
    override:
        - (./gradlew test):
            timeout: 360

단 기존 환경 기준으로 API 26을 사용했다는 것 만큼은 기억해두고 지우자.

.circleci/config.yml 파일 생성

2.0에서 부터는 설정 파일이 .circleci 란 폴더 안에 config.yml 로서 존재하게 되었다.

version: 2
jobs:
  build:
    working_directory: ~/RichUtilsKt
    docker:
      - image: circleci/android:api-26-alpha
    environment:
      JVM_OPTS: -Xmx3200m
    steps:
      - checkout
      - run :
          name: display directory
          command: ls -la
      - restore_cache:
          key: jars-{{ checksum "build.gradle" }}-{{ checksum  "app/build.gradle" }}
      - run:
          name: Download Dependencies
          command: ./gradlew androidDependencies
      - save_cache:
          paths:
            - ~/.gradle
          key: jars-{{ checksum "build.gradle" }}-{{ checksum  "app/build.gradle" }}
      - run:
          name: Run Tests
          command: ./gradlew lint test
      - store_artifacts:
          path: app/build/reports
          destination: reports
      - store_test_results:
          path: richutils/build/test-results

조금 길은데, 하나씩 살펴보자.

  • version: 2.0 이므로 2를 적는다.
  • jobs: 시행할 작업을 나열할 곳이다.
  • working_directory: 작업이 실행될 장소. 보통 프로젝트의 루트 폴더명이다.
  • docker image: 이미 빌드되어 있는 안드로이드 이미지를 적어넣는다. Docker Hub에 따르면 api-23 부터 api-26 까지 있다. 만일 7.0이 대상이라면 api-25 를 적어넣으면 된다.
  • environment: 자바 힙 최대 용량을 3200mb로 설정한다.
  • steps: run, restore_cache, checkout, save_cache 등 문서상에 정의된 내용을 나열하는 곳이다.
  • checkout: git checkout. 더 이상 자세한 설명은 생략한다.
  • run : shell commend 를 실행하는 명령어이다. name 로는 CircleCI 페이지에 표시될 제목, commend 에는 실제 명령어를 작성한다.
  • restore_cache: 주어진 key 로부터 캐시를 불러오는 것이다. 여기서는 ./gradlew androidDependencies 까지를 캐시로 저장한다.
  • save_cahce: 주어진 경로를 캐시하는 기능이다.
  • store_artifacts: 빌드 리포트를 올리는 기능이다.
  • store_test_results: 테스트 결과 리포트를 올리는 기능이다.

여기서 주의할 점은 checksum, store_artifacts, store_test_results 경로를 제대로 설정해야 하는데, 대소문자 구별하는 듯 하다. 실제 파일이 있는 경로를 가리키도록 설정하면 된다.

마지막으로 저장하고 커밋하면 CircleCI 에 빌드 트리거가 걸리고 빌드가 시작된다.

정리

private repo 같은 경우 1x container, 오픈소스 저장소의 경우 4x container 가 지원되는 것 같으니, 앞으로 나오는 왠만한 저장소에 부착하려고 한다.

가끔 정신 나간 상태로 코딩하다 보면 CircleCI 쪽에서 실패 메일이 오게 되면 그때서야 정신을 차리는 일이 다반사이기 때문이다(…