Day 1 閱讀之日
序
來到這個階段代表你的軟體已經接近成型!準備供他人做使用,但很多程式的初學者與新鮮人對於建置與部署的細節不太熟悉,常常認為 Code 只要可以動就好了,卻忽略了後續的運維問題 🥺
— 簡單來說軟體建置與部署的目的,就是為了確保軟體在被交付給客戶或使用者時能夠順利執行 —
為什麼要花時間做這個?
相信大家最常碰到的問題就是,換了個環境,程式突然無法順利執行,俗稱「Demo 魔咒😈」。如果是在重要的場合發生的話,可能會大大影響團隊與產品的聲譽。
那我該注意什麼?
- 軟體版本的控制:軟體版本是造成程式”突然”無法運行的很大一個因素,像是軟體執行的環境版本過老舊,或使用的套件版本太新不穩定。除了通過實際測試,也有許多方便的套件管理工具,像是 Node.js 的 npm、Yarn 以及 Python 的 pip、Poetry …等,來幫助我們減少版控發生的錯誤。
- 作業系統的不同:有些 Coding 語法可能會因為作業系統的不同,而無法兼容。當然在開發前肯定會詢問客戶執行的環境,不過以前踩過雷還是補充一下🙁
- 環境變數(Environment Variable)的設置:因為 .env 通常都放一些重要的變數設定,時常是以 Example 狀態被 Clone 下來,常常忘記更改就拿去執行。
以上就是一些注意事項,當然軟體能否順利運行,還有許多因素,像客戶硬體環境的磁碟大小…等等,這些都是要經過不斷實測才能完成的,所以軟體建置與部署,真的是耗時又耗力 😥
DevOps
有了基本概念後,我們來了解一個軟體建置與部署的文化 DevOps,它是 Development(開發)與 IT Operation(運維)的組合詞,正式因為開發工程師與運維工程師常常在軟體的生命週期上發生爭執,所以希望開發工程師與運維工程師互相合作、多為彼此著想。
試想一下開發工程師只要程式能在自己的環境上跑就交給運維工程師,運維工程師發現不能在客戶指定的環境執行,心情是如何?🤬🤬🤬🤬
DevOps 主打的概念是 **快速、fast、schnell、vite、nopeasti、snel、เร็ว,**快還要更快
實現 DevOps 精神的方法?
- 持續整合(Continuous Integration):一旦團隊的程式碼有所更新,就馬上進行測試並整合。
- 持續部署(Continuous Deployment):整合完畢後,馬上將最新的版本部署至 server。
- 微服務(Microservice):簡單來說就是將一個軟體的功能,拆分為幾個獨立的服務,並透過其他方式讓他們連接運作,各個服務也能隨時更新替換(
就像人體器官一樣各司其職,壞掉了也可以替換)
以上都是簡單列舉,如果想更詳細的了解 DevOps,可以自己去搜尋相關文章閱讀喔😎
What’s CI/CD ?
經過上面 DevOps 的介紹,我們知道 CI/CD 正是去實踐其精神的方式,也藉此提高軟體的交付速度,現在讓我們更仔細去認識 CI/CD 中的意義吧!
CI(Continuous Integration)持續整合
如果團隊的程式碼整合頻率太少,可能會發生以下事情:
- 整合的程式碼越多,發生問題的可能性就越大,加上萬一有部份程式碼大改,一旦整合失敗就會使得團隊必須花費大量時間去修正以及除錯。
- 由於程式碼太久做整合更新,團隊的重工機率會大幅上升,縱使每天開會還是無法避免,個人經驗 ~
🤔 這階段在幹嘛?
- 軟體建置(Build): 確保程式碼在整合之後,能夠在指定的環境中成功執行。
- 軟體測試(Test): 確保程式碼在整合之後,能通過單元測試(Unit Test)、整合測試(Integration Test)。
CD(Continuous Deployment / Continuous Delivery)持續部署 / 持續交付
經過前面的整合完成,接下來我們還要確保軟體能夠成功上線,還能夠快速交付給使用者做使用。
🤔 這階段在幹嘛?
- 軟體部署(Deployment): 將 CI 完畢的程式碼,部署到指定的 Server 中,並確保其順利營運。
- 軟體交付(Delivery): 將軟體更新檔交給使用者,確保其能享受最新服務。
當然身為一個工程師,這種長期繁瑣的重複動作,自然有 Automatic 的必要性,所以市面上可以找到許多開源的 CI/CD 工具,像是 Jenkins、Github Action…等等,供大家做使用。
Day 2 認識 GitHub Action (CI/CD 工具)
GitHub Action 是 GitHub 於 2019 年推出的一套 CI/CD 工具,
當然前提是要有 GitHub 帳號,相信看文章的大家應該都有吧?沒有點此
第一次的 GitHub Action
當你隨便進一個 Repository 時,你會看到有一個 Action 的 Tag,如下圖。
點進去就破題了,這就是 CI/CD 的相關頁面,建立成功後他就會改成另一種頁面(期待一下😀)。
然後往下滑可以看到 Workflows,你可以看到許多別人寫好的 yaml 檔,當然你可以直接拿來用,但因為怕混亂我們暫且不使用(有點類似Quick Start的感覺)。
如果有興趣的人可以隨便 Configure 一個來玩,你就會發現 Github Action 開始轉動了 (因為你剛剛 Push了 yaml 檔),至於成不成功又是另外一回事了🤣。
其實 CI/CD 自動化的關鍵在於
流程與觸發
兩個概念上。
你需要一個流程(Workflows)處理軟體程式碼的測試與部署,你還需要一個條件,來幫助你觸發時會執行你設計好的流程。
打造第一個 Workflows
解釋一下這個 LGTM Reaction 到底是什麼東西,它是一個別人設計好的 Workflows,當有人在你的 Issues 中留 lgtm 時,它會自動回傳一張意義不明的圖片。
我知道這很沒用,但它對於 GitHub Action 新手來說真的很讚,讓你了解流程與觸發的意義!
- 流程:當有人留 **“lgtm”**時,使用 LGTM Reaction 回傳一張意義不明的圖片。
- 觸發條件:當有人在我的 Issues 留 “lgtm”(小寫注意是小寫)。
我們的第一個 yaml 檔
要打造 Workflows 首先就必須創建 yaml 檔
然後在這邊輸入 yaml 的檔案路徑和名稱,切記一定要是.github/workflows/some-name.yaml
的形式,不然 GitHub Action 是吃不到你的 yaml 檔喔。
然後我們把 LGTM Reaction 寫好的 yaml code 直接貼進來~~(成為碼農的第一步)~~
name: Send LGTM reaction
on:
issue_comment:
types: [created]
pull_request_review:
types: [submitted]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1.0.0
- uses: micnncim/action-lgtm-reaction@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
貼完我們直接創建
創建成功後,你會發現原本的 Action 頁面,會變成流程列表,它會列出每次觸發流程的紀錄。
來試著觸發流程!
我們創建一個 Issue (這邊不多作教學),然後試著在剛創好的 Issue 留下 “lgtm”
※第一次創建 Issue 直接輸入 ****“lgtm” 是不會觸發流程的,他設計的不要問我
大成功!
我們再回到 Action 頁面查看,可以發現 Workflows 多了一條紀錄,它記錄了事件的名稱(Commit Content)、流程的過程、成功或失敗。
好了以上其實就是 CI/CD 的過程,只是跟想像的不太一樣,我們只要思考一下將流程步驟稍加更改,就會更接近你所想像的 CI/CD 了。
思考時間 – yaml 檔裡面在寫什麼?
我們看看剛剛複製貼上的 yaml code,是時候還債了,我們要了解它其中的內容在寫什麼😆
name: Send LGTM reaction
on:
issue_comment:
types: [created]
pull_request_review:
types: [submitted]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1.0.0
- uses: micnncim/action-lgtm-reaction@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name
:整個 Workflows 的名稱
on
:Workflows 的觸發條件
可以看到觸發事件有兩個issue_comment
以及pull_request_review
,它們都是 GitHub Action 所設計好的事件,還有更多的事件可以自己慢慢摸索。
issue_comment
的觸發條件是 [created](在 issue 建立留言時觸發,也就是我們剛剛玩的範例)
pull_request_review
的觸發條件是 [submitted](在 pull request 裡的 review 中發送 “lgtm”,也會觸發,這個剛剛沒有實作,想觸發此條件的人可以自己研究看看 pull request 是什麼)
jobs
:Workflows 所做的事情
build
:是一個 Job 的名稱,將 Workflows 要做的事情再細分**,**也可以隨意命名,你要改叫 “abc” 也沒問題。(更簡單來說就是有個 Job 叫 build,Workflows 可能會有一堆 Job)
runs-on
:這個是指定你的程式碼要傳送到哪邊進行整合或測試,GitHub Action 有提供他們的機器來讓大家練習 **CI/CD,**你只需要輸入你想在哪個環境中進行即可,此範例就是使用 GitHub 所提供的 ubuntu-latest 版本。當然你也可以輸入 self-hosted
然後設定自己的 Runner 去進行整合與測試。(因為是 CI/CD 工具一定會有的功能,如果你急著想懂的話可以自己搜尋,或等待明天的實作我會更詳細的介紹)
steps
:Job 要做的指令步驟(簡單一點想就是你 runs-on
那台機器的 terminal 你要使用到的指令)
uses
:你使用到別人所寫好的指令,像這邊就使用到 actions/checkout@1.0.0 (有沒有其實沒關係,但它是 GitHub Action 一個重要的套件,功能是 Pull 你所指定 branch 的 程式碼,非常實用)以及剛剛我們玩的 micnncim/action-lgtm-reaction@master
run
:執行 terminal 指令,長得像下面這樣,讓 terminal 印出 “Hello World!“
run: echo "Hello World!"
好了大致上 GitHub Action 的 yaml code 就是這樣寫的。哀你說什麼? env
是什麼,你沒講啊😡
因為想要在這邊要補充一下 steps 的寫法,其實還有很多方式,像以幫它們取名字為例。
我想要幫我每個 steps 都取個名字,好讓大家看得懂我 CI/CD 在做什麼,你會看到一個 steps 只能有一個 -
,而不是像上面一樣逐漸往內縮~~(我不知道你去問設計的人)~~
steps:
- name: pull my code to runs-on machine
uses: actions/checkout@1.0.0
- name: use action-lgtm-reaction
uses: micnncim/action-lgtm-reaction@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
而 env
正是你使用 action-lgtm-reaction 所需要的環境變數 GITHUB_TOKEN
,然後帶入的值是secrets.GITHUB_TOKEN
(不了解 GitHub secrets 的可以自己去查詢,它會讓的對 GitHub 安全設計更加了解!)
思考時間 – 這跟我想像的 CI/CD 不同啊?你是不是騙我?
對
試著想想要怎麼樣才能把剛剛的流程變成理想中的 CI/CD 🤔
- 流程:
當有人留 **“lgtm”**時,使用 LGTM Reaction 回傳一張意義不明的圖片。→ 當有最新的程式碼被推上 GitHub (指定的 branch),將程式碼整合與測試後丟到指定的 Server。 - 觸發條件:
當有人在我的 Issues 留 “lgtm”(小寫注意是小寫)。→ 當我把最新的程式碼推上 GitHub (指定的 branch)。
這樣就變成我們理想中的 CI/CD 了,更詳細的流程我們把它交給明天的自己吧!
Day 3 透過 GitHub Action 來實作簡易 CI/CD
CI/CD的簡單流程
在規劃 CI/CD 的流程之前,我們有兩個重要的角色 Runner 以及 Server 要了解:
- Runner:它負責將 Repository 更新來的程式碼進行整合與測試,再將測試完畢的程式碼傳送到指定 Server。
- Server:負責將 Runner 送過來的程式碼做上線服務,供人使用。
※有慧根的你肯定馬上就想起昨天學到的觸發 Workflows
沒錯 CI/CD 工具,正是建置在 Runner 之中,CI/CD 工具會去監測程式碼是否有新的程式碼被 Push,再執行你所編寫的一連串自動化指令,而這些指令通常會被寫成 yaml 檔。
有了之前的介紹,我們可以大致想像一下 CI/CD 的簡單流程,真的非常簡單.jpg
- 有人更新 Repository 的程式碼 😀
- 將 Repository 的程式碼丟到 Runner 做整合並測試 👀
- 部署到指定 Server 🦾
使用 GitHub Action 實作理想中的 CI/CD
練習 CI/CD 是其實是非常麻煩的,光是 Runner 以及 **Server,**你就必須準備 2 個平台,不管事虛擬機或者是實體主機,那怎麼辦?
還好我們有 Monosparta Code Camp!
Monosparta Code Camp 是一個由「創科資訊 Trunk Studio」與「Monospace 共同工作空間」共同推廣的「軟體工程師」培訓計畫,強調斯巴達式的實戰精神,提供「學習環境」、「訓練課程」與「專業指導」給予未來想成為優秀軟體開發者的有志夥伴,透過參與模擬真實專案開發的「協作團隊」,在 6~18 週的短期密集訓練過程中,讓你有機會和其他熱血學員一起精進,並獲得職場中累積多年經驗的技術專家親授指導。
好了我們回歸正題,之前就有說 GitHub 就有提供 Runner,那我們就懷著感恩的心使用它****!****
之前有說過我們撰寫 Workflows 的流程與方式
- 流程:當有最新的程式碼被推上 GitHub (指定的 branch),將程式碼整合與測試後丟到指定的 Server。
- 觸發條件:當我把最新的程式碼推上 GitHub (指定的 branch)。
開始設計 Workflows
這邊我們使用 React App、GitHub Action、GitHub Page 作為練習的工具
角色定位如下:
- React App :程式碼 (因為它 Test 幫我寫好了超方便)
- GitHub Action:CI/CD 工具
- GitHub 提供的 Runner:Runner🤔
- GitHub Page:Server
哇太讚了吧!免費白嫖 GitHub 所有功能
我設計的詳細 Workflows 預計如下
- 流程:當有最新的程式碼被推上 GitHub (指定的 branch),將程式碼 Pull 到 GitHub 提供的 Runner 整合與測試後,丟到 GitHub Page 做部署。
- 觸發條件:當我把最新的程式碼推上 GitHub (指定的 branch)。
事前作業1:將一個乾淨的 React App 並推上 GitHub (建 Repository)
不會的可以自己去搜尋如何建立 React App 喔
事前作業2:將 React App 部署上 GitHub Page (建 Server)
- 首先先在專案中安裝
gh-pages
套件
// 使用 npm 安装
npm install gh-pages
// 使用 yarn 安装🧶
yarn add gh-pages
- 修改
package.json
,添加homepage
※注意 homepage 的網址的 [github-username] 請替換成你的 Github 帳號(已打碼),[repository-name] 則是你的 repository 名稱(我的是CI-CD-React)
"name": "my-app",
"version": "0.1.0",
"private": true,
"homepage": "https://[github-username].github.io/[repository-name]",
- 修改
package.json
,在scripts
追加predeploy
以及deploy
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"predeploy": "npm run build", //yarn 把 npm 換掉即可
"deploy": "gh-pages -d build"
},
- 之後執行部署指令
// 使用 npm 部署
npm run deploy
// 使用 yarn 部署🧶
yarn run deploy
5.到 GitHub 看看是否部署成功,路徑 Settings → Pages
打造 yaml 檔
好了經過剛剛的事前步驟,我們已經準備好所有的條件了,那麼我們要怎麼製作 Workflows 把我們剛剛的規劃自動化呢
- 流程:當有最新的程式碼被推上 GitHub (指定的 branch),將程式碼 Pull 到 GitHub 提供的 Runner 整合與測試後,丟到 GitHub Page 做部署。
- 觸發條件:當我把最新的程式碼推上 GitHub (指定的 branch)。
將 yaml code 寫在 .github/workflows
中
name: React App Deploy
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: ci and test and build
run: |
npm ci
npm test
npm run build
- name: deploy
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: build
對就是這麼簡單…🥴,我們完成了以下幾點
- 今天只有 Push 到 main 分支才會觸發 Workflows。
- 透過 npm ci 安裝 React App 的相關套件,也供 npm test 做準備。
- npm test:之前有提到 CI ,也不只有軟體的整合也有測試,而此次實作是使用 react-scripts test來測試**。**
- npm run build:在 Runner 中先 build 好 React App(關於前端靜態檔的建置,不熟悉的人可以自己搜尋一下)。
- 將 build 好的 React App 透過 JamesIves/github-pages-deploy-action@v4 部署上 GitHub Page
來看看 Action 上面的 Workflows,CI/CD成功!
結語
這就是一個簡單的 CI/CD 的流程,當然 CI/CD 要難可以非常的難,比如我們之前 DevOps 提到的微服務(Microservice)的概念,要將所有獨立的服務都串起來 CI/CD,先後順序、使用的環境都不盡相同,需要下非常大的苦工😥
此文章也在這邊來到了尾聲,非常感謝的閱讀與觀看,也希望大家對於軟體的建置與部署有更進一步的認識。
如果還是有哪裡不熟悉,但還是有興趣的朋友,不妨考慮參加 Monosparta Code Camp!
Monosparta Code Camp 是一個由「創科資訊 Trunk Studio」與「Monospace 共同工作空間」共同推廣的「軟體工程師」培訓計畫,強調斯巴達式的實戰精神,提供「學習環境」、「訓練課程」與「專業指導」給予未來想成為優秀軟體開發者的有志夥伴,透過參與模擬真實專案開發的「協作團隊」,在 6~18 週的短期密集訓練過程中,讓你有機會和其他熱血學員一起精進,並獲得職場中累積多年經驗的技術專家親授指導。