Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Travis CI 소개 #2

이 포스팅은 Travis CI 소개 #1에서 이어진 포스팅입니다.




.travis.yml을 통한 Travis CI의 빌드 설정
.travis.yml에 대해서 더 자세히 알아보겠습니다. 이 내용은 Configuring your Travis CI build with .travis.yml에 기반하고 있습니다. 앞에서 모든 빌드 설정은 .travis.yml을 사용해서 한다고 했습니다. 이 파일을 통해서 기본값을 사용할 수도 있고 원하는대로 조작할 수도 있습니다.

Travis CI의 워커는 다음과 같은 과정으로 빌드를 수행합니다.

  1. 언어 런타임 변경 (예를 들어 Ruby 1.9.3이나 PHP 5.4)
  2. Github에서 프로젝트 저장소 클론
  3. before_install 스크립트 실행 (있을 경우)
  4. 클론받은 디렉토리로 이동하고(cd) 의존성 설치 명령어를 실행한다.(기본값은 프로젝트 언어를 따릅니다.)
  5. after_install 스크립트 실행 (있을 경우)
  6. before_script 스크립트 실행 (있을 경우)
  7. 테스트 스크립트 명령어 실행(기본값은 프로젝트 언어를 따릅니다.) 성공했을 경우에는 exit code로 0을 리턴해야 하고 그 외 값은 모두 실패로 간주합니다.
  8. after_script 스크립트 실행 (있을 경우)
이 과정 중에서  프로젝트 저장소 클론과 디렉토리를 바꾸는 과정 빼고는 모두 .travis.yml에서 변경할 수 있습니다. Travis CI는 각 빌드간에 빌드간에 상태가 유지되지 않음을 보장하기 위해서 가상머신 스냅샷을 사용않기 때문에 디비에 값을 쓰거나 파일 생성등 어떤 쓰기 작업으로 CI 환경을 수정해도 이어진 빌드에는 영향을 주지 않습니다.


script
script 키로 기본값 대신 메인 빌드 명령어를 지정할 수 있습니다.

script: "make it-rain"

어떤 스크립트든 실행할 수 있으면 성공하면 exit code로 0을 사용해야 합니다. 그 외는 모두 실패가 됩니다. 그리고 필요한 정보를 콘솔에 출력하면 사이트에서 리얼타임으로 메시지를 볼 수 있습니다. 저장소 로컬 스크립트를 실행하려면 다음과 같이 지정합니다.

script: ./script/ci/run_build.sh



before_script, after_script
메인 빌드 스크립트 이전과 이후에 실행할 스크립트를 지정할 수 있습니다.

before_script: some_command
after_script:  another_command


다음과 같이 여러 명령어를 지정할 수도 있습니다.

before_script:
  - before_command_1
  - before_command_2
after_script:
  - after_command_1
  - after_command_2


이 과정에서는 데이터베이스를 설정하거나 빌드를 위한 어떤 작업을 수행할 때 사용할 수 있습니다. 참고로 after_script는 빌드가 성공했을 때만 실행됩니다.


install
표준적인 의존성 관리도구를 사용하지 않으면 install 키로 의존성 설치 명령어를 지정해야 하고 어떤 스크립트든 사용할 수 있지만 성공하면 0으로 끝나야 합니다.

install: ant install-deps



before_install, after_install
의존성 설치 스크립트 이전과 이후에 실행할 스크립트를 정의할 수 있습니다.

before_install: some_command
after_install:  another_command


다음과 같이 여러 명령어를 지정할 수도 있습니다.

before_install:
  - before_command_1
  - before_command_2
after_install:
  - after_command_1
  - after_command_2


이 스크립트에서는 보통 git 저장소의 서브모듈을 업데이트(서브모듈 업데이트에 대한 내용은 해당 가이드에 자세히 나와 있습니다.)하거나 의존성 설치 전에 해야하는 작업들을 지정합니다.


런타임 선택
Travis CI에서는 여러가지 런타임과 버전에서 테스트 슈트를 실행할 수 습니다.

rvm:
  - 1.8.7
  - 1.9.2
  - 1.9.3
  - jruby
  - rbx-18mode


.travis.yml에서 지정한 런타임과 버전에서 모두 테스트를 실행합니다.


환경 변수 설정

env: DB=postgres


위처럼 환경변수를 지정할 수 있습니다. ENV 변수는 빌드중에 설정되므로 테스트 슈트가 수행 중인지 탐지할 때 사용할 수 있습니다. 다음과 같이 env 배열을 통해서 여러가지 환경변수를 설정할 수 있습니다.

rvm:
  - 1.9.3
  - rbx-18mode
env:
  - FOO=foo BAR=bar
  - FOO=bar BAR=foo



이렇게 설정할 경우 총 4개의 빌드가 실행됩니다.

  • Ruby 1.9.3에 FOO=foo와 BAR=bar
  • Ruby 1.9.3에 FOO=bar와 BAR=foo
  • Rubinius 1.8 a모드에 FOO=foo와 BAR=bar
  • Rubinius 1.8 a모드에 FOO=bar와 BAR=foo

apt를 이용한 패키지 설치
네이티브 라이브러리에 대한 의존성이 있다면 비밀번호를 사용하지 않는 sudo를 통해 설치할 수 있습니다.

before_install:
  - sudo apt-get update
  - sudo apt-get install [packages list]

빌드는 가상머신 스냅샷에서 실행되고 빌드후에는 초기상태로 롤백되기 때문에 네이티브 패키지를 필요한대로 설치할 수 있습니다. Travis CI는 우분투 11.04와 11.10을 사용하고 있으므로 여기서 사용가능한 패키지는 서드파티 PPA에서도 설치할 수 있습니다.


빌드 타임아웃
테스트 슈트나 스크립트가 행아웃이 걸릴 수 있으므로 Travis CI는 하드타임 제한을 두고 있습니다. 타임아웃이 넘어가면 빌드는 강제적으로 종료됩니다. 정확한 타임아웃은 프로젝트 종류에 따라 다르지만 보통 테스트 슈트 실행에 10~15분정도이고 before_script에 5~10분 정도입니다. 행아웃이 걸리는 이유는 키보드 인풋을 기다리거나 데드락이나 라이브락같은 동시성 이슈, 네이티브 라이브러리를 컴파일하고 설치하는데 오래걸리는 등이 있습니다.


빌드 브랜치 지정
Travis 는 Github가 전달한 git commit에 지정한 브랜치가 .travis.yml에 지정되어 있는지 찾을 것이고 한 브랜치에 설정된 내용은 다른 브랜치에는 영향을 미치지 않습니다. 다음과 같이 빌드할 브랜치의 화이트리스트와 빌드하지 않을 블랙리스트 브랜치를 지정할 수 있습니다.

# blacklist
branches:
  except:
    - legacy
    - experimental

# whitelist
branches:
  only:
    - master
    - stable



브랜치를 양쪽에 다 지정하면 except쪽은 무시합니다. 브랜치 리스트에는 다음과 같이 정규표현식을 사용할 수도 있는데 /로 감싸진 이름은 정규표현식으로 간주하고 Ruby에서 지원하는 정규표현식은 모두 사용할 수 있지만 /뒤에 옵션(i나 g같은)은 지원하지 않습니다.

branches:
  only:
    - master
    - /^deploy-.*$/




노티피케이션
Travis CI는 빌드 결과를 이메일이나 IRC, 웹훅을 통해서 알림을 보낼 수 있습니다. 기본적으로는 이메일로, 커밋한 사람과 커미터, 저장소 소유자와 저장소가 속한 조직의 모든 공개멤버에게 메일을 보냅니다. 메일은 빌드가 깨지거나 계속 깨진 상태로 있을 때와 깨져있던 빌드가 고쳐졌을 때 보냅니다. 물론 이 동작도 옵션으로 바꿀 수 있습니다. 다음과 같이 이메일을 받을 수신자를 지정할 수 있습니다.

notifications:
  email:
    - one@example.com
    - other@example.com



다음과 같이 지정하면 이메일을 보내지 않습니다.

notifications:
  email: false



다음과 같지 이메일을 보낼 때를 지정할 수도 있습니다. always와 never는 항상 보내거나 항상 보내지 않는 다는 것이며 change는 빌드상태가 변경되었을 때 보내는 것을 나타냅니다.

notifications:
  email:
    recipients:
      - one@example.com
      - other@example.com
    on_success: [always|never|change] # default: change
    on_failure: [always|never|change] # default: always



IRC나 웹훅에 대한 설정은 가이드문서를 참고하세요.




빌드 매트릭스
Travis는 다음 3가지 키에 지정된 내용으로 가능한 모든 조합을 사용해서 테스트를 수행합니다.

  • 테스트할 런타임
  • 빌드스크립트를 설정할 수 있는 환경변수
  • 제외하거나 허용된 실패
예를 들면 다음과 같이 설정한 경우 총 28개의 빌드가 실행됩니다.  Travis CI는 오픈소스 서비스로 커뮤니티가 제공하는 워커박스를 사용하므로 필요한 조합만으로 빌드 매트릭스를 구성해야 합니다.

rvm:
  - 1.8.7 # (current default)
  - 1.9.2
  - 1.9.3
  - rbx-18mode
  - jruby
  - ruby-head
  - ree
gemfile:
  - gemfiles/Gemfile.rails-2.3.x
  - gemfiles/Gemfile.rails-3.0.x
  - gemfiles/Gemfile.rails-3.1.x
  - gemfiles/Gemfile.rails-edge
env:
  - ISOLATED=true
  - ISOLATED=false




불필요한 빌드 매트릭스는 다음과 같이 제외할 수 있습니다. 제외는 정확히 일치한 조합만 제외합니다.

matrix:
  exclude:
    - rvm: 1.8.7
      gemfile: gemfiles/Gemfile.rails-2.3.x
      env: ISOLATED=true
    - rvm: jruby
      gemfile: gemfiles/Gemfile.rails-2.3.x
      env: ISOLATED=true




빌드 매트릭스에서 실패해도 상관없는 빌드를 지정할 수 있습니다. 이렇게 지정한 빌드는 실패해도 전체 빌드를 실패한 것으로 간주하지 않기 때문에 공식적으로 지원하지 않는 버전이나 환경 등에 사용할 수 있습니다.

matrix:
  allow_failures:
    - rvm: 1.9.3







데이터 스토어 설정
Travis CI에서 테스트를 위한 데이터스토어 설정에 대해서 설명하고 이 내용은 Databases on Travis workers에 기반하고 있습니다. Travis CI에는 다음과 같은 데이터 스토어가 미리 설치되어 있으며 대부분은 기본 설정을 사용하고 있습니다.

  • MySQL
  • PostgreSQL
  • SQLite3
  • MongoDB
  • CouchDB
  • Redis
  • Riak
  • Memcached

MySQL
MySQL은 127.0.0.1에 바인딩 되고 "root" 사용자명으로 비밀번호 없이 인증할 수 있습니다. MySQL 클라이언트에 따라서 사용자명을 입력안하면 root로 인식하는 것도 있고 익명유저로 인식하는 것도 있으니 주의해야 합니다. MySQL을 사용하려면 먼저 myapp_test 데이터베이스를 생성해야 하고 다음과 같이 빌드스크립트에서 실행합니다.

# .travis.yml
before_script:
  - mysql -e 'create database myapp_test;'




루비 프로젝트에서 ActiveRecord를 사용한다면 config/database.yml 파일에 다음과 같이 설정합니다.(database.yml은 레일즈에서 사용하는 디비 설정파일로 다른 언어를 사용한다면 설정 내용만 참고하시면 됩니다.)

mysql:
  adapter: mysql2
  database: myapp_test
  username: root
  encoding: utf8





PostgreSQL
PostgreSQL은 127.0.0.1로 바인딩 되고 "postgres" 사용자명으로 비밀번호 없이 인증할 수 있습니다. MySQL과 마찬가지로 빌드과정에서 데이터베이스를 생성해야 합니다.

# .travis.yml
before_script:
  - psql -c 'create database myapp_test;' -U postgres




루비 프로젝트에서 ActiveRecord를 사용한다면 config/database.yml 파일에 다음과 같이 설정합니다.

postgres:
  adapter: postgresql
  database: myapp_test
  username: postgres





SQLite3
루비 프로젝트라면 sqlite3 루비 바인딩이 번들에 포함되어 있는지 확인해야 합니다.

# Gemfile
# for CRuby, Rubinius, including Windows and RubyInstaller
gem "sqlite3", :platform => [:ruby, :mswin, :mingw]

# for JRuby
gem "jdbc-sqlite3", :platform => :jruby




루비 프로젝트에서 ActiveRecord를 사용한다면 config/database.yml 파일에 다음과 같이 설정합니다.

test:
  adapter: sqlite3
  database: ":memory:"
  timeout: 500





MongoDB
MongoDB는 127.0.0.1에 바인딩되고 인증이 필요없으면 미리 디비를 생성할 필요도 없습니다. 데이터베이스에 사용자를 추가해야 하면 before_script에서 지정할 수 있습니다.

# .travis.yml
before_script:
  - mongo mydb_test --eval 'db.addUser("travis", "test");'





CouchDB
CouchDB는 127.0.0.1에 바인딩 되고 인증이 필요없습니다.(admin party로 실행됩니다.) 다음과 같이 빌드과정에서 데이터베이스를 생성해야 합니다.

# .travis.yml
before_script:
  - curl -X PUT localhost:5984/myapp_test





Redis
Redis는 기본 설정을 사용하고 LevelDB 스토리지를 백엔드로 설정했습니다.


Redis
Redis는 기본 설정을 사용하고 localhost로 사용할 수 있습니다.


Cassandra
Cassandra는 설치는 되어 있지만 시작되어 있지 않으므로 before_install에서 시작해 주어야 합니다. Cassandra는 Datastax Community Edition을 사용하고 127.0.0.1에 바인딩 됩니다.

before_install:
  - sudo service cassandra start
  - sleep 3





Neo4J
Neo4J는 서버 커뮤니티 에디션을 사용할 수 있지만 시작되어 있지 않으므로 before_install에서 시작할 수 있습니다.

before_install:
  - which neo4j && sudo neo4j start
  - sleep 3





ElasticSearch
ElasticSearch도 시작되어 있지 않으므로 시작해 주어야 합니다. ElasticSearch는 공식 데비안 패키지를 사용하며 127.0.0.1에서 사용할 수 있습니다.

before_install:
  - sudo service elasticsearch start
  - sleep 3





여러가지 데이터베이스 사용

DB 환경변수를 사용해서 사용하는 데이터베이스를 지정할 수 있습니다. 이를 다음과 같이 설정할 수 있습니다.

# .travis.yml
env:
  - DB=sqlite
  - DB=mysql
  - DB=postgres
2012/05/01 01:46 2012/05/01 01:46