持續整合服務 Travis CI 教程

阮一峰發表於2017-12-19

編寫程式碼只是軟體開發的一小部分,更多的時間往往花在構建(build)和測試(test)。

為了提高軟體開發的效率,構建和測試的自動化工具層出不窮。Travis CI 就是這類工具之中,市場份額最大的一個。

本文介紹 Travis CI 的基本用法。用好這個工具不僅可以提高效率,還能使開發流程更可靠和專業化,從而提高軟體的價值。而且,它對於開源專案是免費的,不花一分錢,就能幫你做掉很多事情。

一、什麼是持續整合?

Travis CI 提供的是持續整合服務(Continuous Integration,簡稱 CI)。它繫結 Github 上面的專案,只要有新的程式碼,就會自動抓取。然後,提供一個執行環境,執行測試,完成構建,還能部署到伺服器。

持續整合指的是隻要程式碼有變更,就自動執行構建和測試,反饋執行結果。確保符合預期以後,再將新程式碼"整合"到主幹。

持續整合的好處在於,每次程式碼的小幅變更,就能看到執行結果,從而不斷累積小的變更,而不是在開發週期結束時,一下子合併一大塊程式碼。

二、使用準備

Travis CI 只支援 Github,不支援其他程式碼託管服務。這意味著,你必須滿足以下條件,才能使用 Travis CI。

  • 擁有 GitHub 帳號
  • 該帳號下面有一個專案
  • 該專案裡面有可執行的程式碼
  • 該專案還包含構建或測試指令碼

如果這些條件都沒問題,就可以開始使用 Travis CI 了。

首先,訪問官方網站 travis-ci.org,點選右上角的個人頭像,使用 Github 賬戶登入 Travis CI。

Travis 會列出 Github 上面你的所有倉庫,以及你所屬於的組織。此時,選擇你需要 Travis 幫你構建的倉庫,開啟倉庫旁邊的開關。一旦啟用了一個倉庫,Travis 會監聽這個倉庫的所有變化。

三、.travis.yml

Travis 要求專案的根目錄下面,必須有一個.travis.yml檔案。這是配置檔案,指定了 Travis 的行為。該檔案必須儲存在 Github 倉庫裡面,一旦程式碼倉庫有新的 Commit,Travis 就會去找這個檔案,執行裡面的命令。

這個檔案採用 YAML 格式。下面是一個最簡單的 Python 專案的.travis.yml檔案。


language: python
script: true

上面程式碼中,設定了兩個欄位。language欄位指定了預設執行環境,這裡設定使用 Python 環境。script欄位指定要執行的指令碼,script: true表示不執行任何指令碼,狀態直接設為成功。

Travis 預設提供的執行環境,請參考官方文件 。目前一共支援31種語言,以後還會不斷增加。

下面是一個稍微複雜一點的.travis.yml


language: python
sudo: required
before_install: sudo pip install foo
script: py.test

上面程式碼中,設定了四個欄位:執行環境是 Python,需要sudo許可權,在安裝依賴之前需要安裝foo模組,然後執行指令碼py.test

四、執行流程

Travis 的執行流程很簡單,任何專案都會經過兩個階段。

  • install 階段:安裝依賴
  • script 階段:執行指令碼

4.1 install 欄位

install欄位用來指定安裝指令碼。


install: ./install-dependencies.sh

如果有多個指令碼,可以寫成下面的形式。


install:
  - command1
  - command2

上面程式碼中,如果command1失敗了,整個構建就會停下來,不再往下進行。

如果不需要安裝,即跳過安裝階段,就直接設為true


install: true

4.2、script 欄位

script欄位用來指定構建或測試指令碼。


script: bundle exec thor build

如果有多個指令碼,可以寫成下面的形式。


script:
  - command1
  - command2

注意,scriptinstall不一樣,如果command1失敗,command2會繼續執行。但是,整個構建階段的狀態是失敗。

如果command2只有在command1成功後才能執行,就要寫成下面這樣。


script: command1 && command2

4.3 例項:Node 專案

Node 專案的環境需要寫成下面這樣。


language: node_js
node_js:
  - "8"

上面程式碼中,node_js欄位用來指定 Node 版本。

Node 專案的installscript階段都有預設指令碼,可以省略。

  • install預設值:npm install
  • script預設值:npm test

更多設定請看官方文件

4.4 部署

script階段結束以後,還可以設定通知步驟(notification)和部署步驟(deployment),它們不是必須的。

部署的指令碼可以在script階段執行,也可以使用 Travis 為幾十種常見服務提供的快捷部署功能。比如,要部署到 Github Pages,可以寫成下面這樣。


deploy:
  provider: pages
  skip_cleanup: true
  github_token: $GITHUB_TOKEN # Set in travis-ci.org dashboard
  on:
    branch: master

其他部署方式,請看官方文件

4.5 鉤子方法

Travis 為上面這些階段提供了7個鉤子。

  • before_install:install 階段之前執行
  • before_script:script 階段之前執行
  • after_failure:script 階段失敗時執行
  • after_success:script 階段成功時執行
  • before_deploy:deploy 步驟之前執行
  • after_deploy:deploy 步驟之後執行
  • after_script:script 階段之後執行

完整的生命週期,從開始到結束是下面的流程。

  1. before_install
  2. install
  3. before_script
  4. script
  5. aftersuccess or afterfailure
  6. [OPTIONAL] before_deploy
  7. [OPTIONAL] deploy
  8. [OPTIONAL] after_deploy
  9. after_script

下面是一個before_install鉤子的例子。


before_install:
  - sudo apt-get -qq update
  - sudo apt-get install -y libxml2-dev

上面程式碼表示before_install階段要做兩件事,第一件事是要更新依賴,第二件事是安裝libxml2-dev。用到的幾個引數的含義如下:-qq表示減少中間步驟的輸出,-y表示如果需要使用者輸入,總是輸入yes

4.6 執行狀態

最後,Travis 每次執行,可能會返回四種狀態。

  • passed:執行成功,所有步驟的退出碼都是0
  • canceled:使用者取消執行
  • errored:before_installinstallbefore_script有非零退出碼,執行會立即停止
  • failed :script有非零狀態碼 ,會繼續執行

五、使用技巧

5.1 環境變數

.travis.ymlenv欄位可以定義環境變數。


env:
  - DB=postgres
  - SH=bash
  - PACKAGE_VERSION="1.0.*"

然後,指令碼內部就使用這些變數了。

有些環境變數(比如使用者名稱和密碼)不能公開,這時可以通過 Travis 網站,寫在每個倉庫的設定頁裡面,Travis 會自動把它們加入環境變數。這樣一來,指令碼內部依然可以使用這些環境變數,但是隻有管理員才能看到變數的值。具體操作請看官方文件

5.2 加密資訊

如果不放心保密資訊明文存在 Travis 的網站,可以使用 Travis 提供的加密功能。

首先,安裝 Ruby 的包travis


$ gem install travis

然後,就可以用travis encrypt命令加密資訊。

在專案的根目錄下,執行下面的命令。


$ travis encrypt SOMEVAR=secretvalue

上面命令中,SOMEVAR是要加密的變數名,secretvalue是要加密的變數值。執行以後,螢幕上會輸出如下資訊。


secure: ".... encrypted data ...."

現在,就可以把這一行加入.travis.yml


env:
  global:
    - secure: ".... encrypted data ...."

然後,指令碼里面就可以使用環境變數$SOMEVAR了,Travis 會在執行時自動對它解密。

travis encrypt命令的--add引數會把輸出自動寫入.travis.yml,省掉了修改env欄位的步驟。


$ travis encrypt SOMEVAR=secretvalue --add

詳細資訊請看官方文件

5.3 加密檔案

如果要加密的是檔案(比如私鑰),Travis 提供了加密檔案功能。

安裝命令列客戶端以後,使用下面的命令登入 Travis CI。


$ travis login 

然後,進入專案的根目錄,使用travis encrypt-file命令加密那些想要加密的檔案。


$ travis encrypt-file bacon.txt

encrypting bacon.txt for rkh/travis-encrypt-file-example
storing result as bacon.txt.enc
storing secure env variables for decryption

Please add the following to your build script (before_install stage in your .travis.yml, for instance):

    openssl aes-256-cbc -K $encrypted_0a6446eb3ae3_key -iv $encrypted_0a6446eb3ae3_key -in bacon.txt.enc -out bacon.txt -d

Pro Tip: You can add it automatically by running with --add.

Make sure to add bacon.txt.enc to the git repository.
Make sure not to add bacon.txt to the git repository.
Commit all changes to your .travis.yml.

上面的程式碼對檔案bacon.txt進行加密,加密後會生成bacon.txt.enc,該檔案需要提交到程式碼庫。此外,該命令還會生成一個環境變數$encrypted_0a6446eb3ae3_key,儲存金鑰,儲存在 Travis CI,檔案解密時需要這個環境變數。你需要把解密所需的openssl命令,寫在.travis.ymlbefore_install欄位裡面。這些都寫在上面的命令列提示裡面。

--add引數可以自動把環境變數寫入.travis.yml


$ travis encrypt-file bacon.txt --add

encrypting bacon.txt for rkh/travis-encrypt-file-example
storing result as bacon.txt.enc
storing secure env variables for decryption

Make sure to add bacon.txt.enc to the git repository.
Make sure not to add bacon.txt to the git repository.
Commit all changes to your .travis.yml.

詳細資訊請看官方文件,實際的例子可以參考下面兩篇文章。

(完)

相關文章