.travis.yml을 통한 Travis CI의 빌드 설정
.travis.yml에 대해서 더 자세히 알아보겠습니다. 이 내용은 Configuring your Travis CI build with .travis.yml에 기반하고 있습니다. 앞에서 모든 빌드 설정은 .travis.yml을 사용해서 한다고 했습니다. 이 파일을 통해서 기본값을 사용할 수도 있고 원하는대로 조작할 수도 있습니다.
Travis CI의 워커는 다음과 같은 과정으로 빌드를 수행합니다.
- 언어 런타임 변경 (예를 들어 Ruby 1.9.3이나 PHP 5.4)
- Github에서 프로젝트 저장소 클론
- before_install 스크립트 실행 (있을 경우)
- 클론받은 디렉토리로 이동하고(cd) 의존성 설치 명령어를 실행한다.(기본값은 프로젝트 언어를 따릅니다.)
- after_install 스크립트 실행 (있을 경우)
- before_script 스크립트 실행 (있을 경우)
- 테스트 스크립트 명령어 실행(기본값은 프로젝트 언어를 따릅니다.) 성공했을 경우에는 exit code로 0을 리턴해야 하고 그 외 값은 모두 실패로 간주합니다.
- after_script 스크립트 실행 (있을 경우)
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가지 키에 지정된 내용으로 가능한 모든 조합을 사용해서 테스트를 수행합니다.
- 테스트할 런타임
- 빌드스크립트를 설정할 수 있는 환경변수
- 제외하거나 허용된 실패
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
후후. travis ci 에 대해서까지 블로깅 하실 줄이야. :)
ci 배척이 굉장히 심한 대한민국이라는 나라에서
이 글은 무지 많이 퍼져야 할 글이라고 생각됩니다.
저도 올해초, 깃허브에 조그만한 honor image를 확인하고, 관심을 가졌고 공부한바 있지만
저또한 분위기에 휩쓸려 무관심하고 있었죠. ;;
어디서나 ci 할 수 있는 travis 를 최초로 한국에 전파해주셔서 감사할 따름~~~~
대한민국 최초 맞을거임.
그럼 KIN플 요~~~~~
앗. 국내가 CI에 무지한가요?
현재 업무에선 허드슨을 쓰고 있어서 딱히 의식은 못하고 있었네요.
생각해보면 CI는 Unit Test가 있어야 의미가 더 커지는데 Test를 강조하지 않으니 CI도 자연히 그럴것 같고요 ㅎㅎㅎ
Travis CI는 관심가진지는 좀 되었는데 귀차니즘으로 미루고 있다가요. ㅎㅎㅎ Github처럼 좋은 저장소 인프라에 빠져있던 CI부분을 잘 매꿔준 좋은 서비스라 생각합니다.(사실 CI 운영하는것도 꽤나 귀찮은 일이라서요 ㅎ)
github project 홈페이지에서 travis-ci status icon을 보고 뭔가 쿨한 서비스가 나왔다는것을 직감했었는데 그땐 그냥 이런 ci툴도 있구나 하고 지나갔었죠 ㅎㅎ
그런데 아웃사이더님이 보기 좋게 잘 정리해주셔서 활용할만한 가치가 매우 높은 서비스라는 점을 확인하고 아주 잘 보고 갑니다.
travis-ci는 정말 github과 찰떡궁합인 서비스라고 생각합니다 :)
테스트가 CI의 가장 큰 역활을 차지한다고 생각하기 때문이죠
좋은 글 감사합니다.
예 저장소를 Github를 쓰는 마당에 CI서버를 따로 구축하기어렵고 관리도 만만치 않은데 Travis CI에는 그부분은 잘 해결해 주는 서비스 같습니다. ㅎ