哈囉,我們又見面了,前面幾天我們寫了簡單的測試、讓 CircleCI
自動測試、試玩了兩種資料庫,然後再放到 GAE
(Google App Engine)雲端上執行,那麼今天要做什麼呢?今天就是在 整合
的最後一步:持續部署 (Continous Deployment, CD
),也就是 CI/CD
中的 CD
。
我在這邊所採用的是 DevOps 的概念,也就是 Developement
(開發) 加上 Operation
(營運),將 開發 與 測試 這兩個流程綁在一起,相信講到這裡還是有點模糊,那麼到底什麼是持續佈署 ?
你可以想像你是「開發人員」,假設當你把一個部落格功能做完後,並且在你的電腦 (這邊假設是 Windows) 能正常運作,那麼下一步就是要把你做好的功能交給「營運的部門」,有可能是管 server 的部門,也有可能是你的同事,甚至是你自己,而 server 可能是 Linux,那麼你該怎麼確保你的功能可以在 server 上正常運作 ?,這一步就做 Delivery
(交付) 和Deployment
(佈署)。
你可能需要檢查一下 server 的 linux
版本,你可能需要檢查一下 linux 是否有你在部落格使用的套件,你可能需要檢查一下 server 的 python
版本,你可能需要檢查一下你的程式碼的縮排大小,你可能需要檢查一下你的中英文編碼是否一致,簡而言之,需要注意的點太多,很容易被這些"坑",搞到 你在佈署的時間,甚至比開發還要長,所以避免這樣的情況,我們就來一勞永逸吧 !
「修改完我的 code,然後 commit、push 到 Github,CircleCI 就會偵測到 Github 有新的 commit,自動執行測試,測試完成就自動部署到 GAE 上」
也就是說當我 push 上去 Github
,就喝杯咖啡等測試結果,如果測試沒問題,就直接被放到正式版,使用者可以直接用到 最新而且穩定的版本,如果你不想要每個 commit 都測試、發佈的話,在 CircleCI
也可以把設定,改成把 branch merge 回去 master 的時候,才進行測試和發佈。
你可以自己挑一個專案來做測試,我這邊就用 前天 Day17 和 昨天 Day18 的全新 django project 來做示範。
Github
、將 repository 連接到 CircleCI
細節可以參考 Day13,目前 config.yml
檔的內容,可以先不要管它,晚點我們再來一次解釋。
gcloud
開放授權給 Docker Image
這一步就是告訴 google app engine:「我是真正開發者所授權的 docker image,請相信我所做的一切修改」,參考 官方文件 Authorizing the Google Cloud SDK | CircleCI 2.0,如果你對於發佈的作業系統沒有特定要求要哪個版本的話,可以直接使用 google/cloud-sdk
的 docker image,我這邊就是直接用 google/cloud-sdk
的 docker image,可以略過幾個麻煩的步驟(在官方文件有解釋)。
這個環境變數,跟 系統環境變數
不是同一個名詞,但是一樣的概念,可以放一些比較機密的資料,例如 token、密碼、各種 ID 等等的資料,直接放在 CircleCI
中,它會幫我們進行加密解密,省得我們還要自己處理。
從 Jobs
找到你那個 Project 的齒輪,點進去
找到 BUILD SETTINGS
的 Environment Variables
,再點 Add Variable
,來新增環境變數
GCP
的 IAM&Admin
的 Service Accounts
下載 GCLOUD_SERVICE_KEY因為在 CircleCI 的文件中,沒有提到怎麼下載這個 GCLOUD_SERVICE_KEY
,所以我補充一下,先到 GCP 後台
→ 到 IAM & Admin
→ 再到 Service Accounts
→ 點 動作
的 icon → 點 建立金鑰
→ 選 JSON
下載
切回到 CircleCI 環境變數的分頁,把 JSON金鑰
直接 全部複製,貼到 Value 的欄位
至少一定要加入 GCLOUD_SERVICE_KEY
,另外兩項: 時區 和 專案ID,可以自己選擇要不要加入
GCLOUD_SERVICE_KEY
(必要)GOOGLE_COMPUTE_ZONE
(可選擇)GOOGLE_PROJECT_ID
(可選擇)到目前為止算是把前置作業做完了,接下來進入「告訴 CircleCI,我們的部屬環境、部屬流程」
CircleCI
部屬到 Google App Engine
的執行環境和流程關於 config.yml
可以參考在 Day13 的介紹,簡單來講是個告訴 CircleCI
的 執行環境設定檔,config.yml
需要放在 專案資料夾
之下的 .circleci
資料夾中。
今天的 config.yml
長這樣,主要就是告訴 CircleCI:「請你先幫我執行 測試
,如果測試結果沒問題,再幫我放到 Google App Engine 上去執行」
version: 2.1
# orb 是 CircleCI 特有的
# 可以把 orb 想成已經打包好的環境
# 跟 DockerHub 上的 docker image 很像
orbs:
python: circleci/python@0.2.1
jobs:
# 第一個 job,負責執行`測試`
build-and-test:
executor: python/default
steps:
- checkout
# 為了增加 build 的速度,所設定的暫存
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements.txt" }}
# 執行 python 虛擬環境,並安裝相依套件
- run:
command: |
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
# 為了增加 build 的速度,所設定的暫存
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements.txt" }}
paths:
- "venv"
# 所有測試跑起來
- run:
name: Running tests
command: |
. venv/bin/activate
python3 manage.py test
- store_artifacts:
path: test-reports/
destination: python_app
- persist_to_workspace:
root: .
paths:
- build-and-text
- app.yaml
# 第二個 job 負責執行`部屬`
deploy:
# 採用官方的 docker image 可以省麻煩
docker:
- image: google/cloud-sdk
executor: python/default
steps:
# 別忘了加 `checkout`,
# 是為了讓 deploy 這個 job
# 也能拿到目錄下的檔案
- checkout
# 授權 gcloud,注意 CircleCI 的環境變數
- run:
name: Authorizing gcloud
command: |
echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account django-shop-269303@appspot.gserviceaccount.com --key-file=-
gcloud --quiet config set project ${GOOGLE_PROJECT_ID}
gcloud --quiet config set compute/zone ${GOOGLE_COMPUTE_ZONE}
# 執行 GAE 的 deploy 指令
- run:
name: Deploy to App Engine
command: |
gcloud app deploy
workflows:
main:
jobs:
- build-and-test
- deploy:
# 表示 `build-and-test` 這個 job
# 執行成功後,才會執行 `deploy` 的 job
requires:
- build-and-test
Github
,看看 CircleCI
會不會執行兩個 job第一次會報錯,因為 App Engine Admin API 還沒啟用
App Engine Admin API
這個 API 是「允許能用 RESTful API 來修改 App Engine app」
到這邊應該就可以了 ! 其實最難的是,瞭解 config.yml
怎麼寫,才能符合你的需求
CircleCI
串起來了修改 views.py
、urls.py
,再 push 到 Github
views.py
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def home_view(request):
return HttpResponse("Hi Django on GAE, I am updated when push to github, and deployed by CircleCI~~")
urls.py
from django.contrib import admin
from django.urls import path
from shop.views import home_view
urlpatterns = [
path('', home_view),
path('admin/', admin.site.urls),
]
CircleCI
會不會幫我們自動部屬之後再你每次修改完、push 到 Github 或 merge branch 到 master,都會 自動 執行 測試
和 部屬
兩個工作,潮爽 der ~~
回想二十天前的我,我對 CI/CD 還懵懵懂懂,沒想到我真的走到這一步了,成功把 開發
→ 測試
→ 部屬
的步驟給串起來,這樣可以專心開發功能還有測試碼,其他可以交給平台來解決就好。
很感謝各位的支持,大部分的文章點閱都還不錯,也有好心人點 like,甚至還有破十個追蹤,真的很開心能夠幫助到大家;還有感謝我自己,勇敢地做了一個正確的決定,讓自己從工作中抽離出來,專心地做自己想做的事,再一次感謝我的女朋友,她明明看不懂我在寫什麼 XD,卻還是會看我寫的文章;最後感謝我的家人,他們沒有看不起沒有領薪工作的我,還稱我「到工作室」這件事,叫做「上班」,讓我可以很放心地完成每天的目標,謝謝大家。
我是 RS,這是我的 不做怎麼知道系列 文章,我們 明天見。