簡介
軟體工程是一個步調快速且競爭激烈的領域。更快地向用戶推出您的產品將使您在競爭對手面前佔據優勢。值得慶幸的是,業界最佳實踐已經到位,可以幫助企業在公平的起跑線上競爭。
持續整合與持續開發 (CICD) 就是一個利用業界最佳實踐在競爭激烈的領域中為企業贏得優勢的策略範例。
GitHub 是一個基於 Web 的儲存庫,搭配版本控制工具 Git,允許軟體開發人員、工程師和架構師實現 CI/CD。持續開發 (CD) 是自動化建置、測試和部署的實踐。持續整合 (CI) 使許多人能夠在同一個專案上進行協作,並在無需擔心合併衝突的情況下檢查程式碼是否正常運作。
GitHub Actions 允許我們編寫自動化建置、測試和部署的步驟。
在本教學中,您將學習如何使用 GitHub Actions 設定持續整合。我們將首先設定一個 Git 儲存庫來託管我們的程式碼。然後,我們將設定一個 GitHub CI 流程來監控程式碼中的變更,啟動 CI 執行器 (runner) 來執行測試、建置並將我們的應用程式部署到執行 Nginx 的 Ubuntu 22.04 伺服器上。
先決條件
要跟隨本教學,您將需要以下內容:
-
一部執行 Ubuntu 22.04 的伺服器。您可以參考本教學來進行 初始 Ubuntu 伺服器設定, 新增非 root 用戶,以及 啟用 Ubuntu 的 UFW 防火牆.
-
您需要在伺服器上安裝 Node.js,建議版本為 14 或以上。我們有一篇關於 如何在 Ubuntu 上安裝 Node.js.
-
您需要安裝 Nginx 伺服器軟體。我們有一份指南關於 如何在執行 Ubuntu 的伺服器上安裝 Nginx.
-
您將需要 Docker 和 Docker Compose 安裝在您的本機電腦上,以執行隔離的開發環境。請跟隨我們的教學來學習 如何安裝和操作 Docker 於雲端。
現在我們已經準備好所需的一切,讓我們開始吧。
步驟 1. 複製專案儲存庫。
我們將以 Reactjs 為基礎,這是一個用於建置使用者介面的宣告式 Javascript 函式庫。如果您想從頭開始建立一個新專案,您可以使用這個 關於設定 React 應用程式的資源。為了簡潔起見,我們將使用此 React.js 儲存庫 的複製品,該儲存庫我們已在 GitHub 上設定好。
我們正在複製的應用程式是一個簡單的 React 應用程式,其中包含 react-router 6 以及使用 React Testing Library 進行的測試,它為我們提供了存取 DOM 的方法。
要複製儲存庫,請點擊綠色按鈕並複製 URL。

在您的工作區中開啟終端機,並執行以下命令來複製應用程式:
|
1 |
git clone git@github.com:EspiraMarvin/cicd-tut.git |
複製儲存庫後,導覽至專案目錄:
|
1 |
cd cicd-tut |
執行 docker-compose up 命令以建置並執行應用程式:
|
1 |
docker-compose up --build --force-recreate |
當流程完成時,請造訪 http://localhost:3000
您應該會看到類似這樣的畫面:

步驟 2. 了解 Node.js.yml 檔案。
在此步驟中,我們將定義 GitHub Yaml 檔案中的指令,以幫助我們了解發生了什麼事。在儲存庫中,有一個目錄 .github/workflows ,其中包含一個 node.js.yml 檔案,該檔案包含在您將變更推送至 GitHub 上的程式碼儲存庫後,GitHub 執行器 (runners) 所遵循的工作流程步驟。YAML 語法用於編寫 GitHub Actions 的工作流程。YAML 檔案的副檔名為 yaml 或 yml.
開啟 node.js.yml 檔案,它應該看起來像這樣:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
name: cicd-tut on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: # 該工作將在其上運行的執行器(runner)類型 runs-on: self-hosted strategy: matrix: node-version: [16.x] # 步驟代表將作為工作一部分執行的任務序列 steps: - name: 'checkout' uses: actions/checkout@v3 - name: 'setup node actions' uses: actions/setup-node@v3 with: node-version: "16" cache: 'npm' - run: npm i - run: npm test - run: npm run build # - run: cp -r ~/actions-runner/cicd-react/react-tut-test/react-tut-test/build /var/www/react-cicd |
在撰寫本教學時,我們使用的是 Node.js 16 的版本 16。現在,讓我們來了解 GitHub Actions 的工作流程:
-
name
name: cicd-tut
您的工作流程名稱,此名稱將顯示在您的存放庫 Actions 頁籤中。
-
on
|
1 2 3 4 5 |
on: push: branches: [ "main" ] pull_request: branches: [ "main" ] |
on 用於定義事件。事件可以自動觸發工作流程,或排程在稍後執行。事件可以是單個或多個,您還可以將工作流程的執行指定給特定的分支、標籤或檔案。這就像一個過濾器。
在我們的 YAML 檔案中,我們定義了多個自動事件,它們是:
-
當 push 事件在程式碼提交到存放庫時被觸發
-
當 pull_request 事件在主分支上建立拉取請求時被觸發。
我們指定了一個分支名稱 main ,以將工作流程的執行限制在該分支。我們還可以使用 ! 旗標後跟分支名稱來指定要忽略的分支。
-
jobs
工作流程本質上由一個或多個工作(jobs)組成。這些工作會從第一個到最後一個依序執行。
|
1 2 3 4 |
jobs: build: # 該工作將在其上運行的執行器(runner)類型 runs-on: self-hosted |
每個工作都在由 指定的執行器(runner)環境中執行runs-on。您可以選擇在由 表示的 GitHub 執行器上執行工作ubuntu-latest ,或是由 self-hosted 表示的自託管(self-hosted)執行器上執行。self-hosted。您的選擇將取決於您需要的工作數量。使用自託管執行器,您將擁有更多的靈活性和對資源的控制權。
在下一步中,我們將首先在 GitHub 執行器上執行我們的工作,稍後,我們將在我們自己的伺服器上設定 GitHub 自託管執行器。
-
strategy
策略(Strategy)讓我們可以在單個工作定義中使用變數,以根據變數的組合自動建立多個工作執行。
在我們的 YAML 檔案中,我們有一個用於 node-version 的變數,但如果我們為 Node 版本 18 新增另一個變數,如下所示: node-version: [16.x, 18.x],那麼矩陣(matrix)策略將為我們的 React 應用程式針對 Node 版本 16 和 18 建立 2 個工作執行。
|
1 2 3 |
strategy: matrix: node-version: [16.x] |
-
steps
步驟(Steps)是組成工作的一系列任務。步驟可以執行指令、設定任務、在您的公開存放庫中執行動作,或執行在 Docker 登錄中發佈的動作。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
steps: - name: 'checkout' uses: actions/checkout@v3 - name: 'setup node actions' uses: actions/setup-node@v3 with: node-version: "16" cache: 'npm' - run: npm i - run: npm test - run: npm run build |
步驟具有名稱。雖然它是選填的,但您可以使用它來指定一個簡單的方法來識別將在 GitHub 上顯示的步驟名稱。
在步驟中,您可以選擇要在工作(job)中執行的動作(action),動作是可重複使用的。定義動作時會指定動作的版本,這非常重要,因為它可以防止在動作擁有者發布更新時破壞您的工作流程。
在上述程式碼片段中, checkout@v3 是一個具有指定版本的動作範例 3。此動作會檢出您的存放庫,以便您的工作流程可以存取它。
某些動作(例如 actions/setup-node@v3 上方)具有使用 with 關鍵字表示的輸入,setup node 動作需要快取 Node 版本 16 和 npm。
-
run
此動作使用作業系統的 shell 執行命令列程式。
在上述 YAML 檔案中,我們有三個指令,它們都將在執行器環境中使用相同的 shell 執行。
-
第一個指令 npm i 會安裝我們 React 應用程式所需的所有相依性。
-
第二個 npm test,會執行我們編寫的測試。該測試預期文字 learn react 會被渲染在首頁上。
-
最後, npm run build 指令會建立一個包含我們應用程式生產版本的 build 目錄。稍後,我們將在我們的 Nginx 伺服器區塊.
步驟 3. 使用 GitHub Runner 測試 GitHub CI。
在此步驟中,我們將使用 GitHub runner 測試持續整合流程。首先打開 node.js.yml 檔案。將動作將在其上執行的執行器類型修改為 ubuntu-latest。這樣做的目的是在設定我們自己的自我裝載執行器之前,測試 GitHub 工作流程是否在 GitHub runner 上完美運作。
|
1 2 3 |
jobs: build: runs-on: ubuntu-latest |
在您的 GitHub 帳戶 建立一個新的存放庫。在我們繼續之前,請回到您的工作空間目錄並刪除 .git 目錄,如果您看不到它,請檢查您的隱藏檔案。您可以在終端機上使用以下指令來刪除該目錄:
|
1 |
rm -rf .git |
現在您可以 git add 您所有的專案檔案,提交並將它們推播到您的存放庫中。如果卡住了,請使用此指南關於 將您的專案資料夾連接到 GitHub 存放庫 (您在上方建立的)。
當您完成後,點擊您存放庫中的 Code 頁籤,您會在總提交次數旁邊看到一個橘色小點,點擊它時,您會看到一個類似下方的彈出視窗,表示您的工作流程已進入佇列:

現在點擊該視窗上的 Details 連結,或前往 Actions 頁籤,您將看到由 GitHub runner 執行的 node.js.yml 工作流程的每個步驟:

如果成功,點擊 Actions 頁籤,它應該看起來像這樣:

就是這樣,我們 Code 頁籤上的橘色小點現在應該變成綠色勾號。GitHub runner 已成功建置我們的應用程式。
現在,讓我們更進一步,將建置環境更改為在我們自己的 Ubuntu 伺服器基礎架構.
步驟 4. 設定 GitHub 工作流程以使用自我裝載執行器。
在我們於伺服器中安裝自我裝載執行器之前,讓我們回到工作空間,並編輯 node.js.yml 工作流程檔案,使其在 GitHub 自我裝載執行器上執行。
|
1 2 3 |
jobs: build: runs-on: self-hosted |
在此階段,當您提交變更時,由於尚未定義自我裝載執行器,該工作將會進入佇列。
在您的存放庫中,點擊
Settings 頁籤,在左側側邊欄中點擊
Actions,然後點擊
Runners:

點擊 New self-hosted runner,然後選擇 Linux 作為作業系統。
您將看到說明,向您展示如何下載執行器並將其安裝在您的伺服器上。
步驟 5. 在我們的伺服器上安裝並設定 GitHub 自我裝載執行器。
在此步驟中,我們將設定自託管的 GitHub runner。自託管 runner 是一個可以部署和管理 GitHub 網站上 GitHub Actions 工作執行的系統。與 GitHub 託管的 runner 相比,自託管 runner 的一個優勢是靈活性。它對作業系統、硬體和其他工具提供更多控制,可以進行自訂以滿足您所需的應用程式需求。
自託管 runner 可以新增在不同的層級,例如:
-
儲存庫層級的 runner,這些是專用於單一儲存庫的。
-
組織層級的 runner,這些可以處理組織中多個儲存庫的工作。
-
企業層級,可以分配給多個組織。
若要繼續,請透過 ssh 登入您的伺服器:
|
1 |
ssh username@server_ip |
使用以下指令切換到您的家目錄:
|
1 |
cd ~ |
然後,建立一個名為 action-runners 並進入該目錄:
|
1 |
mkdir actions-runner && cd actions-runner |
接下來,下載最新版本的 runner 套件:
|
1 |
curl -o actions-runner-linux-x64-2.298.2.tar.gz -L https://github.com/actions/runner/releases/download/v2.298.2/actions-runner-linux-x64-2.298.2.tar.gz |
然後使用以下指令解壓縮下載的套件:
|
1 |
tar xzf ./actions-runner-linux-x64-2.298.2.tar.gz |
回到您的儲存庫,在 Settings 索引標籤,在左側面板中按一下 Actions,然後 Runners,就像我們在 中所做的一樣步驟 4.
您將會看到列出的一個指令,其中包含將您的自託管 runner 連結到您的 GitHub 儲存庫的權杖。在您解壓縮 GitHub runner 程式碼的目錄中,使用列出的指令來連結您的 runner,例如:
|
1 |
./config.sh --url https://github.com/EspiraMarvin/react-tut-test --token XXXXXXXXXXXXXXXXXXXXXXXXXXX |
它應該會驗證成功:

按下 Enter 鍵以選擇預設的 runner 群組。
然後輸入您的 runner 名稱,例如 my-runner,然後按下 Enter 鍵。
按下 Enter 鍵以跳過新增額外標籤,您應該會看到如下方螢幕截圖所示的成功訊息:

輸入您的工作目錄名稱,例如 react-cicd,它應該會成功並顯示文字 settings saved.
最後,執行 ./run.sh,這應該會顯示 Connected to Github:

但這不會在背景執行,如果我們在終端機中輸入 ctrl+c,runner 將會停止,我們需要將其替換為 .svc.sh 服務,以讓 runner 作為服務持續執行,以便我們可以繼續與其互動。
使用 ctrl+c 停止 runner。您可以透過執行以下指令來安裝 .svc.sh 服務:
|
1 |
sudo ./svc.sh install |
安裝完成後,使用以下指令啟動服務:
|
1 |
sudo ./svc.sh start |
這應該會成功,並顯示 active (running).
若要確認 svc.sh 服務已啟動並正在執行,請執行以下指令:
|
1 |
sudo ./svc/sh status |

此時,任何可能已加入佇列等待自託管 runner 的工作流程都應該能成功執行。您也可以編輯檔案並進行測試。例如,修改 關於.tsx 檔案,提交並推送變更,自託管 runner 將會成功完成該工作。
步驟 6. 設定 Nginx 伺服器區塊
在此步驟中,我們將在 Nginx 中設定一個伺服器區塊,以檢視我們 React 應用程式的建置版本。我們有一篇關於 設定 Nginx 伺服器區塊 的教學,您可能會覺得有所幫助。
以下是本教學中使用的伺服器區塊範例:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
server { listen 80; listen [::]:80; server_name react.test; root /var/www/react-cicd/build; index index.html index.htm index.nginx-debian.html; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; charset utf-8; location / { try_files $uri $uri/ =404; } } |
您將在以下目錄中建立一個 Nginx 伺服器區塊(server block)設定檔: /etc/nginx/sites-available 目錄。
使用以下命令以 nano 編輯器開啟您網站的伺服器區塊設定檔:
|
1 |
sudo nano /etc/nginx/sites-available/react-cicd |
複製上面分享的伺服器區塊並根據您的目錄路徑進行修改,然後將其貼上到開啟的檔案中。編輯完成後,請按 ctrl+x 然後按 y 與 enter 以儲存並退出。
儲存後,為 react-cicd 伺服器區塊設定建立符號連結(symlink),從 /etc/nginx/sites-available 到 /etc/nginx/sites-enabled ,執行以下命令:
|
1 |
sudo ln -s /etc/nginx/sites-available/react-cicd /etc/nginx/sites-enabled/ |
為了讓變更生效,您需要重新啟動 Nginx。然而,在重新啟動 Nginx 服務之前,請先執行以下命令測試 Nginx 設定是否有效:
|
1 |
sudo nginx -t |
如果設定正確,測試應該會成功。
注意到伺服器區塊中 server_name 指令的值為 “ react.test ” 嗎?您需要將此值新增到您本機電腦的 hosts 檔案中。這將使您能夠在瀏覽器中開啟該應用程式。此步驟僅適用於本機開發環境中使用的虛擬網域。如果您有已註冊的網域連結到伺服器的公用 IP,那麼該網域應該已經可以在您的瀏覽器中存取。
在本機電腦上,使用以下命令開啟 hosts 檔案:
|
1 |
sudo nano /etc/hosts |
在 hosts 檔案中,新增您伺服器的 IP 位址,例如 127.0.0.1,後面加上您的虛擬網域名稱。
範例如下所示。然後關閉檔案並儲存:
|
1 |
192.168.3.123 react.test |
回到您伺服器上的 /var/www 目錄,建立一個新目錄,您可以執行以下命令將其命名為 react-cicd:
|
1 |
mkdir react-cicd |
在此階段,我們將取消註解 node.js.yml 檔案中的最後一個命令。
此命令會將我們 React 應用程式的建置資料夾,從我們在上一個 步驟 5.
中於 actions-runner 目錄內指定的工作資料夾複製,並將 public 資料夾放入 /var/www/react-cicd 目錄中。
伺服器區塊現在可以存取我們的應用程式並將其顯示在瀏覽器上。
最後,使用以下命令重新啟動 Nginx 服務:
|
1 |
sudo service nginx restart |
現在,您可以在 關於.tsx 檔案中進行變更,然後提交並推送變更至您的儲存庫。建置成功後,您將在 http://react.test 或您指定的網域名稱看到 React 應用程式的建置版本。請避免編輯 href 元素,位於 Home.tsx 檔案中,因為這可能會導致已撰寫的測試失敗。您儲存庫中的 Actions 頁籤也應該會顯示已完成的工作建置。

結論
使用 GitHub Actions 進行持續整合帶來了許多優勢,包括良好的開發者體驗、有助於持續測試、讓大型團隊中的協作更輕鬆、縮短開發時間、快速發布新功能、即時回饋和客戶滿意度,從而讓您在競爭對手中脫穎而出。為了在此知識基礎上更進一步,您可能還想了解 在 Ubuntu 上設定 GitLab 持續整合 (CI) 管線。以及使用 自行管理的 GitLab 實例 來託管您的 Docker 映像檔並執行私有建置。
祝您運算愉快!
留言
目前尚無留言。成為第一個留言的人吧。