2023/10/07
# GitHub Actions 實現自動化部署流程 (Deploy Workflow for GitHub Pages)
## 前言
承[上一篇文章](https://hackmd.io/@pericode/BkcNtoPl6)手動部署 GitHub Pages,專案在 GitHub 遠端儲存庫已有main、gh-pages兩個分支,其中 main 作為開發更新的主要分支,gh-pages作為遠端部署 github pages 的來源,那麼我在本地更新程式碼並遞交程式碼,然後執行推送到遠端部署分支的命令:`git subtree push --prefix dist origin gh-pages`,每次部署都要重複同樣的瑣碎命令和流程,能不能將這個部署流程自動化? 當然可以! 只要撰寫腳本就行了。
## 實現自動部署功能
建立自動部署腳本的常見方式包含在本地專案創建`deploy.sh`腳本文件,或是藉由建立以 YAML (`.yml`)文件編寫的 Workflow 來控制一連串 GitHub Actions 來達到目的。
以本次專案為例,這個自動部署的功能如下:
當本地專案更新`push`推送至 GitHub 遠端庫 main 分支時,利用Workflow自動觸發 GitHub Actions 建構及部署等等指令,來達成程式碼更新並自動部署 GitHub Pages 靜態網頁的目的。
## GitHub Actions
簡單來說,每個 Action 都是功能獨立的腳本,例如抓取程式碼、執行測試、登入遠端伺服器、設定指定 Node 環境...等,GitHub Actions 就是各種 Action 操作集合而成。
GitHub Actions 的 Workflow 是以 YAML 文件進行設定 (副檔名為`.yml`或`.yaml`)。
如果想更多了解關於 GitHub Actions ,推薦一篇不錯的文章: https://www.ruanyifeng.com/blog/2019/09/getting-started-with-github-actions.html
## 使用工具及前置作業
- 以下示範的專案是採用`vite`及`pnpm`作為開發工具,實際請依照自己使用的工具修改。
- 已建立好的 GitHub Repository 遠端庫
- 生成一個 GitHub 令牌: Personal access tokens
## Environments 設定

- DEPLOY_TOKEN 設置了GitHub令牌。
- VITE_API 設置Vite專案中使用到的API key。
## Workflow 工作流程
Workflow 的檔案名稱可以任意取,只要副檔名為`.yml`或`.yaml`都可,以我設置的`static.yml`為例,使用的套件管理工具為`pnpm`,以下是這次為自動部署 GitHub Pages 設置的 Workflow 內容,參考[Vite官方文件](https://vitejs.dev/guide/static-deploy.html#github-pages):
```
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ['main']
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow one concurrent deployment
concurrency:
group: 'pages'
cancel-in-progress: true
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install PNPM
run: npm i -g pnpm
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm build
env:
VITE_API: ${{ secrets.VITE_API }}
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
# Upload entire repository
path: './dist'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
```
以上需要注意的是:
- YAML 以換行符號與縮排方式進行語法區隔,多餘的空白或Tab是不被允許的,我是先在 VSCode 編輯器裡編輯修改,完成後和程式碼一起推送到遠端庫。
- 使用 pnpm 必須在安裝專案套件指令之前增加一個安裝 pnpm 的指令,否則部署會失敗。如果使用 npm 則不需要這個指令。
```
- name: Install PNPM
run: npm i -g pnpm
```
- 若本地專案中有使用環境變數設定(.env.local),在本地手動用 vite 打包生成 dist 目錄,推送至遠端並成功部署 Github Pages ([參考上一篇文章](https://hackmd.io/@pericode/BkcNtoPl6)), 這個過程中並不需要在 GitHub 設 Environment secrets,網頁可以正常運作,這是因為 vite 在`build`打包的過程中已經將環境變數包進去。
所以在規劃部署流程時,這個環境變數必須要在`build`時提供,否則網頁會無法正常顯示或執行。
```
- name: Build
run: pnpm build
env:
VITE_API: ${{ secrets.VITE_API }}
```
- 即使上述 Workflow 內容並未明確將 GITHUB_TOKEN 傳遞給 GitHub Actions,GitHub Actions 仍然可以通過`github.token`上下文訪問 GITHUB_TOKEN。我們只要設置權限即可:
```
permissions:
contents: read
pages: write
id-token: write
```
## 可能遇到的問題
### `git push` 失敗
console 報錯如下:
```
To https://github.com/periondev/vue-project.git
! [remote rejected] main -> main (refusing to allow an OAuth App to create or update workflow `.github/workflows/static.yml` without `workflow` scope)
error: failed to push some refs to 'https://github.com/periondev/vue-project.git'
```
**FIX**
- 首先檢查 github Token 勾選的權限設定,務必包含`workflow`,確認勾選後儲存,再次執行`git push`。
- 若 github Token 早已勾選`workflow`,那麼問題可能與本地登入驗證有關,命令列執行:
>gh auth login --scopes workflow
之後需回覆一連串設定,按照流程驗證並登入之後,再執行`git push`。
## 參考
- vite官方文件: https://cn.vitejs.dev/guide/static-deploy.html#github-pages
- GitHub Token: https://docs.github.com/en/actions/security-guides/automatic-token-authentication
- https://juejin.cn/post/7202127250643796024
- https://juejin.cn/post/7213548316981526586