該死的自動構建

test_frontend

當我聽到專案要「自動化構建佈署」時,我想應該就是一場硬仗了。

試過以後,才發現是真的難。很多事情幾乎毫無頭緒,複製貼上、問LLM、找問答都沒有用。真的搞不懂自動構建的作法。

目標

先解釋一下我的環境:我是個純 SPA 的專案,使用 Vite 建立的 Vue 來開發,然後要在 Github Pages 上傳以 node js 構建好的程式,呈現在網路上。

其實也可以用 Cloudflare Pages, Netlify, Vercel 等,不過就先用 Github Pages 吧。

挫折

首先我先問了 GPT 怎麼做。他教我安裝 gh-pages 後,要在 package.jsonscripts 添加兩個指令:

{
  "scripts": {
    "predeploy": "npm run build",
    "deploy": "gh-pages -d build"
  }
}

接下來呢,又要我在 .github/workflows/deploy.yml 寫下類似這樣的檔案:

name: Deploy to GitHub Pages

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16'

      - name: Install dependencies
        run: npm install

      - name: Build the project
        run: npm run build

      - name: Deploy to GitHub Pages
        run: npm run deploy

程式當然毫不意外地失敗了

vite v5.4.8 building for production...
transforming...
✓ 63 modules transformed.
rendering chunks...
computing gzip size...
dist/index.html                 0.74 kB │ gzip:  0.47 kB
dist/assets/index-ChJyGF5y.js  99.54 kB │ gzip: 39.47 kB
✓ built in 868ms
ProcessError: fatal: could not read Username for 'https://github.com': No such device or address

    at ChildProcess.<anonymous> (/home/runner/work/test_frontend/test_frontend/node_modules/gh-pages/lib/git.js:42:16)
    at ChildProcess.emit (node:events:513:28)
    at maybeClose (node:internal/child_process:1100:16)
    at Process.ChildProcess._handle.onexit (node:internal/child_process:304:5)
Error: Process completed with exit code 1.

看了一下,似乎是是因為沒有用戶、專案、與密碼,所以自動佈署無法上傳,自然地就不成功。

那麼,給自動化佈署加了 SSH URL 應該就沒問題了吧:

name: Deploy to GitHub Pages

on:
  push:
    branches:
      - master

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    env:
      MY_EMAIL: iigmir@gmail.com
      MY_NAME: iigmir
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16'

      - name: Install dependencies
        run: npm install

      - name: Build the project
        run: npm run build

      - name: Deploy to GitHub Pages
        run: |
          git config --global user.email $MY_EMAIL
          git config --global user.name $MY_NAME
          git remote set-url origin https://$MY_NAME:${{ secrets.MY_PASSWORD }}@github.com/$MY_NAME/test_frontend.git
          npm run build
          gh-pages -d docs -u ${MY_NAME} <${MY_EMAIL}>

CI: 當然不是這樣。我怎麼會讓你稱心如意呢?

基本上,程式一直在 syntax error near unexpected token 'newline' 附近鬼打牆。查了 Github issue 後說什麼 remote 要 set-url 以便上傳,但一樣,怎麼做都是失敗。花了差不多三小時也沒有什麼結果。

一怒之下,就把自動構建程式全部砍掉、改用手動構建交差後去睡覺。

轉轉龜

醒來後吃個飯,然後去外面玩一下。結果想到,如果原本的專案做不了,那自己先用 Vite 作個專案試試如何?

想到了後我就搜尋 Vite Github Pages 看看,發現 Vite 官方網站居然有完整指引、整個文件還能複製貼上:

# 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 the GITHUB_TOKEN permissions 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@v4
      - name: Set up Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - name: Install dependencies
        run: npm ci
      - name: Build
        run: npm run build
      - name: Setup Pages
        uses: actions/configure-pages@v4
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          # Upload dist folder
          path: './dist'
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

裡面還說能這個程式要在 Github Action 用、而且要設定 vite.config.js 裡面的 base 路徑以便構建。我決定回家後試試看。

回家後發現,在 Github Action 裡要手動創建構建文件的話,它會建立在 .github/workflows/main.yml 那邊。

然後叮咚,居然可以動!我真的很驚訝!

回轉

好,居然成功了,那我回去弄專案如何。

我重新修改裡面的 base 路徑與 Github Pages 設定後,把 .github/workflows/main.yml 的主要推送的 branches['main'] 改為 ['master'] 後,試試看程式如何。

# 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: ['master']

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# Sets the GITHUB_TOKEN permissions 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@v4
      - name: Set up Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - name: Install dependencies
        run: npm ci
      - name: Build
        run: npm run build
      - name: Setup Pages
        uses: actions/configure-pages@v4
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          # Upload dist folder
          path: './dist'
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

也可以。居然能自動構建了。

自動化啊,我真是搞不懂你。

總結

Vite 在 Github Pages 上不要用 gh-pages 構建。那是在自討苦吃;相反地,你應該用 Vite 官方提供的程式。修改方面苦痛就比較小。

但我想我應該那種學不會教訓的人吧。

參考資料