composer での require と require-dev キー
PHPで広く使われている依存性マネージャの composer には、昨今の他の言語で用いられているツール同様に、依存性を設定するキーとして
require
と require-dev
が存在します。
このキー欄にはそれぞれプロジェクトが依存する、PHPのバージョン・個々のPHP拡張・ベンダーパッケージとそのバージョン が指定できます。
普段PHPを利用する開発者のみなさんは、以下の通り依存性の追加コマンドを追加されてるかと思います。
composer require monolog/monolog # ロガーとしてmonologが必要
composer require --dev phpunit/phpunit # 開発時にテイスティングツールとしてPHPUnitが必要
require-dev
の特徴として、
composer install --no-dev
にてプロジェクトでのインストール時に対象外となる。
依存指定するパッケージの require 指定時に、そのパッケージ先の require-dev は対象外となる。
が挙げられます。
本番リリース時のデプロイケース
開発用パッケージについては、本番の実行環境については必要ありませんので、デプロイパイプラインでは本番のみ --no-dev
と指定しているプロジェクトも多いかと思います。
例えば、Google App Engine flex の実行Dockerイメージを作成する php-docker は、composer.jsonがプロジェクトルートに含まれていれば、指定されたPHP拡張のインストールも含め行ってくれますが、デフォルトでは、
'COMPOSER_FLAGS' => '--no-dev --prefer-dist',
と--no-dev
でのインストールになります。
require-dev が依存するパッケージの問題
この 本番と開発環境でインストールされるパッケージが異なる点について問題となるのが、dev指定のパッケージが依存するパッケージをプロダクションコードにて利用している場合です。
例えば、friendsofphp/php-cs-fixer
を利用している場合 symfony/process
がdev依存性でありますが、それに気づかず、Symfony\Component\Process\Process
クラスを用いる改修を行い、require
設定をsymfony/process
に行っていない場合にクラスが見つからずエラーとなってしまいます。
composer-require-checker による検出
昨年のPHPカンファレンス 2019 でも紹介しましたが、maglnet/composer-require-checker
を用いると、composer.jsonでrequire定義されていないシンボル(クラスやPHP拡張の関数) を検出することができます。
github.com
実行方法としては、インストール後プロジェクトのルートディレクトリにて、
composer-require-checker check composer.json
とすることで、以下のような出力を得ることができます。
ComposerRequireChecker 2.1.0@0c66698d487fcb5c66cf07108e2180c818fb2e72
The following unknown symbols were found:
+------------------------------------------------------------+--------------------+
| unknown symbol | guessed dependency |
+------------------------------------------------------------+--------------------+
| Aura\Router\Router | |
| Aura\SqlQuery\Common\InsertInterface | |
| Aura\SqlQuery\Common\SelectInterface | |
| Aura\Sql\ExtendedPdoInterface | |
| BEAR\AppMeta\AbstractAppMeta | |
| BEAR\AppMeta\AppMeta | |
| BEAR\AppMeta\Meta | |
| ctype_digit | ext-ctype |
| Doctrine\Common\Cache\Cache | |
それぞれのクラス名については、対応するパッケージを追加し、guessed dependency 欄にext-○○○ と記載されている場合はPHP拡張がrequireセクションに足りないので追加します。
CIでの検出
このcomposer-require-checker check
コマンドでのunknown symbolsがなにも検出されなかった場合と検出時のexitコードは分かれてますので、CIに組み込むができます。
弊社では GitHub Actionに composer-require-checker のセットアップを行いました。
GitHub Actions での設定例
最近では shivammathur/setup-php@v2 にて、7月21日リリースの2.4.0でtoolsにcomposer-require-checker
が追加されたのでそちらを使うと良いかと思います。
https://github.com/shivammathur/setup-php/releases/tag/2.4.0
設定例としては、.github/workflows/composer-require-checker.yml
に以下の設定を行います。
name : "Composer Require Checker"
on :
pull_request :
push :
branches :
- "master"
jobs :
composer-require-checker :
name : composer-require-checker check
runs-on : ubuntu-latest
steps :
- name : "Checkout"
uses : actions/checkout@v2
- name : "Install PHP"
uses : shivammathur/setup-php@v2
with :
tools : composer-require-checker
- name : "Get composer cache directory"
id : composercache
run : echo "::set-output name=dir::$(composer config cache-files-dir)"
- name : "Cache composer dependencies"
uses : actions/cache@v2
with :
path : ${{ steps.composercache.outputs.dir }}
key : ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys : ${{ runner.os }}-composer-
- name : "Install dependencies"
run : |
composer install --no-progress --no-scripts --no-dev
- name : "Run composer-require-checker check"
run : composer-require-checker check composer.json
余談ですが、 GitHub Actionsの場合は、
「Create Status badge」から以下のようなステータスバッジのマークダウンがコピーできますので、
![Composer Require Checker](https://github.com/{ベンダー}/{リポジトリ}/workflows/Composer%20Require%20Checker/badge.svg)
Github Actions composer require checker badge setting
README.md に追加して確認できるようにすると、ちょっとだけ安心感が増えるかも知れません。
composer-require-check-badge
利用/導入しての感想
composer-require-checkerの利用目的としては、上述に上げました--no-dev
な本番環境へのリリース事後防止が上げらえますが、それ以外にも
extの指定漏れがなくなるので、途中からの参画メンバには composer install
で必要な開発環境を確認してもらうことができる。
依存パッケージが大多数の場合での、個別のパッケージupdate作業にて依存の確認が分かりやすくなった。
という良かった点があります。
利用されてないパッケージの削除? ~ composer-unused
composer-require-checker の"逆"なツールとして、コードベースでは未使用なrequireパッケージを検出する composer-unused が存在します。
github.com
現状では class-string
なクラス名指定箇所に(Foo::class指定ではなく) 文字スカラー値そのままでの指定の場合にもunusedと検出されてしまうので、
現在、弊社のメインプロジェクトではCIには取り組めてないのですが、将来的にはこの点も解消した上で過不足無いパッケージにしていきたいです。