From 8c83457144c702a0b5080d6f255c8d9d65d637e5 Mon Sep 17 00:00:00 2001 From: David Zuelke Date: Wed, 23 Nov 2016 21:55:23 +0100 Subject: [PATCH] require runtime platform requirement in require if require-dev has one --- CHANGELOG.md | 4 ++++ bin/compile | 7 ++++--- bin/util/platform.php | 13 +++++++++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbcdf9fdb..51978d036 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - ext-blackfire/1.14.1 [David Zuelke] +### CHG + +- composer.json "require" or dependencies must now contain a runtime version requirement if "require-dev" or dependencies contain one [David Zuelke] + ## v114 (2016-11-10) ### ADD diff --git a/bin/compile b/bin/compile index 4510a6fbf..d03e1d493 100755 --- a/bin/compile +++ b/bin/compile @@ -126,9 +126,10 @@ echo "export PATH=\$HOME/.heroku/php/bin:\$PATH:\$HOME/$composer_bindir" > $buil status "Installing platform packages..." # extract requirements from composer.lock -/app/.heroku/php-min/bin/php $bp_dir/bin/util/platform.php "$bp_dir/support/installer/" $HEROKU_PHP_PLATFORM_REPOSITORIES 2>&1 >$build_dir/.heroku/php/composer.json | indent || error "Couldn't parse '$COMPOSER_LOCK'; it must be a valid lock -file generated by Composer. Run 'composer update', add/commit -the change, then push again." +/app/.heroku/php-min/bin/php $bp_dir/bin/util/platform.php "$bp_dir/support/installer/" $HEROKU_PHP_PLATFORM_REPOSITORIES 2>&1 >$build_dir/.heroku/php/composer.json | indent || error "Couldn't load '$COMPOSER_LOCK'; it must be a valid lock +file generated by Composer and be in a consistent state. +Check above for any parse errors and address them if necessary. +Run 'composer update', add/commit the change, then push again." # reset COMPOSER for the platform install step COMPOSER_bak="$COMPOSER" diff --git a/bin/util/platform.php b/bin/util/platform.php index d062e3d06..9d40558d8 100755 --- a/bin/util/platform.php +++ b/bin/util/platform.php @@ -48,6 +48,7 @@ function mkmetas($package, array &$metapaks, &$have_runtime_req = false) { if(!is_array($json)) exit(1); $have_runtime_req = false; +$have_dev_runtime_req = false; $require = []; $requireDev = []; if(file_exists($COMPOSER_LOCK)) { @@ -56,6 +57,7 @@ function mkmetas($package, array &$metapaks, &$have_runtime_req = false) { if(!$lock || !isset($lock["platform"], $lock["platform-dev"], $lock["packages"], $lock["packages-dev"])) exit(1); if(!isset($lock["content-hash"]) && !isset($lock["hash"])) exit(1); $have_runtime_req |= hasreq($lock["platform"]); + $have_dev_runtime_req |= hasreq($lock["platform-dev"]); // for each package that has platform requirements we build a meta-package that we then depend on // we cannot simply join all those requirements together with " " or "," because of the precedence of the "|" operator: requirements "5.*," and "^5.3.9|^7.0", which should lead to a PHP 5 install, would combine into "5.*,^5.3.9|^7.0" (there is no way to group requirements), and that would give PHP 7 $metapaks = []; @@ -95,7 +97,7 @@ function mkmetas($package, array &$metapaks, &$have_runtime_req = false) { } // collect platform requirements from dev packages in lock file foreach($lock["packages-dev"] as $package) { - if(mkmetas($package, $metapaks)) { + if(mkmetas($package, $metapaks, $have_dev_runtime_req)) { $requireDev[$package["name"]] = $package["version"]; } } @@ -105,7 +107,14 @@ function mkmetas($package, array &$metapaks, &$have_runtime_req = false) { } // if no PHP or HHVM is required anywhere, we need to add something -if(!$have_runtime_req) { // FIXME: this may break things if only root require-dev contains a PHP requirement that conflicts with the default +if(!$have_runtime_req) { + if($have_dev_runtime_req) { + // there is no requirement for a PHP or HHVM version in "require", nor in any dependencies therein, but there is one in "require-dev" + // that's problematic, because requirements in there may effectively result in a rule like "7.0.*", but we'd next write "^5.5.17" into our "require" to have a sane default, and that'd blow up in CI where dev dependenies are installed + // we can't compute a resulting version rule (that's the whole point of the custom installer that uses Composer's solver), so throwing an error is the best thing we can do here + file_put_contents("php://stderr", "ERROR: neither your $COMPOSER 'require' section nor any\ndependency therein requires a runtime version, but 'require-dev'\nor a dependency therein does. Heroku cannot automatically select\na default runtime version in this case.\nPlease add a version requirement for 'php' to section 'require'\nin $COMPOSER, 'composer update', commit, and deploy again."); + exit(3); + } file_put_contents("php://stderr", "NOTICE: No runtime required in $COMPOSER_LOCK; using PHP ". ($require["heroku-sys/php"] = "^5.5.17") . "\n"); } elseif(!isset($root["require"]["php"]) && !isset($root["require"]["hhvm"])) { file_put_contents("php://stderr", "NOTICE: No runtime required in $COMPOSER; requirements\nfrom dependencies in $COMPOSER_LOCK will be used for selection\n");