以實務為例,帶領大家一步步學習 Gitlab-ci 上各種關鍵字的用法
上篇分享如何在 Gitlab-CI 上執行單元測試,並限制通過測試才可合併分支,而接下來就是本篇的部署了,分享重點會著重在 Gitlab-CI 的部分,以實務例子帶大家更進一步理解 Gitlab-CI 語法設定及部署方式:
- Gitlab-CI 自動化測試 (單元測試入門篇)
- Gitlab-CI 自動化部屬部署 ✔ 本篇
- Gitlab-CI 開發流程細節、整合測試、測試報表
注意:本篇將延續上篇講解的內容,如果不清楚以下 Gitlab-ci.yml 內容,建議先看看上篇,可點擊傳送門移動過去:
本篇重點:開始前請先思考幾個問題
- 有任何方式可以使用指令或腳本將專案部署到遠端伺服器嗎?
- 在 Gitlab-CI 中如何設定才能在測試成功下執行部署?
- 在 Gitlab-CI 中如何才能指定 Job 只在特定 branch 執行嗎?
以上議題如果有任何不清楚或不了解的,我覺得此篇文章將可以給你一點方向,本篇閱讀時間約為 10 分鐘,實作 45 分鐘。
流程說明:持續性整合 ( CI )時機
- 把本機電腦開發完的新功能分支 ( Feature Branch )上傳到 Gitlab
- Gitlab 觸發 Gitlab-CI 執行 pipeline
- GitlabCI 執行自動化測試
- GitlabCI 回傳結果至 Gitlab,pipeline 執行通過則可以被執行 Merge
流程說明: 持續性部署 ( CD ) 時機
- 把新功能分支 Merge 進入 master 分支(此時功能代表已經是合法可上線的功能了)
- Gitlab 觸發 Gitlab-CI 執行 pipeline
- GitlabCI 執行自動化測試
- GitlabCI 測試成功後,執行部署到正式伺服器
- 回傳執行結果至 Gitlab
前傳:如何進行指令部署
想要達成「自動化部屬」之前
要先能達成「能遠端用指令下達部署更新」
實作上大概要做兩件事:
- 整理在更新專案時需要哪些指令,將其寫成腳本
- 獲得伺服器授權,來對伺服器下達更新專案的腳本
以 laravel 專案為例:
- 腳本製作:上線新版本大概要執行以下圖片中的內容
補充:細節上還要注意打包、更新套件時間會不會影響產品服務,如果可以透過一些預先打包、更新來優化
2. 對遠端伺服器下指令:最底層都是使用 ssh 與伺服器連線溝通,所以先在伺服器產生授權金鑰給與要遠端控制的電腦,如果是想給 Gitlab-CI 控制的就也要把金鑰存在 Gitlab 上,以下舉例一個最基礎使用 git 更新專案的控制程式碼。
補充:在管理指令腳本上有許多工具,比如 Ansible 或 Laravel有 envoy 套件
重點一:如何在 Gitlab-CI 上執行自動化部署
搭建實作環境:使用 Heroku 平台建置遠端伺服器環境
因本篇文重點想著重在於 Gitlab-CI 如何做自動化部屬,所以我們選用 Heroku 這種 Paas 的平台做為遠端伺服器,以減少過度花時間架設環境。(且他有免費的方案正適合這種開發練習)
如果有跟我一樣對雲端平台不是很熟悉的朋友,推薦這份簡報「十分鐘讓程式人搞懂雲端平台與技術」。擷取一部分來補助說明大家常見的虛擬機與 heroku 平台上部署專案的差別:
- 虛擬機是由主機服務商提供 “基礎建設即服務”( Iaas ):初級的如 Linode,高級點的如 AWS EC2,在服務商將上圖綠色選項目完成,剩餘的藍色項目。如想架設一個 Laravel 為底的網頁服務,免不了連上虛擬機中手動安裝如:php、nginx、php-fpm、mysql、node、composer 等等服務相依的套件。
- “平台即服務” (Paas):代表如 Heroku ,如果同樣想架設一個 Laravel 服務,將改以服務的 API 指令需要的套件內容,該平台將依據這些內容把整個服務架設起來。
創建 Heroku 帳號即專案
觀看產出的專案服務頁面
申請部署 API 並加入到 Gitlab 上
在 Gitlab 中加入部署所需的變數
- 變數名(HEROKU_PRODUCTION_PROJECT_NAME):同 Heroku 部署專案名稱
- 變數名(HEROKU_PRODUCTION_API_KEY):部署 Token
調整程式碼及 .gitlab-ci.yml
- 承接上篇 laravel 專案範例,開設新分支 test_for_cd
- 新增檔案名稱為 Procfile 於專案根目錄(注意不需要副檔名),此為 Heroku 在部署更新時啟動的對象,比如範例為我們網頁服務使用 apache2 指令運行並把入口指向專案資料夾中 laravel 專案的入口資料夾
web: vendor/bin/heroku-php-apache2 public/
3. 建立或取代 .gitlab-ci.yml 檔,設定自動化部屬的任務 Job 及腳本
上傳至 Gitlab 來觸發 Gitlab-CI 執行自動化部屬
git commit -a -m "settle for continuous deployment"
git push origin test_for_cd
說明 gitlab-ci.yml 中自動化部署 ( CD ) 腳本
環境變數 (environment variables)
環境變數大致可分為三個地方設定
- 預設環境變數:例如 $CI_COMMIT_REF_NAME 可以取得 branch 名稱、$CI_COMMIT_SHA可以得此次版本最後的 commit hash 資料
- CI/CD 環境變數:撰寫在 Gitlab 上,在本篇文章前已經有先把 Heroku 專案的名稱及部署 Token 存進去了(名稱為 HEROKU_PRODUCTION_PROJECT_NAME 跟HEROKU_PRODUCTION_API_KEY)
- 任務環境變數:可以在任務中自行定義變數,此次範例中使用 HEROKU_PROJECT_NAME 變數取用已經有設定在 CI/CD 環境變數的值,雖然有點雞肋,因為其實腳本原本就是可以取用 CI/CD變數,不需要重複宣告一次,但這樣設定可以提醒這個任務是會使用到變數的,習慣上我會這樣設定。
自動化部屬腳本(Continuous Deployment Script)
- 任務執行前腳本(Before Script)
因為這一部分執行目的是將部署需要的套件成功安裝,跟任務主要邏輯是相依關係不是直接關係,但區隔後可以比較明確知道哪些部分是主要 Script,因此決定與 Script 分離。但實際上合併或分離並不會影響執行結果 - 主要執行腳本(Script)
自動化部屬指令執行使用 dpl 這個指令套件,裡面建立有 heroku 的部署工具,只要指定部署專案名稱、部署 Token,即可完成部署。
重點二:整合 Gitlab CI/CD
目標:將自動化單元測試、自動化部屬整合成一個 Pipeline (產線)
部署條件1:完成測試的版本才能進行部署
這邊是一個 CI/CD 合併的 gitlab-ci.yml,裡面包含到
- 自動化單元測試(任務為 unit_test)
- 自動化部屬(任務為 production_deploy)
我們試著 push 到 Gitlab 觸發看看會發生什麼問題。
問題描述:
如果測試單元沒有通過,理論上此版本不應該被部署,因為這樣就會把錯誤的內容丟到正式機器上。
要在 Gitlab-CI 上達成有限制的執行任務,可以使用 stages 語法
這個設定的執行結果可以看到成功達成了部署條件1:
在持續性整合(CI)都通過後,才能進行持續性部屬(CD)。
以下再來統整一下一直提到的 Pipeline、Stage、Job 關係。
Pipeline > Stage > Job
- Job:是整個 Gitlab-CI 裡面最小的執行單位
- Stage:可以包含一個或多個 Job,代表一個執行階段
- Piepline:可以由一個或多個 Stage 組成,即是一次 CI/CD 的所有執行階段,且會依序執行 Stage。如果執行過程中只要有一個 Job 錯誤了,預設後續的 Stage 都會被略過(skip)。
以下有一個比較豐富、完整的 pipeline 動圖,可以比較清楚整個執行的方式。此 pipeline 有三個 stage,stage 內的任務 Job 如果 gitlab runner 夠將可以同步執行,一個 stage 都通過後才會往下一個 stage 移動。
重點三:控制自動化部署(CD)只在特定分支執行
目標:設定 Job 執行條件
部署條件2:要是 master 分支 (指定 branch) 才進行自動化部署
問題敘述:如果不設定自動化部屬的執行條件,將會造成線上版本不斷被不相關的版本覆蓋,造成極大的不穩定,因此通常開發上只有一個分支能部署到正式環境上,那就是 master 分支。而 Gitlab 中還可以設定 master 分支必要通過以下步驟才能有新版本
- 只能通過發 Merge Request 方式
- 需要被 Review 過並寫上通過評論
- 需要有管理者權限才能執行
此次分享完整 .gitlab-ci.yml 程式碼
結尾
非常感謝大家鼓勵,原本預計搭配公司的工程月會時程產出文章,想不到此篇一週後就完成了。而此次內容已經完整實作一個產品最基礎的 CI/CD 設定了,這系列文章目的是希望大家能藉此入門 Gitlab-CI ,甚至在工作上應用看看,而講述方式比較是以實作導向。如果要對 Gitlab-CI 有更全面認識可以參考官方文件都寫的蠻清楚的。
發問!求收集下篇文章的素材
發問 1 :伺服器大集合
此文章中講述自動化部屬時,是用 heroku 為伺服器。但大部分公司應該不會使用 heroku 作為服務的伺服器,因為很貴很貴,大部分還是使用 AWS、GCP、Linode 等等自己管理的伺服器。但不同的伺服器設定方式會有些差異,所以想整理一篇自動化部屬與伺服器溝通的文章。因此想問問大家:
工作上都用哪些平台作為伺服器,及使用什麼方式部署新版本?
發問 2 :開發流程大集合
下篇系列文章預計針對實際開發流程上進行優化,並帶入 Gitlab-CI 一些如 cache、artifact 的實務用法,但這些內容使用我自己工作上的方式可能不太完整,所以:
想問問大家平常工作上都使用哪種開發流程呢?
例如但不限於,希望大家可以留言告訴我:
- 開發測試上有無需要先 build 專案的需求,如整合測試、前端打包
- 開發流程到正式部版前是否有什麼 Review階段,比如 staging 測試機
- 開發上實際有使用什麼樣的測試項目
補充:如果使用 Laravel 及 GCP 為開發環境的,可以參考這篇文章:
如果喜歡我這篇文,可以幫我拍手 1-10 下
如果覺得這文章對你有幫助,可以幫我拍手 10–30 下
如果覺得想看到更多關於學習筆記的文章,可以幫我拍手 30–50 下
讓我知道也記得 Follow我 陳建宇
更歡迎你在下方留言,我很樂意與你討論聊天或回答問題!