CI

コミット時にWordPressコーディング規約に自動的に準拠させる方法

GitにはGitフックという仕組みがあります。
Git Documentation 8.3より

Gitのカスタマイズ ー Git フック
Gitにも特定のアクションが発生した時にカスタムスクリプトを叩く方法があります。

これを使って、WordPressのコーディング規約に準拠するようPHP/CSSをコミット時に自動修正します。
また、チェックにパスできない場合はコミットできないようにもなります。
コードのチェックにはPHP Code Snifferを使います。
さらに、Code Snifferが参照するWordPressのコーディング規約
WordPress-Coding-Standards
参考として、大元になるWordPressのコーディング規約集
WordPress コーディング規約 WordPress Codex 日本語版

PHP Code Snifferのインストールと設定

ローカルでPHPの実行環境が必要になりますので、インストールしておいて下さい。
WindowsでのPHP単体インストールは当サイトに記事があります。
参照:PHP7を単体でインストールする
Code Snifferをインストールします。
Composerでも行けるし、公式のGitHubにあるようにcurlwgetでダウンロードでもいいです。

ファイルを入れるだけで動かせます、binフォルダ内のphpcsを実行してバージョンを確認してみます。

$ phpcs/bin/phpcs --version

PHPCSの動作確認
別途、WordPress用のルールセットWordPress-Coding-Standardsをダウンロードしておきます。
今回はルールセットをwpcsフォルダにダウンロードしています。
このフォルダを下記コマンドでCode Snifferのinstalled_pathsに登録します。

$ phpcs/bin/phpcs --config-set installed_paths .\wpcs

コマンドラインで単体ファイルの修正とチェックを行ってみます。

$ phpcs/bin/phpcs --standard=wordpress front-page.php

PHPCSでコードをチェック
2箇所のエラーがありますね。

49行目
「次の関数はエスケープ処理を行うべきです(Codexの『データバリデーション』を参照)、’get_first_post_year’」
50行目
「関数呼び出しの閉じ括弧の後ろのスペースは禁止されています」
最後に
「マークされた1件の違反は、PHPCBFで自動修正が可能です」

50行目は自動修正が可能なようですので、CodeSnifferのphpcbfツールで修正します。

$ phpcs/bin/phpcbf --standard=wordpress front-page.php

PHPCBFにて自動修正
1カ所が修正されました。
もう一度、phpcsでチェックしてみます。
PHPCSで2回目のチェック
50行目のエラーが修正されたので、エスケープ処理がされていないエラーだけ残っています。
こちらは適切なエスケープ処理を書いてやる必要があります。
エラー処理前のコードは下図の通りです。50行目のhome_url()の直後だけ余計なスペースがあります。
また、get_first_post_year関数はfunctions.phpで定義している、年号を返す関数なのでエスケープ処理が必要です。
intvalにて整数型へキャストするようにWordPress Codexに記載があります。
PHPCSでエラーになる例

git hooksファイルの作成

先に試した修正とチェックをコミット前に行うよう、git hooksにスクリプトを書きます。
ローカルリポジトリの.git/hooks/にサンプルがあります。
中身はシェルスクリプトです。簡単に使い方など書いてあります。
githooksのフォルダ
ファイル名から.sampleを削除すると、該当するgitの処理が走る時に実行されます。
今回、pre-commitとして、このようなスクリプトを配置します。

#!/bin/sh
IS_ERROR=0
# コミットされるファイルのうち、.phpかcssで終わるもの
FILES=` git status --short | grep -E "^[M|A].*(.css|.php)$" | cut -c4-`
for FILE in $FILES
do
    ./phpcs/bin/phpcbf --standard=wordpress $FILE
    if ! ./phpcs/bin/phpcs --standard=wordpress $FILE ; then
        ./phpcs/bin/phpcs --standard=wordpress $FILE
        IS_ERROR=1
    else
        git add $FILE
    fi
done
exit $IS_ERROR

スクリプトの処理内容は、下記の通り。

  1. git addされたファイルから拡張子がphpかcssのファイル名を取り出す
    → FILES変数へ格納する
  2. 取り出したファイル一つずつに対し、自動修正をかける
    for FILES in $FILE do 内の処理
  3. さらに、そのファイルにCodeSnifferでチェックを行う
  4. エラーがなかったファイルは、git addでステージングし直す。
  5. エラーコードを返して終了

動作確認

git commitしてみます。
pre-commitフックはコミットメッセージを書くためのエディタが立ち上がる直前に実行されます。
githooksからPHPCSを走らせる
先ほどのように修正してチェックが実行されています。
エスケープ処理は自分で書かなくてはいけないので、エラーで終わっています。
この場合、エディタが起動しません。
SourceTreeからコミットしようとしてもこの通り。
SourceTreeからもgithooksは実行される
また、下記のように「手動で調査が必要」というアラートが出ることがあります。

Detected access of super global var $_POST, probably needs manual inspection.

手動での調査が必要なエラー
コードが規約に準拠していてもアラートが出て、エラーコード1となってしまうため、githooksでCodeSnifferが走る限りコミットできなくなります。
ルールセットの修正などで対応できるのだと思いますが、私は一度エラーメッセージを確認したらバイパスしてコミットしています。  githooksをバイパスする
gitコマンドではgit commit --no-verifyでバイパスできます。
さらにShirohanadaテーマはTravisCIでもCodeSnifferを実行するようにしています。
チェック後にテーマをビルドするので、規約違反のコードはデプロイされません。
(設定はローカルと違って、Warningは可としています)
TravisCIでのチェックログ

やってはいけないことは、できないようにしておく

例えば工場のプレス機など、プレスをするスイッチは両手で同時押しになっています。
手を挟まないように、両手が安全な位置になければ動作しない構造にしているわけです。
(それでも労働災害は、起きるときは起きる)
危険が伴う作業や現場、機械には、さまざまな安全装置があり原則があります。
有名なところでは「フェイル・セーフ」という原則があります。
例えば鉄道はブレーキの信号線が断線すると自動的に非常ブレーキがかかります。
安全に関わる原則の内「やってはいけないことは、できなくしておく」ことは「フール・プルーフ」という原則に含まれます。
私はデスクワークやコーディングも、このような原則を積極的に取り入れるべきだと思います。
今回紹介したように、コミット時とビルド時に自動修正をかけた上でチェックする仕組みを整えておけば、コーディング規約に準拠するコードだけがコミットされていきます。
こういった「安全確認」は本来やりたいこと、やるべきことに対する付随作業です。
また、コーディング規約の準拠は、手作業でやるには煩雑で、目視では間違えやすいところです。
たった一つの丸括弧の後ろの空白を、手作業で探すのは非現実的ではないでしょうか。
なので、機械に任せてしまう方が楽で確実です。

参考

gitのpre-commit hookを使って、綺麗なPHPファイルしかコミットできないようにする MANA-DOT
フェイルセーフとフールプルーフ~意味の違いと事例 レジリエントメディカル より安全な医療システムを実現する

WordPressのテーマを自動デプロイする

WordPressのテーマをGithubにPushするだけで、デプロイできるとのことで試してみた。
コードを書いてからの手間暇が凄く軽減され、予想以上に楽で快適。
5行ほどCSSを変更しただけでも、数クリックで10分以内に本番用WordPressに適用できる。

参考サイト
Github から WordPress のテーマを自動更新するとめちゃくちゃ快適だった。
toro_unit

今回は@Toro_Unitさんの記事の後半、自動デプロイを自サイトに設定した際の手順を紹介します。

自動デプロイに必要な環境

たった二つである。

  1. Githubリポジトリ
  2. WordPressプラグイン:WP-Pusher

Githubでは「Webhooks」という仕組みがあり、リポジトリに変更があった際に、指定のWebサイトへ通知を送ってくれる。
WordPress側でプラグインを入れておいて、その通知を受け取ってテーマを取得&更新する仕組み。
実際の処理としては、Githubが何のリポジトリにどういうコミットがあったか、json形式でPostを投げている。
テーマだけでなくプラグインなどにも使える模様。

WP-Pusherをインストール

WP-Pusherは基本的に、有料で提供されている。
「Pricing」や「Buy Now」が大きく表示されていると思う。
ただし、オープンソースかつ公開プロジェクトに限って無償使用が可能。
Pricingの下の方とかに

For open source code, in public repositories, WP Pusher is 100% free to use. Download it here.

とかあるので、その辺からメールアドレスを入力する画面へ飛ぶ。
そうすると、ダウンロード用アドレスを送ってくれる。
メール記載のアドレスからZipをダウンロードして展開、WordPressへアップロードしてインストール。
有効化したらWP Pusherがダッシュボードに出る。
wp-pusher01
WP-Pusher > Install themeへ移動してリポジトリとか入力する。この辺はTro_Unitさんの記事通り
有料ライセンスならプライベートリポジトリにも使えるのだろうけども、グレーアウトしている。
ちなみにPHP5.4.x以下だとPHPの文法エラーで有効化できなかった。現在PHP5.4系はEOLでサポート終了のため、レンタルサーバーで最新版に変更。さくらインターネットのレンタルサーバーなら「標準のPHP」でOKでしょう。というか、そんな便利システムがあるのに、何故かPHP5.3固定にしていた。

Theme was successfully installed. Go ahead and activate it.

完了したらWP-Pusher > Themesへ移動。
「テーマがインストール済み」とエラーが出たら、一旦該当テーマを削除してインストールするか、Dry runボックスにチェックを入れるんだと思う。(当方では未検証)

Githubの設定

wp-pusher02
WP-Pusher > Themes
ここのPush-to-Deploy:URLへGithubは通知を投げる。
トークンとかあれこれ含めてWP-Pusherが生成してくれている。
これをGithubの方へ登録する。
wp-pusher03
テーマを管理しているリポジトリの
Settings > Webhooks & services > add webhooks
Payload URLにPush-to-Deploy:URLを貼り付けて、保存。

URLはWordPressインストールディレクトリでなく、サイトのルートを指定。
 https://autumnsky.jp/?wppusher-hook&token=xxx
上記のようなURL形式とすること。

設定は以上である。
ここではまってしまったのだが、デフォルトではWordPressのインストールディレクトリを取得することがある。
当サイトではWordPress本体はwordpressディレクトリに配置しているため、

Push-to-Deploy:URL
https://autumnsky.jp/wordpress?wppusher-hook&wppusher-hook&token=xxxx

WP-PusherによるデフォルトがWordPressディレクトリとなり、そのまま貼り付けてもGithubでエラーとなっていた。

Push後の通知状況の確認

それでは、Pushしてみてください。Gitクライアントでは何も起きません。
なので、PushしたらGithubから状況を確認する。
Webhooksに登録したサイトURLが出ている。
他にも登録すればここに表示されるはず。
wp-pusher04
URLをクリックで設定と最新の通知状況が確認できる。
チェックマークはおそらく最新の1件の状況。
先の設定画面の下にRecent Deliveriesがある。
Githubから通知が成功していれば、緑のチェックマークがつく。
Recent Deliveriesの3件のうち、一番下が不成功
(先の宛先URL間違いの時のログ)
wp-pusher05
 
以上である。
私のテーマ作成はWockerというWordPress用仮想化環境をローカルで走らせながら、PHP/CSSを書いている(プリプロセッサはStylus、バージョン管理は当然Git)。従来の方法ではFTPでレンタルサーバーに接続してアップロードとなるが、これは面倒な上に間違えやすそうだ。
自動化しておくと、コードを書いた後が楽で確実なのでちょっとした更新もすぐに反映できる。また、レスポンシブレイアウトの確認も実機から本番用をすぐに見られる。
自動化最高かよ… な気分になれる、メリットしかない。