2026年8月4日
2026年8月4日
WP-CLIとGitHub ActionsでWordPressのCI/CDパイプラインを構築する方法
WordPress の CI/CD は、GitHub Actions で「コードチェック → サーバーへ転送 → WP-CLI で後処理」という流れを組むと、手作業の FTP アップロードをなくし、毎回同じ手順でデプロイできるようになります。この記事では、テーマやプラグインのリポジトリを例に、チェック用のジョブ、SSH と rsync によるデプロイ、WP-CLI のエイリアスを使ったリモート操作、デプロイ後の処理と切り戻しの考え方までを説明します。
パイプラインの全体像
ここで作るパイプラインは次の2段構成です。
- CI(チェック):プルリクエストと main ブランチへのプッシュのたびに、Composer の依存関係を入れて PHP_CodeSniffer(必要なら PHPUnit)を実行する
- CD(デプロイ):main へのプッシュでチェックが通ったときだけ、本番サーバーへ SSH で接続し、データベースのバックアップ、ファイル転送、WP-CLI による後処理を行う
リポジトリに含めるのは、自分たちが開発するテーマやプラグインのコードだけにするのが扱いやすい構成です。WordPress 本体、wp-config.php、wp-content/uploads はサーバー側で管理し、パイプラインからは触りません。wp-config.php にはデータベースのパスワードなどが含まれるため、リポジトリに入れないことが大前提です。
事前準備
デプロイ用の SSH 鍵とユーザー
CI から接続するための専用の SSH 鍵ペアを作り、公開鍵を本番サーバーのデプロイ用ユーザーに登録します。個人の鍵を流用すると、退職や鍵の更新のたびにパイプラインが止まり、漏えい時の影響範囲も大きくなります。デプロイ用ユーザーには、公開ディレクトリへの書き込みと wp の実行に必要な権限だけを与えます。
GitHub のシークレットに登録する
秘密鍵や接続先は、リポジトリの設定画面にある Actions 用のシークレットに登録します。この記事の例では次の名前を使います。
DEPLOY_SSH_KEY:デプロイ用の秘密鍵DEPLOY_KNOWN_HOSTS:接続先サーバーのホスト鍵(手元でssh-keyscan example.comを実行し、フィンガープリントを確認してから登録)DEPLOY_USER、DEPLOY_HOST:接続ユーザー名とホスト名
本番用のシークレットは、GitHub の environment(環境)に紐づけて登録すると、承認者の設定やブランチの制限をかけられます。画面の項目名は変わることがあるため、GitHub のドキュメントで確認してください(2026年10月現在)。
コーディング規約の設定
チェック用に、composer require --dev wp-coding-standards/wpcs で WordPress Coding Standards を入れ、リポジトリ直下に phpcs.xml.dist を置いて対象ディレクトリを決めておきます。こうしておくと、CI でも手元でも vendor/bin/phpcs だけで同じチェックが走ります。
GitHub Actions のワークフロー
.github/workflows/deploy.yml として次のファイルを置きます。テーマ my-theme のリポジトリを /var/www/example.com の WordPress へ配置する例です。
name: CI/CD
on:
pull_request:
push:
branches: [main]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer
coverage: none
- run: composer validate --strict
- run: composer install --no-interaction --prefer-dist --no-progress
- run: vendor/bin/phpcs
deploy:
needs: check
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
concurrency:
group: deploy-production
cancel-in-progress: false
env:
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
WP_PATH: /var/www/example.com
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer
coverage: none
- name: 本番用の依存関係を入れる
run: composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
- name: SSH の準備
env:
SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
KNOWN_HOSTS: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
run: |
mkdir -p ~/.ssh
printf '%s\n' "$SSH_KEY" > ~/.ssh/id_deploy
chmod 600 ~/.ssh/id_deploy
printf '%s\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts
- name: データベースをバックアップ
run: |
ssh -i ~/.ssh/id_deploy "$DEPLOY_USER@$DEPLOY_HOST" \
"mkdir -p ~/backups && wp db export ~/backups/pre-deploy-${GITHUB_SHA}.sql --path=$WP_PATH"
- name: テーマを転送
run: |
rsync -az --delete \
--exclude='.git' --exclude='.github' --exclude='node_modules' --exclude='tests' \
-e "ssh -i ~/.ssh/id_deploy" \
./ "$DEPLOY_USER@$DEPLOY_HOST:$WP_PATH/wp-content/themes/my-theme/"
- name: WP-CLI で後処理
run: |
ssh -i ~/.ssh/id_deploy "$DEPLOY_USER@$DEPLOY_HOST" \
"wp core update-db --path=$WP_PATH && wp cache flush --path=$WP_PATH"
- name: 動作確認
run: curl -fsS -o /dev/null https://example.com/
アクションのメジャーバージョン(@v4、@v2)は、各リポジトリで最新の推奨を確認してから使ってください。
設定のポイント
- **シークレットは
env経由で渡す**:runの中に${{ secrets.… }}を直接埋め込むより、環境変数として渡すほうが、シェルの解釈による事故を避けやすくなります。GitHub はログ上のシークレットの値を伏せ字にしますが、echoで出力するような書き方は避けます。 - **
--deleteの範囲に注意**:rsync の--deleteは、転送元にないファイルを転送先から消します。転送先をテーマのディレクトリに限定しているのはこのためです。WordPress のルートに向けて--deleteを付けると、uploads や wp-config.php が消える恐れがあります。最初は--dry-runを付けて実行し、消える対象を確認してください。 - **
concurrencyで同時デプロイを防ぐ**:続けてプッシュしたときにデプロイが並行して走ると、ファイルが混ざった状態になりえます。同じグループのジョブを順番に実行させます。 - ホスト鍵を検証する:
StrictHostKeyChecking=noでホスト鍵の確認を省く例を見かけますが、接続先のなりすましに気づけなくなります。known_hosts を登録して検証させます。
テストを追加したい場合、プラグインであれば wp scaffold plugin-tests でテスト用の雛形を作り、check ジョブに PHPUnit の実行を足す方法があります。テスト用のデータベースが必要になるため、最初は規約チェックだけで始め、慣れてから広げるのが現実的です。
WP-CLI のエイリアスでリモートを操作する
デプロイ後の確認や手動の運用作業では、WP-CLI のエイリアスを使うと ssh を毎回組み立てずに済みます。プロジェクト直下の wp-cli.yml に接続先を書きます。
# wp-cli.yml
@staging:
ssh: deploy@staging.example.com/var/www/staging.example.com
@production:
ssh: deploy@example.com/var/www/example.com
wp cli alias list
wp @staging plugin list --update=available
wp @production core version
エイリアスは手元の ssh コマンドを使って接続し、接続先の wp を実行します。そのため、接続先に WP-CLI がインストールされていること、手元の ~/.ssh/config や SSH エージェントで鍵が使える状態になっていることが前提です。CI で使う場合は、ランナーに WP-CLI を入れたうえで同じ設定を置けば、ワークフローの ssh ... "wp ..." を wp @production ... に置き換えられます。
@production を付けたコマンドは本番に直接作用します。wp search-replace などデータを書き換えるコマンドは、まず @staging で試し、本番では --dry-run で件数を確認してから実行してください。
デプロイ後に実行する WP-CLI コマンド
後処理は「毎回実行してよいもの」と「必要なときだけ実行するもの」に分けて考えます。
wp core update-db:WordPress 本体のデータベース更新を適用します。更新が不要なら何もしないので、毎回実行して問題ありません。マルチサイトでは--networkを付けます。wp cache flush:オブジェクトキャッシュを消します。ページキャッシュ系プラグインのキャッシュは別管理のことが多いため、各プラグインの WP-CLI コマンドや設定を確認します。wp rewrite flush:カスタム投稿タイプやリライトルールを変更したときだけ実行します。毎回実行する必要はありません。
プラグインが独自にデータベースを更新する仕組みを持っている場合、その実行方法はプラグインごとに異なります。各プラグインのドキュメントを確認し、必要ならワークフローに追加します。
切り戻し(ロールバック)の考え方
デプロイで不具合が出たときに戻せる手段を、パイプラインを作る段階で決めておきます。
- コードを戻す:問題のコミットを
git revertして main にプッシュすれば、同じパイプラインで前の状態が配置されます。手順が普段のデプロイと同じなので、慌てているときでも間違えにくい方法です。 - データベースを戻す:デプロイ前に書き出した
pre-deploy-<コミットID>.sqlをwp db importで戻せます。ただし、バックアップ以降に入った注文やコメントも消えるため、最後の手段と考えてください。 - より短時間で戻したい場合:リリースごとにディレクトリを分け、シンボリックリンクを切り替える方式にすると、前のリリースへ数秒で戻せます。Deployer のようなデプロイツールがこの方式を提供しています。
本番に適用する前に、ステージング環境向けに同じワークフローを用意し、デプロイと切り戻しの両方を一度試しておくと、いざというときに慌てずに済みます。
まとめ
- CI は PR とプッシュごとに
composer installとphpcsを実行し、CD は main でチェックが通ったときだけ動かす - 秘密鍵や接続先は GitHub のシークレット(本番は environment)に登録し、
env経由で渡す。wp-config.php はリポジトリに入れない - rsync の
--deleteは転送先をテーマ・プラグインのディレクトリに限定し、最初は--dry-runで確認する - デプロイ前に
wp db export、デプロイ後にwp core update-dbとwp cache flush。wp rewrite flushは必要なときだけ wp-cli.ymlのエイリアス(@staging、@production)でリモート操作を簡単にし、切り戻し手順も事前に試しておく