WordPress
Git

WordPress テーマを Git 管理して自動デプロイする

WordPress のテーマディレクトリを Git 管理するのは良いが、少し修正するたびにサーバで git pull コマンドを実行するのが面倒くさい。

GitHub などのリモートリポジトリに push したら、自動で git pull が実行されて反映されるようにしたい。

流れ

  1. リモートリポジトリに git push したら WordPress に Webhook が飛ぶ
  2. Webhook を受け取った WordPress はテーマディレクトリで git pull を実行する

簡単!(?)

もしかしたら何らかの WordPress プラグインで実現できるかもしれないけど、そのあたりは詳しくないのでわからない。

テーマディレクトリを Git で管理するようにしておく

前提として、テーマディレクトリ (/wp-contents/themes/<テーマ名>/) 以下を Git リポジトリとして管理し、何らかのホスティングサービス (GitHub など) をリモートリポジトリとして設定してあるものとする。

詳しい設定方法は割愛。

nginx ユーザで git pull できるようにする

今回 WordPress は Nginx + php-fpm で動いていたので、nginx ユーザで git pull できるようにしたい。もし Apache + mod_php で動いている場合は apache ユーザに置き換えて考えてもらえればいいと思う。

まず、リポジトリにアクセスするための秘密鍵ファイルを配置する。
場所はどこでも構わないが今回は /home/nginx/.ssh/ 以下に置いた。
パーミッションが適切でないと SSH コマンド実行時に怒られるので注意。

# ls -l /home/nginx/.ssh/
total 8
-rw------- 1 nginx www 1679 Apr  2 11:32 id_rsa
-rw-r--r-- 1 nginx www  407 Apr  2 11:32 id_rsa.pub

次に、環境変数 GIT_SSH を指定することで Git コマンドから SSH 接続する際の秘密鍵を指定する。
※ もしサーバにインストールされている Git のバージョンが 2.3 以上なのであれば、GIT_SSH_COMMAND が使えるのでそちらを使ったほうが便利ではある。

以下のスクリプトを (今回は) テーマディレクトリのルートに配置する。

git-ssh.sh
#!/bin/sh

ssh -i /home/${USER}/.ssh/id_rsa "$@"

環境変数 GIT_SSH にこのスクリプトのパスが指定されていた状態で git コマンドを利用した場合、このスクリプト経由で ssh コマンドが実行される。

試しに git pull してみる

$ sudo -u nginx GIT_SSH=git-ssh.sh git pull

WordPress のエンドポイントを追加する

functions.php などで wp_ajax_nopriv_XXX という名前のアクションを追加すると、 GET /wp-admin/admin-ajax.php?action=XXX というエンドポイントから指定した関数を実行することができる。

functions.php
/**
 * Add deploy hook endpoint
 */
add_action('wp_ajax_nopriv_update_theme', 'update_theme');
function update_theme() {
  $git_root = dirname(__FILE__);
  exec("cd ${git_root} && GIT_SSH=git-ssh.sh git pull 2>&1", $out);
  echo join("\n", $out);
}

今回は update_theme というアクションで git pull が実行されるようにした。

リモートリポジトリへの push 時に Webhook URL を叩く

GitHub / Bitbucket / GitLab などの Git ホスティングサービスでは、リポジトリへ push した際に指定した Webhook URL にリクエストを投げることができる。(設定方法はサービスごとに異なるので割愛)

これに先ほど作成したエンドポイントの URL を指定しておくと、リポジトリに push された際に WordPress サーバのテーマディレクトリで git pull が実行されるようになる。