iT邦幫忙

2025 iThome 鐵人賽

DAY 29
0
Modern Web

不只是登入畫面!一起打造現代化登入系統系列 第 29

CI/CD 實作 — React + Firebase(Preview → Staging → Production)

  • 分享至 

  • xImage
  •  
  1. 已安裝並設定 Firebase CLI(本地)
  2. 在 Firebase Console 建好 stagingproduction project(或使用相同專案的不同 hosting site)
  3. 在 GitHub repository 設定 Secrets:
    • FIREBASE_TOKEN(由 firebase login:ci 取得)
    • FIREBASE_PROJECT_ID_STAGING(staging 專案 id)
    • FIREBASE_PROJECT_ID_PROD(production 專案 id)

產生 FIREBASE_TOKEN:
firebase login:ci → 複製 token → GitHub repo > Settings > Secrets > New repository secret


package.json

{
  "scripts": {
    "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
    "test": "react-scripts test --ci --reporters=default",
    "build": "react-scripts build",
    "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,css,md}\"",
    "deploy:staging": "firebase deploy --only hosting --project $FIREBASE_PROJECT_ID_STAGING",
    "deploy:prod": "firebase deploy --only hosting --project $FIREBASE_PROJECT_ID_PROD"
  }
}

firebase.json

{
  "hosting": {
    "public": "build",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      { "source": "**", "destination": "/index.html" }
    ]
  }
}

.github/workflows/pr-preview.yml

name: PR Preview Deploy

on:
  pull_request:
    types: [opened, synchronize, reopened, closed]

jobs:
  preview:
    runs-on: ubuntu-latest
    if: github.event.pull_request != null
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 18

      - name: Install deps
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build

      - name: Deploy to preview channel
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
        run: |
          # preview channel name: pr-<number>
          CHANNEL="pr-${{ github.event.number }}"
          firebase hosting:channel:deploy $CHANNEL --project ${{ secrets.FIREBASE_PROJECT_ID_STAGING }} --expires 7d
      - name: Post preview URL comment
        if: ${{ github.event.action != 'closed' }}
        uses: marocchino/sticky-pull-request-comment@v2
        with:
          header: preview-url
          message: |
            Preview deployed: https://$CHANNEL--${{ secrets.FIREBASE_PROJECT_ID_STAGING }}.web.app

.github/workflows/staging.yml

name: Deploy to Staging

on:
  push:
    branches:
      - staging

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

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 18

      - name: Cache node modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build

      - name: Deploy to Staging (Firebase Hosting)
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
          FIREBASE_PROJECT_ID_STAGING: ${{ secrets.FIREBASE_PROJECT_ID_STAGING }}
        run: |
          firebase deploy --only hosting --project $FIREBASE_PROJECT_ID_STAGING

.github/workflows/production.yml

name: Deploy to Production

on:
  push:
    branches:
      - main

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

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 18

      - name: Cache node modules
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build

      - name: Deploy to Production
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
          FIREBASE_PROJECT_ID_PROD: ${{ secrets.FIREBASE_PROJECT_ID_PROD }}
        run: |
          firebase deploy --only hosting --project $FIREBASE_PROJECT_ID_PROD

上一篇
CI/CD 流程實作
系列文
不只是登入畫面!一起打造現代化登入系統29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言