---
# System prepended metadata

title: GitHub Actions 實現自動化部署流程 (Deploy Workflow for GitHub Pages)
tags: [Deploy, npm/yarn/pnpm, github, Blog Post]

---

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 設定
![](https://hackmd.io/_uploads/rkHVcb9-p.png)
- 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