本文介紹的內容包含:
閱讀本文需要你:
持續集成(Continuous Integration)指開發人員在特性分支(頻繁)提交代碼,立即執行構建和單元測試,代碼通過測試標準後集成到主幹的過程。強調的是分支代碼的提交、構建與單元測試,這個過程的產出是單元測試報告。
說明:這裡的 test 是指unit test(圖片來源見文末參考鏈接)
持續交互(Continuous Delivery)是在持續集成的基礎上,將構建的代碼部署到「類生產環境」,完成QA測試之後手動部署到生成環境的過程。強調代碼部署,這個過程產出測試報告。
說明:這裡的 test 是真的test
持續部署(Continuous Deployment)是持續交互的下一步,強調部署生產環境代碼的過程自動化,同時可以處理上線通知等操作。
說明:與持續交互主要就是手動跟自動的區別。
以一言概之的話我想應該是:機械的事情讓機器做。一個開發團隊,沒有CI/CD,我想可能是這樣子的:無法管理代碼多人多地協作(git repository也是CI的一部分),系列的shell需要人工處理,代碼的發布需要登錄伺服器等等;相反,擁有CI/CD,這些事情都交給機器去完成,騰出的碎片時間去做更有意義的事情(比如摸魚放鬆下)。
我認為理想的CI/CD開發流應該包含三個階段:build、deploy和notify。build階段專註做代碼構建與單元測試,deploy階段專註做test/gray/prod環境的代碼部署,notify階段專註做上線通知,如下圖;
build
deploy
notify
以下內容圍繞build和deploy兩個階段完成從0到1的部署。筆者的系統環境:Ubuntu 18.04.1 LTS
sudo apt-get install gitlab-runner
官網文檔 install gitlab-runner
sudo gitlab-runner register
之後是QA式操作,按照提示語輸入信息即可,可參考官網操作,需要注意:
①. gitlab host和token在你的gitlab項目上找,頁面路徑是:Settings >> CI/CD >> Runners
②. runner執行器選擇 docker,image(鏡像)輸入 node:8.11.2-stretch
node:8.11.2-stretch
註冊成功後,我們就能在:Settings >> CI/CD >> Runners下看到我們註冊的runner
在項目根目錄下新建 .gitlab.yml文件,加入如下內容:
.gitlab.yml
unit_test、compile和deploy_test是自定義的job名字,另外幾點配置說明:
unit_test
compile
deploy_test
cache
stage
artifacts
only
tags
when
on_success
always
manual
dependencies
environment
before_script
先在本機(註冊runner所在的機器)配一遍免密登錄伺服器的流程:
使用rsa作為非對稱加密方式:
ssh-keygen -t rsa -C "$(whoami)@$(hostname)-$(date -I)"
說明:一路enter就好了,切記 Enter passphrase 時直接enter,這樣就是 no passphrase。如果你非要加個password,對不起,沒救了!
在~/.ssh/config文件寫入以下內容(文件不存在直接創建):
Host any_name Port your_port HostName server_ip User user IdentityFile ~/.ssh/id_rsa
說明:定義ssh的config文件是為了快捷訪問,就像你配置host一樣,沒有hostname,你只能訪問ip。配置後你就可以通過 ssh any_name 登錄伺服器了。當然,不出意外,會要求你輸入伺服器的登錄密碼。
ssh any_name
免密登錄的精髓就是:把本機的公鑰存儲到目標伺服器的authorized_keys文件內(該文件伺服器上不存在可以直接創建。)
ssh-copy-id -i ~/.ssh/id_rsa.pub username@ip
特別地:如果你的埠不是默認的22埠,則加上埠號 -p PORT
-p PORT
不出意外,你應該可以直接登錄伺服器了。那麼,我們回到gitlab的配置上~
我們進入gitlab頁面位置:Settings >> CI/CD >> Environment variables下定義 .gitlab.yml 上出現的幾個變數:
SSH_PRIVATE_KEY
TEST_CONFIG
TEST_KNOWN_HOST
ssh-keyscan -p PORT IP
rsync -rve ssh dist/ user@hostname:project_path/dist
說明:hostname就是你在ssh config定義的Host值。rsync操作指南
hostname
ssh config
Host
設置environment的好處是可以對各發布環境進行管理,特別是線上發布,出現bug可以及時操作回滾。 在gitlab web頁面位置:Operations >> environments 可以查看當前項目下的environments,點擊其右側的預覽按鈕即可查看對應環境的發布效果
點擊其中一個environment:test_env,可以查看當前環境下的所有發布記錄,右側的按鈕可以執行回滾操作。
environment:test_env
在整個搭建過程,很多都是關於ssh登錄伺服器的問題,擇幾個高頻出現的問題說明下:
當我們初次使用ssh登錄伺服器的時候,ssh會要求驗證遠程伺服器的身份,通過身份驗證之後才允許連接。解決該問題有兩種方式: - 設置免身份認證: 在ssh config配置中加一段StrictHostKeyChecking no,如此.gitlab.yml配置中就可以去掉關於known_hosts的設置了; - 通過遠程伺服器的公鑰指紋進行身份認證:
StrictHostKeyChecking no
known_hosts
將腳本輸出的結果保存在~/.ssh/known_hosts文件中(@gitlab上定義ssh配置信息部分有提及),這樣ssh在登錄之前會從該文件中拿到目標伺服器的公鑰指紋進行身份確認。
~/.ssh/known_hosts
出現這個問題是沒有配置「ssh免密登錄」,配置操作見@免密登錄部分
這個問題一般情況下並不會出現,但卻是個實實在在的坑。我在deploy的job裡面通過rsync將構建生成的dist目錄上傳至伺服器,拋出不存在該目錄的錯誤。
我在compile這個job執行後,list出根目錄下的文件/夾(gitlab-runner的輸出):
在本機查看根目錄下的文件/夾:
可以看見,gitlab-runner執行構建後實實在在是生成了dist目錄,但進入下一個job的時候卻提示不存在!問題出在: dist目錄並不是由構建直接生成的文件夾,而是release-[timestamp]目錄的軟鏈接(筆者用的是Ubuntu,在webpack配置裡面設置了個騷操作:每次構建產出一個release-[timestamp]目錄,同時建立一個軟鏈。軟鏈不是一個目錄,它的內容就是目標文件夾的地址)。 在我的.gitlab.yml配置裡面,artifacts緩存的是dist,沒有把實際的文件夾release-[timestamp]緩存,那麼進入下一個job的時候,自然就提示不存在該目錄了。解決辦法是:
release-[timestamp]
dist
cp dist public
在compile這個job裡面,構建之後複製一份dist目錄,再將public目錄交由artifacts緩存。
public
推薦閱讀: