告別FTP手動上傳惡夢!資深工程師手把手搞定 WordPress CI/CD,從 GitHub Actions 到資料庫遷移全攻略

2025/09/15 | WP 開發技巧

告別FTP手動上傳惡夢!資深工程師手把手搞定 WordPress CI/CD,從 GitHub Actions 到資料庫遷移全攻略

哈囉,我是浪花科技的 Eric。身為一個每天在程式碼和伺服器之間打滾的工程師,我最怕聽到的就是:「Eric,我剛剛用 FTP 更新網站,結果整個白畫面了,救命啊!」這種半夜驚魂 call,相信是很多開發者或網站管理員的共同惡夢。

每次手動上傳,就是一次心跳加速的賭博。你賭你沒有傳錯檔案、沒有漏掉哪個檔案、沒有蓋掉不該蓋的設定。說實話,這種依賴人工操作的流程,既沒效率又充滿風險。這就是為什麼今天我想來好好聊聊 WordPress 的 CI/CD 自動部署,特別是利用 GitHub Actions 這個強大神器。這不只是為了耍帥或跟風,而是為了讓我們能睡個好覺,把時間花在真正有價值的開發上,而不是重複又危險的手動上傳。

很多人一聽到 CI/CD 就覺得那是大型軟體公司才玩的東西,跟 WordPress 這種「看似簡單」的 CMS 無關。錯!大錯特錯!一個專業的 WordPress 專案,更需要穩定、可預測的部署流程。今天,我不只會教你怎麼設定檔案自動同步,更會帶你深入探討在 WordPress CI/CD 流程中最常遇到的三大魔王:環境變數、資料庫遷移、以及使用者上傳內容。準備好了嗎?泡杯咖啡,我們來把你的部署流程從石器時代直接躍升到未來紀元!

為什麼你的 WordPress 專案需要 CI/CD?不只是「潮」,更是專業!

在我們深入技術細節前,先讓我這個老工程師囉嗦一下,為什麼你應該花時間來建立 CI/CD 流程。CI/CD 代表「持續整合 (Continuous Integration)」與「持續部署 (Continuous Deployment)」。簡單來說,就是把「測試、建置、部署」這一連串繁瑣的工作,交給自動化流程來處理。

當你將新的程式碼推送到 GitHub 儲存庫 (Repository) 時,CI/CD 流程就會自動被觸發,它會像一個不知疲倦的機器人,幫你完成所有後續工作。這帶來的好處是顯而易見的:

  • 錯誤掰掰,穩定至上:自動化流程消除了大部分人為疏失。再也不會發生「啊!我忘記上傳那個檔案了」或是「咦?我怎麼傳到正式站去了」的慘劇。每個部署步驟都被明確定義,確保了環境的一致性。
  • 版本控管,高枕無憂:每一次的部署都與 Git 的一個 commit (提交) 記錄緊密綁定。如果新版本出了問題,你可以輕易地「回滾」到上一個穩定的版本,而不是在伺服器上手忙腳亂地找舊檔案。
  • 專注開發,不做雜事:身為開發者,你的價值在於創造功能、解決問題,而不是當個檔案搬運工。把部署的髒活累活交給機器人,你就能專注於真正重要的開發任務。
  • 團隊協作,順暢無比:當團隊有多位開發者時,一個標準化的部署流程至關重要。大家遵循同一個流程,避免了「在我電腦上可以跑啊?」的經典甩鍋情境,讓協作更加順暢。

核心挑戰:超越檔案同步,搞定 WordPress CI/CD 的三大魔王

網路上很多 GitHub Actions 的教學,可能只教你如何用 SSH 和 rsync 把檔案同步到伺服器。這當然是第一步,但一個真正能在實戰中運作的 WordPress CI/CD 流程,需要解決的問題遠不止於此。以下這三大魔王,才是區分業餘和專業部署流程的關鍵:

1. 環境變數之亂 (`wp-config.php`)

你的本機開發環境、測試站 (Staging)、正式站 (Production) 的資料庫連線資訊、API 金鑰、安全金鑰肯定都不同。這些敏感資訊都放在 `wp-config.php` 裡。你絕對、絕對、絕對不能把包含這些密碼的 `wp-config.php` 直接 commit 到 Git 裡面!這等於是把家裡鑰匙掛在門口。那麼,該如何讓不同環境自動吃到正確的設定呢?

2. 資料庫遷移之痛 (Database Migrations)

WordPress 的許多功能都跟資料庫緊密相連。例如,你用 ACF (Advanced Custom Fields) 新增了幾個欄位,或是你的自訂外掛需要新增一個資料表。這些變動都存在資料庫裡。當你把程式碼部署上去後,資料庫結構也需要跟著更新,否則網站就會出錯。你總不希望每次部署完,還要手動登入後台去點擊「啟用外掛」或匯入 SQL 吧?這過程必須自動化。

3. 使用者上傳內容的兩難 (`uploads` 資料夾)

你的 `wp-content/uploads` 資料夾存放著所有使用者上傳的圖片和檔案。這個資料夾的內容會不斷在正式站上更新。在部署時,你不能用程式碼庫裡的 `uploads` 資料夾去覆蓋正式站的,否則客戶上傳的圖片就全沒了。但同時,你又需要確保部署流程不會動到這個資料夾。這該怎麼處理?

GitHub Actions 實戰:從零打造一個處理魔王的部署流水線

好了,理論說完了,我們來動手實作吧!假設你已經有一個 WordPress 專案的 Git 儲存庫在 GitHub 上了。

Step 1: 建立你的 GitHub Actions Workflow 檔案

首先,在你的專案根目錄下建立一個資料夾路徑:`.github/workflows/`。接著,在這個資料夾裡新增一個 YAML 檔案,例如 `deploy.yml`。這個檔案就是用來定義我們自動化流程的腳本。

這是一個基本的結構:

# .github/workflows/deploy.yml

name: Deploy to Production

on:
  push:
    branches:
      - main # 當 main 分支有新的 push 時觸發

jobs:
  deploy:
    runs-on: ubuntu-latest # 使用最新的 Ubuntu 虛擬機來執行

    steps:
    - name: Checkout code
      uses: actions/checkout@v3 # 第一步:把程式碼從 repo 拉下來

    # ... 後續的部署步驟會加在這裡 ...

Step 2: 設定 GitHub Secrets,保護你的敏感資料

我們需要讓 GitHub Actions 能夠登入你的伺服器,但又不能把密碼寫死在 `deploy.yml` 裡。這時就要用到 GitHub Secrets。

到你的 GitHub 專案頁面,點擊 `Settings` > `Secrets and variables` > `Actions`。在這裡,點擊 `New repository secret` 來新增以下幾個秘密變數:

  • `SSH_HOST`:你的伺-服器 IP 或網域名稱。
  • `SSH_USERNAME`:你用來登入伺服器的使用者名稱。
  • `SSH_KEY`:你的 SSH 私鑰。請把你的 `~/.ssh/id_rsa` 的內容完整複製貼上。
  • `REMOTE_PATH`:你 WordPress 網站的根目錄,例如 `/var/www/html`。

設定好之後,我們就能在 workflow 檔案中透過 `${{ secrets.VARIABLE_NAME }}` 來安全地使用它們。

Step 3: 處理 `wp-config.php` 的優雅解法

我們的策略是,Git 儲存庫裡只放一個 `wp-config-sample.php` 範本檔。正式的 `wp-config.php` 檔案應該存在於伺服器上,並且被伺服器的 Git 或我們的部署腳本忽略。

一個更進階且專業的做法,是讓 `wp-config.php` 動態讀取伺服器上的環境變數。這樣你的 `wp-config.php` 本身不含任何密碼,可以安全地放進 Git。例如:

<?php
// wp-config.php

define( 'DB_NAME', getenv('DB_NAME') );
define( 'DB_USER', getenv('DB_USER') );
define( 'DB_PASSWORD', getenv('DB_PASSWORD') );
define( 'DB_HOST', getenv('DB_HOST') );

// ... 其他設定

/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
	define( 'ABSPATH', __DIR__ . '/' );
}

/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';

這樣,你只需要在伺服器環境中設定好 `DB_NAME` 等環境變數即可,部署時完全不需要動到這個檔案。

Step 4: 用 WP-CLI 自動化資料庫遷移

WP-CLI 是 WordPress 的命令列工具,也是我們自動化資料庫的好朋友。我們可以在檔案部署完成後,透過 SSH 遠端執行 WP-CLI 指令。

例如,更新資料庫結構、啟用外掛、清除快取等。這一步會加在我們的 `deploy.yml` 裡:

# deploy.yml 的其中一個 step
- name: Run post-deployment commands
  uses: appleboy/ssh-action@master
  with:
    host: ${{ secrets.SSH_HOST }}
    username: ${{ secrets.SSH_USERNAME }}
    key: ${{ secrets.SSH_KEY }}
    script: |
      cd ${{ secrets.REMOTE_PATH }}
      wp plugin activate my-custom-plugin --quiet
      wp db upgrade --quiet
      wp cache flush --quiet

看到沒?只需要這幾行,部署後續的資料庫更新、快取清除就全部自動完成了!再也不用手動登入後台操作。

Step 5: 關於 `uploads` 資料夾的策略

最簡單也最有效的方法,就是在使用 `rsync` 同步檔案時,明確地排除 `uploads` 資料夾和 `wp-config.php` 檔案。

# deploy.yml 的檔案同步 step
- name: Deploy files to server
  uses: appleboy/ssh-action@master
  with:
    host: ${{ secrets.SSH_HOST }}
    username: ${{ secrets.SSH_USERNAME }}
    key: ${{ secrets.SSH_KEY }}
    script: |
      rsync -avz --delete --exclude 'wp-content/uploads/' --exclude 'wp-config.php' --exclude '.git/' ./ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:${{ secrets.REMOTE_PATH }}

這個指令會同步所有檔案,但會跳過 `wp-content/uploads/` 和 `wp-config.php`,完美解決了我們的問題。

完整的 Workflow 範例:把它們全部串起來!

結合以上所有概念,一個相對完整的 `deploy.yml` 看起來會是這樣:

# .github/workflows/deploy.yml

name: Deploy to Production

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v3

    # 如果你有前端建置流程 (例如 npm),可以加在這裡
    # - name: Build assets
    #   run: |
    #     npm install
    #     npm run build

    - name: Deploy files to server via rsync
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SSH_HOST }}
        username: ${{ secrets.SSH_USERNAME }}
        key: ${{ secrets.SSH_KEY }}
        script: |
          rsync -avz --delete \
          --exclude 'wp-content/uploads/' \
          --exclude 'wp-config.php' \
          --exclude '.git/' \
          --exclude '.github/' \
          ./ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:${{ secrets.REMOTE_PATH }}

    - name: Run post-deployment commands via SSH
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SSH_HOST }}
        username: ${{ secrets.SSH_USERNAME }}
        key: ${{ secrets.SSH_KEY }}
        script: |
          cd ${{ secrets.REMOTE_PATH }}
          echo "Running database upgrades..."
          wp db upgrade --quiet
          echo "Flushing cache..."
          wp cache flush --quiet
          echo "Deployment complete!"

工程師的小囉嗦:一些你可能沒想到的坑

設定完上面的流程,你已經打敗 90% 的人了。但身為資深工程師,總得提醒你幾個實務上常踩到的坑:

  • 檔案權限問題:部署上去的檔案,網頁伺服器 (Nginx / Apache) 可能沒有讀取權限,導致網站出錯。你可能需要在部署腳本的最後,加上 `chown` 和 `chmod` 指令來修正檔案擁有者與權限。這絕對是新手最常卡關的地方。
  • 快取!又是快取!:有時候程式碼明明更新了,網站看起來卻沒變。記得,除了 `wp cache flush` 清除 WordPress 的 Object Cache,你可能還需要清除 Varnish、Nginx FastCGI Cache,甚至是 Cloudflare 這類 CDN 的快取。
  • 資料庫向下相容:當你的程式碼需要修改資料庫結構時,盡量讓這個修改是「向下相容」的。意思是,即使資料庫更新了,舊版的程式碼跑起來也不會直接掛掉。這在你需要緊急回滾程式碼版本時,會救你一命。
  • 循序漸進,不要貪心:一開始不要想著打造一個超級完美的 CI/CD 流程。先從最基本的檔案同步開始,讓它能順利運作。然後再逐步加上資料庫遷移、快取清除、自動化測試等步驟。一口氣吃成胖子,只會讓你卡關卡到懷疑人生。

建立一套穩定可靠的 CI/CD 流程,是對專案、對客戶、也是對你自己負責的表現。它能將你從重複、高風險的手動部署中解放出來,讓我們回歸開發的本質:用程式碼創造價值。這趟自動化之旅絕對值得你投入時間。

延伸閱讀

如果你在設定過程中遇到困難,或是有更複雜的企業級部署需求,例如零停機部署 (Zero-Downtime Deployment)、藍綠部署 (Blue-Green Deployment) 等,浪花科技的團隊擁有豐富的實戰經驗。我們樂於協助你打造符合商業需求的現代化 WordPress 開發與維運流程。歡迎點擊這裡,填寫表單與我們聯繫,讓我們一起讓你的網站開發流程變得更專業、更有效率!

常見問題 (FAQ)

Q1: 到底什麼是 CI/CD?為什麼我的 WordPress 網站需要它?

CI/CD 分別是「持續整合」與「持續部署」。簡單來說,就是當你把程式碼推送到 Git (如 GitHub),就會觸發一套自動化流程,幫你完成測試、打包、並部署到伺服器上。你需要它的原因是為了「穩定」和「效率」。它能大幅減少因手動上傳檔案所產生的人為失誤,確保每次部署的品質一致,並讓你從重複性的工作中解放,專注於開發。

Q2: 我應該把 `wp-config.php` 檔案放到 Git 裡面一起控管嗎?

絕對不行!`wp-config.php` 包含你的資料庫帳號密碼、安全金鑰等極度敏感的資訊。一旦提交到 Git 儲存庫,就有外洩的風險,等於是把家裡鑰匙公開。正確的做法是,在 Git 中只保留一個範本檔 `wp-config-sample.php`,而正式的 `wp-config.php` 檔案只存在於伺服器上,並被部署腳本所忽略。

Q3: 這套 CI/CD 流程要如何處理 WordPress 核心或外掛的更新?

本文介紹的流程主要針對「佈景主題」或「自訂外掛」的開發與部署。對於 WordPress 核心或從官方商店安裝的外掛更新,建議的管理方式有兩種:1. 在本地或測試環境透過 Composer 管理依賴套件,更新後再透過 CI/CD 部署。 2. 直接在伺服器上透過 WP-CLI 指令 (`wp core update`, `wp plugin update –all`) 進行更新,並做好事前備份。不建議將整個 WordPress 核心和所有外掛都放進你的專案 Git 儲存庫,那會讓儲存庫變得非常臃腫。

Q4: 這看起來好複雜,有沒有更簡單的方法?

確實,從零開始建立一套完整的 CI/CD 流程需要一些學習曲線。市面上有一些高階的 WordPress 主機商(如 Kinsta, Cloudways)提供了內建的 Git 推送部署功能,會簡化許多步驟。然而,那些通常是比較基礎的檔案同步。如果你需要處理資料庫遷移、清除特定快取、或執行客製化腳本等進階需求,學習使用 GitHub Actions 這樣靈活的工具,將會賦予你最大的控制權與彈性,是走向資深開發者不可或缺的技能。

 
立即諮詢,索取免費1年網站保固