2.2 in December stops running Composer plugins that have not been explicitly permitted, and a non-interactive install refuses rather than prompting.
{
"config": {
"allow-plugins": {
"composer/installers": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"php-http/discovery": false
}
}
}
# in CI, without this block:
# composer install --no-interaction
# → the plugin does not run, and nothing says why
# until the thing it would have done is missing
A Composer plugin runs arbitrary code during install, which is the highest-privilege moment in a build, so requiring it to be named is straightforwardly correct. The migration is unpleasant because the failure is silent in a non-interactive context: an installer plugin that places WordPress into a directory simply does not, and the resulting error is about a missing file. Adding the block before upgrading to 2.2, rather than after, avoids the whole episode.