Add option to run bump after update (#11942)
* Add option to run bump after update * Convert the option into a bool | string parameter and change a couple of texts * Apply suggestions from code review * Fix tests --------- Co-authored-by: Jordi Boggiano <j.boggiano@seld.be>pull/12114/head
parent
17930441a1
commit
c8838f198e
|
@ -234,6 +234,7 @@ php composer.phar update vendor/package:2.0.1 vendor/package2:3.0.*
|
|||
changes to transitive dependencies. Can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var.
|
||||
* **--interactive:** Interactive interface with autocompletion to select the packages to update.
|
||||
* **--root-reqs:** Restricts the update to your first degree dependencies.
|
||||
* **--bump-after-update:** Runs `bump` after performing the update. Set to `dev` or `no-dev` to only bump those dependencies.
|
||||
|
||||
Specifying one of the words `mirrors`, `lock`, or `nothing` as an argument has the same effect as specifying the option `--lock`, for example `composer update mirrors` is exactly the same as `composer update --lock`.
|
||||
|
||||
|
|
|
@ -481,6 +481,12 @@ throw, but you can set this config option to `["example.org"]` to allow using sv
|
|||
URLs on that hostname. This is a better/safer alternative to disabling `secure-http`
|
||||
altogether.
|
||||
|
||||
## bump-after-update
|
||||
|
||||
Defaults to `false` and can be any of `true`, `false`, `"dev"` or `"no-dev"`. If
|
||||
set to true, Composer will run the `bump` command after running the `update` command.
|
||||
If set to `"dev"` or `"no-dev"` then only the corresponding dependencies will be bumped.
|
||||
|
||||
## allow-missing-requirements
|
||||
|
||||
Defaults to `false`. Ignores error during `install` if there are any missing
|
||||
|
|
|
@ -663,6 +663,10 @@
|
|||
"type": ["boolean", "string"],
|
||||
"description": "Defaults to \"php-only\" which checks only the PHP version. Setting to true will also check the presence of required PHP extensions. If set to false, Composer will not create and require a platform_check.php file as part of the autoloader bootstrap."
|
||||
},
|
||||
"bump-after-update": {
|
||||
"type": ["string", "boolean"],
|
||||
"description": "Defaults to false and can be any of true, false, \"dev\"` or \"no-dev\"`. If set to true, Composer will run the bump command after running the update command. If set to \"dev\" or \"no-dev\" then only the corresponding dependencies will be bumped."
|
||||
},
|
||||
"allow-missing-requirements": {
|
||||
"type": ["boolean"],
|
||||
"description": "Defaults to false. If set to true, Composer will allow install when lock file is not up to date with the latest changes in composer.json."
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
namespace Composer\Command;
|
||||
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Package\AliasPackage;
|
||||
use Composer\Package\BasePackage;
|
||||
use Composer\Package\Locker;
|
||||
|
@ -72,9 +73,28 @@ EOT
|
|||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
return $this->doBump(
|
||||
$this->getIO(),
|
||||
$input->getOption('dev-only'),
|
||||
$input->getOption('no-dev-only'),
|
||||
$input->getOption('dry-run'),
|
||||
$input->getArgument('packages')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $packagesFilter
|
||||
* @throws \Seld\JsonLint\ParsingException
|
||||
*/
|
||||
public function doBump(
|
||||
IOInterface $io,
|
||||
bool $devOnly,
|
||||
bool $noDevOnly,
|
||||
bool $dryRun,
|
||||
array $packagesFilter
|
||||
): int {
|
||||
/** @readonly */
|
||||
$composerJsonPath = Factory::getComposerFile();
|
||||
$io = $this->getIO();
|
||||
|
||||
if (!Filesystem::isReadable($composerJsonPath)) {
|
||||
$io->writeError('<error>'.$composerJsonPath.' is not readable.</error>');
|
||||
|
@ -112,7 +132,7 @@ EOT
|
|||
$repo = $composer->getRepositoryManager()->getLocalRepository();
|
||||
}
|
||||
|
||||
if ($composer->getPackage()->getType() !== 'project' && !$input->getOption('dev-only')) {
|
||||
if ($composer->getPackage()->getType() !== 'project' && !$devOnly) {
|
||||
$io->writeError('<warning>Warning: Bumping dependency constraints is not recommended for libraries as it will narrow down your dependencies and may cause problems for your users.</warning>');
|
||||
|
||||
$contents = $composerJson->read();
|
||||
|
@ -125,14 +145,13 @@ EOT
|
|||
|
||||
$bumper = new VersionBumper();
|
||||
$tasks = [];
|
||||
if (!$input->getOption('dev-only')) {
|
||||
if (!$devOnly) {
|
||||
$tasks['require'] = $composer->getPackage()->getRequires();
|
||||
}
|
||||
if (!$input->getOption('no-dev-only')) {
|
||||
if (!$noDevOnly) {
|
||||
$tasks['require-dev'] = $composer->getPackage()->getDevRequires();
|
||||
}
|
||||
|
||||
$packagesFilter = $input->getArgument('packages');
|
||||
if (count($packagesFilter) > 0) {
|
||||
$pattern = BasePackage::packageNamesToRegexp(array_unique(array_map('strtolower', $packagesFilter)));
|
||||
foreach ($tasks as $key => $reqs) {
|
||||
|
@ -171,8 +190,6 @@ EOT
|
|||
}
|
||||
}
|
||||
|
||||
$dryRun = $input->getOption('dry-run');
|
||||
|
||||
if (!$dryRun && !$this->updateFileCleanly($composerJson, $updates)) {
|
||||
$composerDefinition = $composerJson->read();
|
||||
foreach ($updates as $key => $packages) {
|
||||
|
|
|
@ -469,6 +469,18 @@ EOT
|
|||
'prepend-autoloader' => [$booleanValidator, $booleanNormalizer],
|
||||
'disable-tls' => [$booleanValidator, $booleanNormalizer],
|
||||
'secure-http' => [$booleanValidator, $booleanNormalizer],
|
||||
'bump-after-update' => [
|
||||
static function ($val): bool {
|
||||
return in_array($val, ['dev', 'no-dev', 'true', 'false', '1', '0'], true);
|
||||
},
|
||||
static function ($val) {
|
||||
if ('dev' === $val || 'no-dev' === $val) {
|
||||
return $val;
|
||||
}
|
||||
|
||||
return $val !== 'false' && (bool) $val;
|
||||
},
|
||||
],
|
||||
'cafile' => [
|
||||
static function ($val): bool {
|
||||
return file_exists($val) && Filesystem::isReadable($val);
|
||||
|
|
|
@ -85,6 +85,7 @@ class UpdateCommand extends BaseCommand
|
|||
new InputOption('minimal-changes', 'm', InputOption::VALUE_NONE, 'During a partial update with -w/-W, only perform absolutely necessary changes to transitive dependencies (can also be set via the COMPOSER_MINIMAL_CHANGES=1 env var).'),
|
||||
new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
|
||||
new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
|
||||
new InputOption('bump-after-update', null, InputOption::VALUE_OPTIONAL, 'Runs bump after performing the update.', false, ['dev', 'no-dev', 'all']),
|
||||
])
|
||||
->setHelp(
|
||||
<<<EOT
|
||||
|
@ -255,7 +256,28 @@ EOT
|
|||
$install->disablePlugins();
|
||||
}
|
||||
|
||||
return $install->run();
|
||||
$result = $install->run();
|
||||
|
||||
if ($result === 0) {
|
||||
$bumpAfterUpdate = $input->getOption('bump-after-update');
|
||||
if (false === $bumpAfterUpdate) {
|
||||
$bumpAfterUpdate = $composer->getConfig()->get('bump-after-update');
|
||||
}
|
||||
|
||||
if (false !== $bumpAfterUpdate) {
|
||||
$io->writeError('<info>Bumping dependencies</info>');
|
||||
$bumpCommand = new BumpCommand();
|
||||
$bumpCommand->setComposer($composer);
|
||||
$result = $bumpCommand->doBump(
|
||||
$io,
|
||||
$bumpAfterUpdate === 'dev',
|
||||
$bumpAfterUpdate === 'no-dev',
|
||||
$input->getOption('dry-run'),
|
||||
$input->getArgument('packages')
|
||||
);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,6 +84,7 @@ class Config
|
|||
'gitlab-token' => [],
|
||||
'http-basic' => [],
|
||||
'bearer' => [],
|
||||
'bump-after-update' => false,
|
||||
'allow-missing-requirements' => false,
|
||||
];
|
||||
|
||||
|
|
|
@ -24,10 +24,14 @@ class UpdateCommandTest extends TestCase
|
|||
* @param array<mixed> $composerJson
|
||||
* @param array<mixed> $command
|
||||
*/
|
||||
public function testUpdate(array $composerJson, array $command, string $expected): void
|
||||
public function testUpdate(array $composerJson, array $command, string $expected, bool $createLock = false): void
|
||||
{
|
||||
$this->initTempComposer($composerJson);
|
||||
|
||||
if ($createLock) {
|
||||
$this->createComposerLock();
|
||||
}
|
||||
|
||||
$appTester = $this->getApplicationTester();
|
||||
$appTester->run(array_merge(['command' => 'update', '--dry-run' => true, '--no-audit' => true], $command));
|
||||
|
||||
|
@ -126,6 +130,62 @@ The temporary constraint "^2" for "root/req" must be a subset of the constraint
|
|||
Run `composer require root/req` or `composer require root/req:^2` instead to replace the constraint
|
||||
OUTPUT
|
||||
];
|
||||
|
||||
yield 'update & bump' => [
|
||||
$rootDepAndTransitiveDep,
|
||||
['--bump-after-update' => true],
|
||||
<<<OUTPUT
|
||||
Loading composer repositories with package information
|
||||
Updating dependencies
|
||||
Lock file operations: 2 installs, 0 updates, 0 removals
|
||||
- Locking dep/pkg (1.0.2)
|
||||
- Locking root/req (1.0.0)
|
||||
Installing dependencies from lock file (including require-dev)
|
||||
Package operations: 2 installs, 0 updates, 0 removals
|
||||
- Installing dep/pkg (1.0.2)
|
||||
- Installing root/req (1.0.0)
|
||||
Bumping dependencies
|
||||
<warning>Warning: Bumping dependency constraints is not recommended for libraries as it will narrow down your dependencies and may cause problems for your users.</warning>
|
||||
<warning>If your package is not a library, you can explicitly specify the "type" by using "composer config type project".</warning>
|
||||
<warning>Alternatively you can use --dev-only to only bump dependencies within "require-dev".</warning>
|
||||
No requirements to update in ./composer.json.
|
||||
OUTPUT
|
||||
, true
|
||||
];
|
||||
|
||||
yield 'update & bump dev only' => [
|
||||
$rootDepAndTransitiveDep,
|
||||
['--bump-after-update' => 'dev'],
|
||||
<<<OUTPUT
|
||||
Loading composer repositories with package information
|
||||
Updating dependencies
|
||||
Lock file operations: 2 installs, 0 updates, 0 removals
|
||||
- Locking dep/pkg (1.0.2)
|
||||
- Locking root/req (1.0.0)
|
||||
Installing dependencies from lock file (including require-dev)
|
||||
Package operations: 2 installs, 0 updates, 0 removals
|
||||
- Installing dep/pkg (1.0.2)
|
||||
- Installing root/req (1.0.0)
|
||||
Bumping dependencies
|
||||
No requirements to update in ./composer.json.
|
||||
OUTPUT
|
||||
, true
|
||||
];
|
||||
|
||||
yield 'update & dump with failing update' => [
|
||||
$rootDepAndTransitiveDep,
|
||||
['--with' => ['dep/pkg:^2'], '--bump-after-update' => true],
|
||||
<<<OUTPUT
|
||||
Loading composer repositories with package information
|
||||
Updating dependencies
|
||||
Your requirements could not be resolved to an installable set of packages.
|
||||
|
||||
Problem 1
|
||||
- Root composer.json requires root/req 1.* -> satisfiable by root/req[1.0.0].
|
||||
- root/req 1.0.0 requires dep/pkg ^1 -> found dep/pkg[1.0.0, 1.0.1, 1.0.2] but it conflicts with your temporary update constraint (dep/pkg:^2).
|
||||
OUTPUT
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
public function testInteractiveModeThrowsIfNoPackageToUpdate(): void
|
||||
|
|
Loading…
Reference in New Issue