# 使用Bitbucket Pipelines 來實做Continuous Delivery / Deployment
# Date: 2019/March/18
環境 & 背景介紹:
Bitbucket, AWS EC2 (Ubuntu), Laravel project (with dotenv file)
我們的程式佈署在EC2上, 可是每次做完pull request, 還要自己手動連進機器裡面佈署最新的程式碼.
手動佈署的工作實在太過無趣, 是不是能用什麼工具來節省寶貴的時間呢?
# 60 seconds
# 簡單暴力解 (bitbucket pipelines & ssh command)
我們需要某種方法, 能讓Bitbucket接收到push的時候, 命令AWS EC2 server自動去執行git pull
(在這個範例是git fetch + git reset), 這樣子便達到了最簡單的自動佈署了!
(保留dot env檔案不進版控, 套件/需要編譯的檔案做最低限度的安裝/更新)
Step 1. Set SSH keys & Known hosts
設定SSH 鑰匙資訊 - Settings > SSH keys (opens new window) > 將公鑰私鑰填入適當的位置, 並把server address加進
Known hosts裡面.
Step 2.
通常AWS EC2上會設定security group, 我們會需要將Bitbucket IP list (opens new window)加入清單當中(用以辨認來自Bitbucket的SSH請求)
Step 3. 在**bitbucket-pipelines.yml**裡, 要執行CD的地方加上這行
$ ssh user@your_host "cd /your/project/path && git fetch - all && git reset - hard origin/your_branch"
它會自動到你要佈署的資料夾裡做類似 git force pull 的動作, 這樣便達到了自動佈署的目的.
當然, 如果有安裝/更新相依性套件的需求, 也能直接加在上面ssh的指令裡, 或是透過 git hook 觸發
# 不使用第三方版控工具 (git bare repository & worktree on deployment server)
如果是要直接將最新的程式推上目標伺服器的話, 也可以使用 **git bare repository**,
配合git hook一樣能達到簡單的自動佈署 (原文請參照這篇 (opens new window))
首先我們先在要佈署的伺服器建立兩個資料夾, 一個是deploy-folder, 另一個則是bare-repository-folder
$ mkdir ~/deploy-folder
$ git init --bare ~/project.git
2
再來是設定git hook, 這裡我們使用的是post-receive
#!/bin/bash
TARGET="/home/webuser/deploy-folder"
GIT_DIR="/home/webuser/project.git"
BRANCH="master"
while read oldrev newrev ref
do
# only checking out the master (or whatever branch you would like to deploy)
if [ $ref = refs/heads/$BRANCH ]; # 這邊在我們的機器上用雙[]會報錯, 因此在這裡改為單[]
then
echo "Ref $ref received. Deploying ${BRANCH} branch to production..."
git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f
else
echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
fi
done
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(記得要把執行的權限打開! git hook會使用git這個使用者)
接著在你自己的本地端加上要佈署目標的資訊
$ cd ~/path/to/working-copy/
$ git remote add production demo@yourserver.com:project.git
2
最後, push讓伺服器觸發deploy的git hook即可.
這個方法是建立一個裸倉庫(bare repository) (opens new window), 並指定它的worktree (opens new window).
當本地端的使用者推送資料到伺服器的時候,
git hook會將這個裸倉庫worktree的資料夾內的程式, 強制指到最新的版本.
所以如果有編譯/安裝相依套件的需求時, 記得要加上執行相關動作的指令.
# 60 minutes
# 開發Bitbucket pipelines 遇到的問題
- Branch workflow
在pipelines (opens new window)裡, 可以針對各個commit / branch設定不同的工作.
需要注意的是, 此處的default/branch是類似if-else條件, 也就是說符合branch條件以後是不會去執行default的內容的.
- Parallel steps
Pipelines可以並行處理腳本, 不過有最多同時執行10筆的上限.
另外, 產生檔案發生衝突時會以最後一個parallel step為準.
# CD with git bare repository and git hook
gist - icyleaf/post-receive.sh (opens new window)
其實一開始我的作法如下圖所示
透過pipeline, git push到server上的裸倉庫後, 再觸發post-receive,
讓deployment資料夾去抓取最新的程式.
不過會遇到git hook沒辦法認得deployment資料夾git 狀態的問題.
這一篇文章的作法有提到使用:
env -i git pull
來替代原本的指令
git pulll
或許可以解決這個問題.
# References
# 其他參考資料
Bitbucket Support - Build, test, and deploy with Pipelines (opens new window)
Bitbucket Support - Bitbucket Deployments (opens new window)
Bitbucket Support - Run pipelines manually (opens new window)