開始使用Travis CI持續整合你的專案吧

Jack_Chou發表於2018-04-15

travis CI簡介

travis CI是一項廣受歡迎的持續整合服務,通過這項技術,我們每次在向程式碼託管平臺push我們的程式碼時,travis就可以自動幫我們完成一系列任務,比如自動將程式碼部署到我們的伺服器,測試等等。而這一系列任務則需要我們在專案主目錄下通過 .travis.yml 檔案進行配置。

travis CI的工作原理也不復雜,它使用了程式碼託管平臺比如 github 提供的 webhooks API ,當我們在程式碼庫執行某些操作(比如將我們的程式碼push到遠端倉庫)時,就會觸發 travis 進行自動化任務的動作。而具體完成什麼任務,則要根據我們的需要通過配置檔案進行配置。

需要注意的是,travis 執行自動化任務並不是在我們本地,也不是在我們的目標伺服器上,而是在 travis 控制檯(可以理解為在 travis 平臺上搭建的虛擬環境)中。它會根據我們專案使用的程式語言靈活搭建所需要的構建環境。

下面我們就直接上一個travis的實際使用案例:

自動部署程式碼

像我們每次寫完程式碼,將程式碼部署到遠端伺服器,重新打包我們的應用再重啟伺服器這樣的體力活完全可以交給我們的主角 ——— travis CI 來完成。

travis 根據我們專案所使用的語言不同,所執行的任務也會有所不同,比如在 JavaScript 專案中,一般會先安裝我們專案中以及構建過程中所需要的依賴,然後執行 npm test 測試命令(執行 npm test 命令是在不定義 script 引數時的預設行為,我們也可以根據實際情況將 script 引數定義為需要執行的命令集合),在命令執行成功之後我們還可以繼續進行其他的操作,比如把程式碼部署到目標伺服器。以上就是一次 build 過程會完成的內容。

我們的配置檔案就是定義在依賴安裝前後,指令碼執行成功(或失敗)之後等等一些時間節點需要 travis 幫我們自動完成的工作。完整的 travis CI 構建過程包含以下這幾個階段:

開始使用Travis CI持續整合你的專案吧

截圖來源:travis CI官方文件

以 JavaScript 專案為例,按照官網的提示,首先需要在官網上對我們要 build 的 github 專案啟用持續整合,接著就可以在專案主目錄下新增一個名為 .travis.yml 的配置檔案,在裡面可以定義我們每次將原生程式碼 push 到遠端倉庫時build所要完成的操作。例如:

language: node_js
node_js:
- 6.10.23
after_success:
- ssh xxx@123.123.123.123 -o stricthostkeychecking=no 'cd /projectMain && git pull && npm run build'
複製程式碼

上面的配置檔案指定我們專案在 travis 控制檯中 build 所需要的構建環境,並且在 travis 執行測試成功之後連線遠端伺服器,到伺服器上的/projectMain目錄拉取最新程式碼並打包。ssh命令可以通過選項 -o stricthostkeychecking=no 來跳過對遠端伺服器返回的 public_key 的檢查。

sshpass實現travis登入伺服器

在上面的配置中,travis控制檯還需要我們手動輸入登入伺服器的密碼,但是我們並不能和travis控制檯進行互動,而且ssh命令也沒有提供一個選項可以用來指定登入密碼。這時我們有兩種方式可供選擇:

  1. 使用 sshpass 傳遞伺服器登入密碼
  2. travis 控制檯通過 ssh 私鑰檔案實現免密連線伺服器

首先介紹使用 sshpass 這種方式。sshpass可以從特定的環境變數 SSHPASS 中獲取到登入時所需要的密碼(使用時需要加上 -e 選項表示從環境變數中讀取)。這時候我們的配置檔案就變成這樣子:

language: node_js
addons:
  apt:
    packages:
    - sshpass
node_js:
- 6.10.23
after_success:
- export SSHPASS=[your password here]
- sshpass -e ssh xxx@123.123.123.123 -o stricthostkeychecking=no 'cd /projectMain && git pull && npm run build'
複製程式碼

但是這樣還有一個問題,就是我們把專案公開出去之後也就暴露了我們的伺服器賬號和密碼,這是相當危險的。travis 也替我們們考慮到了這點,為此也提供了一個用於加密鍵值對的工具。我們可以通過以下命令進行安裝:

$ gem install travis
# 在第一次使用此命令時需要登入
$ travis login
複製程式碼

然後我們就可以對我們不想公開的內容進行加密了,比如:

# 新增 --add 選項可以將加密之後的結果直接新增到.travis.yml檔案中
$ travis encrypt DEPLOY_PASS=[your password here] --add
複製程式碼

然後我們在配置檔案中就可以使用前面定義好的 $DEPLOY_PASS 變數來替換掉我們前面在配置檔案中使用的明文密碼。至此,我們就完成每次push程式碼時,travis都會自動登入遠端伺服器,並更新伺服器上的程式碼。

加密私鑰檔案

除了可以使用sshpass這種方式來傳遞伺服器登入密碼之外,另外一種可以採用類似我們平時使用ssh私鑰檔案來實現免密登入遠端伺服器的方式,讓travis擁有伺服器ssh私鑰檔案來免密登入到我們的伺服器上。

首先我們需要在本地的系統中生成一對用於ssh連線的非對稱金鑰,並將公鑰檔案拷貝到我們的伺服器上,具體過程可以參考網上資料,這裡就不贅述。

然後就是如何讓travis控制檯訪問到我們們在上一步生成的私鑰檔案,這裡需要藉助travis提供的另一個工具:travis encrypt-file 子命令,它可以對我們專案build過程要用到的,但又不能直接公開的檔案進行加密,在加密過程中可以通過 --add 這個可選選項自動向我們的travis配置檔案中新增一個命令用於在build過程中執行解密操作,以獲得加密前的原始檔。具體使用方式如下:

$ travis encrypt-file ~/.ssh/id_rsa --add
複製程式碼

在專案主目錄下執行完上面的指令之後,我們可以看到當前目錄下多出了 id_rsa.enc 檔案,該檔案在後面travis解密得到私鑰檔案時需要被用到。同時我們在當前目錄下的 .travis.yml 檔案中也會發現多出了 before_install 這個欄位,該欄位指定的命令就是用來對 id_rsa.enc 檔案進行解密,這就讓travis控制檯可以訪問上面提到的私鑰檔案了。最後的 .travis.yml 就長下面這個樣子(記得要刪掉before_install 這個欄位指定的命令中的 --out 選項後面多餘的 \ 字元哦):

language: node_js
node_js:
- 8.11.1
after_success:
- ssh xxx@123.123.123.123 -o stricthostkeychecking=no -i ~/.ssh/id_rsa 'cd
  /projectMain && git pull && npm run build && nginx -s reload'
before_install:
- openssl aes-256-cbc -K $encrypted_xxxyyyxxx_key -iv $encrypted_xxxyyyxxx_iv
  -in id_rsa.enc -out ~/.ssh/id_rsa -d
- chmod 600 ~/.ssh/id_rsa
複製程式碼

這時候只需要為配置檔案中的 ssh 命令新增 -i 指定輸出的私鑰檔案儲存路徑即可,另外還需要在before_install欄位增加一個命令,用來修改 ~/.ssh/id_rsa 檔案的訪問許可權(600),否則在後面 build 的過程中因為私鑰檔案訪問許可權過於open而直接導致build errored。注意到生成的 before_install 欄位對應的命令中還用到了兩個環境變數($encrypted_xxxyyyxxx_key$encrypted_xxxyyyxxx_iv),而它們的具體值可以在 travis CI 管理後臺看到。

總結

本文主要介紹了travis CI這個工具的使用,並通過一個具體的?介紹瞭如何通過 travis CI 實現將我們推送的程式碼自動部署到伺服器上。

總體來說,travis CI在解放我們一部分生產力的同時,也為我們及時定位程式碼在交付過程中出現的問題提供了一個很有效的方式。當然,在實際使用中,也發現這個工具本身存在的一些問題,比如build過程本身需要耗費大量的時間,很多操作在每次build都會從頭開始,但往往都是不必要的(比如安裝專案中所需要的依賴),當然對此travis CI也有自己的解決方案,可以通過配置cache欄位,快取專案中的依賴,每次build只需要安裝需要更新的 package,而不是重新安裝全部依賴,這樣也就可以縮短我們的一部分等待時間。更多有趣的地方就等你發掘了~

更多細節可以參考 travis CI 官方文件

相關文章