WordPress.orgプラグイン公開レビューで学んだこと
はじめに
WordPressプラグインを公開するにあたり、かなり時間をかけてPlugin Checkの指摘を一つずつ確認しました。
最初は多くの警告やエラーがありましたが、
- output escaping
- text domain
- prefix
- filesystem access
- prohibited functions
- internationalization
などを確認し、必要な修正を行いました。
一方で、単純に警告を消せばよいわけではない箇所については、なぜその実装が必要なのかを確認した上で、必要に応じて局所的なPHPCS suppressionを使用しました。
最終的にはGitHub Actions上で、実際に配布するZIPを展開してPlugin Checkを実行し、
Success: Checks complete. No errors found.
まで確認できました。
ここまで来れば、WordPress.orgへの公開準備としてはかなり良い状態だろう。
そう思って、プラグインを申請しました。
ところが、そこで終わりではありませんでした。
WordPress.orgのレビューでは、Plugin Checkとは違う観点からいくつかの指摘を受けました。
結果として、最初の公開候補だった 0.1.0 から 0.1.1 へ修正し、再提出することになりました。
今回はその過程を整理してみます。
1. Plugin Checkが見ているもの
Plugin Checkは非常に有用です。
例えば、
escaping
text domain
prefix
direct database access
filesystem access
prohibited functions
plugin metadata
など、WordPressプラグインとして問題になりやすい箇所を広く検査してくれます。
今回のプラグインでも、Plugin Checkによって多くの改善点を見つけることができました。
さらにGitHub Actionsへ組み込み、
GitHub checkout
↓
release build
↓
ZIP生成
↓
ZIP展開
↓
Plugin Check
という形にしました。
ここで重要なのは、GitHubのソースコード全体ではなく、
実際にWordPressへ配布するZIP
を検査していることです。
開発用の、
tests/
.github/
build-release.sh
などは配布物には含まれません。
そのため、最終成果物そのものに対してPlugin Checkを行う形にしました。
この状態でエラー0件になったので、
少なくとも静的チェックとしてはかなり整理された状態
にはなったと思います。
しかし、WordPress.orgの審査はそれだけではありませんでした。
2. 最初に出たのは「名前」の問題だった
最初に申請した名前は、
Secure S3 Storage
でした。
slugは、
secure-s3-storage
です。
自分としては、
- Secure
- S3
- Storage
なので、機能をそのまま表した分かりやすい名前だと思っていました。
ところがレビューでは、
- 名前がやや一般的である
- 他のプラグインとの区別が弱い可能性がある
-
S3が商標・プロジェクト名として扱われる可能性がある
という指摘がありました。WordPress.org側からは、より固有性のある名称へ変更することが提案されました。
そこで名称を、
Ozeki Database Backup for S3
へ変更しました。
これは結果的には良い変更だったと思います。
以前の名前よりも、
誰が作った、何をするプラグインなのか
が明確になりました。
Plugin Checkではコード上のtext domainやslugとの整合性は確認できます。
しかし、
この名前は他と十分区別できるか
商標上の誤解を生まないか
WordPress.org上の名前として適切か
という判断は、単純な静的解析とは別の話です。
ここで最初に、
Plugin Checkで0件でも公開要件をすべて満たしたことにはならない
ということを実感しました。
3. Retentionの「7、14、30」が機能制限と見なされた
もう一つ興味深かったのがRetentionです。
バックアップを何世代残すかについて、最初は管理画面で、
7
14
30
から選択するようにしていました。
これは単純に、
よく使いそうな値を選べるようにした方が分かりやすい
と考えたためです。
内部では、RetentionPolicyやS3BackupRetentionManagerは1以上の任意の保持数を扱えるようになっていました。
つまり、
内部実装
→ 1以上の任意の整数
UI
→ 7 / 14 / 30だけ
という状態でした。
WordPress.orgのレビューでは、この点が、
本来使える機能を意図的に制限しているように見える
として指摘されました。
レビューでは、WordPress.orgに登録するプラグインでは、内蔵機能をライセンスや制限によってロックすることが認められていないという説明とともに、Retentionが7、14、30に限定されている点が具体的に挙げられました。
もちろん、今回の7、14、30は有料版へ誘導するための制限ではありません。
単純にUI上の選択肢としてそうしていただけです。
しかし、
内部では任意の値を扱えるのに、UIだけで制限している
という構造だけを見ると、意図的な機能制限にも見えます。
そこで0.1.1では、
保持数
→ 任意の正の整数
を指定できるように変更しました。
この指摘はかなり面白いものでした。
コードとしては間違っていません。
セキュリティ上の問題でもありません。
しかし、
製品として利用者にどこまで機能を開放しているか
という観点では見直す余地があったわけです。
4. new mysqli() も改めて説明することになった
今回のプラグインでは、可能であれば、
mysqldump
mariadb-dump
を利用してデータベースdumpを作ります。
しかし、それらが利用できない場合や、proc_open()が無効な環境では、PHPだけでdumpを生成するfallbackも実装しています。
このPHP fallbackでは、
new mysqli(...)
によって別のDB接続を作っています。
WordPress.orgのレビューでは、この部分がUnsafe SQL callsとして取り上げられました。
普通のWordPressプラグインであれば、
直接mysqliを使う
↓
$wpdbを使うべき
という指摘は非常に妥当です。
ただし今回の場合は少し事情が違います。
PHP fallback dumperでは、WordPress本体が通常処理で使っている共有DB接続とは分離して、
専用DB connection
↓
consistent snapshot transaction
↓
database dump
という処理を行いたいからです。
つまり、
WordPressの通常クエリを実行したいからmysqliを使っている
のではありません。
バックアップ専用の独立したトランザクションを作るために別接続が必要
という設計です。
そのため0.1.1では、この意図がより明確に分かるよう説明を追加しました。
ここでも、
指摘された関数を機械的に別のものへ置き換える
のではなく、
なぜその関数を使っているのかを説明できる状態にする
ことが重要でした。
5. レビュー中に別のバグも見つかった
WordPress.orgから直接指摘されたものだけを直したわけではありません。
レビュー対応のためにコードをもう一度見直している中で、Daily Cronの登録処理にも問題を見つけました。
最初に設定を保存した場合に、Daily Cronが正しく登録されないケースがありました。
そこで0.1.1では、この点も修正しました。
最終的な0.1.1のChangelogは、
* Renamed the plugin to Ozeki Database Backup for S3.
* Removed the fixed 7, 14, or 30 backup retention choices;
any positive integer keep count is now supported.
* Clarified the separate database connection used by the PHP dump fallback.
* Fixed Daily Cron registration when settings are saved for the first time.
となりました。
レビューを受けることで、
指摘された箇所だけを見るのではなく、もう一度全体を確認する
きっかけにもなりました。
6. Plugin CheckとWordPress.orgレビューは役割が違う
今回一番大きく感じたのは、Plugin Checkと公開レビューを同じものとして考えてはいけないということです。
Plugin Checkは、
コード
構文
WordPress Coding Standards
API利用
security pattern
plugin metadata
などを検査する非常に強力な仕組みです。
一方でWordPress.orgのレビューでは、
名称
商標
機能制限
配布方針
外部サービス
コードの意図
利用者への説明
といった、もっと広い観点も見られます。
整理すると、
Plugin Check
↓
コードを中心とした機械的検査
GitHub Actions
↓
その検査を再現可能にする
WordPress.org review
↓
公開するソフトウェアとして妥当かを見る
という違いがあります。
どれか一つで十分、というものではないように思います。
7. 「警告をゼロにする」と「説明できるコード」は違う
前回Plugin Checkへ対応したときにも感じましたが、今回のレビューでさらに強く感じたことがあります。
それは、
ツールの警告をゼロにすることより、自分の実装を説明できることの方が重要
ということです。
例えば、
proc_open()
unlink()
fopen()
fwrite()
mysqli_report()
new mysqli()
などは、単純に見ると「WordPressらしくない」コードに見える部分があります。
しかし、
- なぜ使っているのか
- 他の方法では何が問題になるのか
- セキュリティ上のリスクをどう抑えているのか
- どこまでをWordPress APIへ任せるのか
を確認していくと、単純な置換では済まない場合があります。
逆に今回のRetentionのように、
技術的には動いているが、製品として見ると改善すべき
というものもあります。
つまり、
静的解析
↓
設計判断
↓
公開レビュー
の間を行ったり来たりしながら、最終的な形を決めることになります。
8. 最終的に公開された
0.1.1へ修正して再提出した後、最終的にWordPress.orgで公開されました。
現在は、
Ozeki Database Backup for S3
として公開されています。
ソースコードとrelease buildの仕組みはGitHubでも公開しています。
最初に考えていたより、WordPress.orgへの公開までには多くの確認事項がありました。
しかし、それによって、
自分の環境で動くプラグイン
から、
他の人へ配布することを前提としたプラグイン
へ一段進めることができたと思います。
まとめ
今回の経験を一言で整理すると、
Plugin Check 0件はゴールではなく、公開品質を確認する一つの工程だった
ということになります。
Plugin Checkによってコード上の多くの問題を見つけることができます。
GitHub Actionsに組み込めば、その状態を継続的に確認できます。
しかし、その先には、
- 名前は適切か
- 機能を不自然に制限していないか
- 実装の意図を説明できるか
- 公開するソフトウェアとして利用者に誤解を与えないか
という別の問いがあります。
今回、
Plugin Check
↓
GitHub Actions
↓
WordPress.org申請
↓
レビュー
↓
0.1.1へ修正
↓
公開
という一連の流れを経験したことで、
静的解析ツールを通すことと、公開できるソフトウェアを作ることは同じではない
ということを実感しました。
そしてこれは、WordPressプラグインに限らず、OSSを外へ出すときには共通する話なのかもしれません。