Add support for "scripts-aliases" in composer.json (#11666)
parent
cc653161c3
commit
aefa46dfba
|
@ -441,3 +441,19 @@ The descriptions are used in `composer list` or `composer run -l` commands to
|
||||||
describe what the scripts do when the command is run.
|
describe what the scripts do when the command is run.
|
||||||
|
|
||||||
> **Note:** You can only set custom descriptions of custom commands.
|
> **Note:** You can only set custom descriptions of custom commands.
|
||||||
|
|
||||||
|
## Custom aliases.
|
||||||
|
|
||||||
|
You can set custom script aliases with the following in your `composer.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts-aliases": {
|
||||||
|
"phpstan": ["stan", "analyze"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The aliases provide alternate command names.
|
||||||
|
|
||||||
|
> **Note:** You can only set custom aliases of custom commands.
|
||||||
|
|
|
@ -694,6 +694,13 @@
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"scripts-aliases": {
|
||||||
|
"type": ["object"],
|
||||||
|
"description": "Aliases for custom commands.",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
|
|
@ -27,11 +27,23 @@ class ScriptAliasCommand extends BaseCommand
|
||||||
private $script;
|
private $script;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $description;
|
private $description;
|
||||||
|
/** @var string[] */
|
||||||
|
private $aliases;
|
||||||
|
|
||||||
public function __construct(string $script, ?string $description)
|
/**
|
||||||
|
* @param string[] $aliases
|
||||||
|
*/
|
||||||
|
public function __construct(string $script, ?string $description, array $aliases = [])
|
||||||
{
|
{
|
||||||
$this->script = $script;
|
$this->script = $script;
|
||||||
$this->description = $description ?? 'Runs the '.$script.' script as defined in composer.json';
|
$this->description = $description ?? 'Runs the '.$script.' script as defined in composer.json';
|
||||||
|
$this->aliases = $aliases;
|
||||||
|
|
||||||
|
foreach ($this->aliases as $alias) {
|
||||||
|
if (!is_string($alias)) {
|
||||||
|
throw new \InvalidArgumentException('"scripts-aliases" element array values should contain only strings');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->ignoreValidationErrors();
|
$this->ignoreValidationErrors();
|
||||||
|
|
||||||
|
@ -43,6 +55,7 @@ class ScriptAliasCommand extends BaseCommand
|
||||||
$this
|
$this
|
||||||
->setName($this->script)
|
->setName($this->script)
|
||||||
->setDescription($this->description)
|
->setDescription($this->description)
|
||||||
|
->setAliases($this->aliases)
|
||||||
->setDefinition([
|
->setDefinition([
|
||||||
new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
|
new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
|
||||||
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
|
new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
|
||||||
|
|
|
@ -249,7 +249,7 @@ class JsonConfigSource implements ConfigSourceInterface
|
||||||
$this->arrayUnshiftRef($args, $config);
|
$this->arrayUnshiftRef($args, $config);
|
||||||
$fallback(...$args);
|
$fallback(...$args);
|
||||||
// avoid ending up with arrays for keys that should be objects
|
// avoid ending up with arrays for keys that should be objects
|
||||||
foreach (['require', 'require-dev', 'conflict', 'provide', 'replace', 'suggest', 'config', 'autoload', 'autoload-dev', 'scripts', 'scripts-descriptions', 'support'] as $prop) {
|
foreach (['require', 'require-dev', 'conflict', 'provide', 'replace', 'suggest', 'config', 'autoload', 'autoload-dev', 'scripts', 'scripts-descriptions', 'scripts-aliases', 'support'] as $prop) {
|
||||||
if (isset($config[$prop]) && $config[$prop] === []) {
|
if (isset($config[$prop]) && $config[$prop] === []) {
|
||||||
$config[$prop] = new \stdClass;
|
$config[$prop] = new \stdClass;
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,7 +365,9 @@ class Application extends BaseApplication
|
||||||
$description = $composer['scripts-descriptions'][$script];
|
$description = $composer['scripts-descriptions'][$script];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->add(new Command\ScriptAliasCommand($script, $description));
|
$aliases = $composer['scripts-aliases'][$script] ?? [];
|
||||||
|
|
||||||
|
$this->add(new Command\ScriptAliasCommand($script, $description, $aliases));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,6 +196,17 @@ class ConfigValidator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// report scripts-aliases for non-existent scripts
|
||||||
|
$scriptAliases = $manifest['scripts-aliases'] ?? [];
|
||||||
|
foreach ($scriptAliases as $scriptName => $scriptAlias) {
|
||||||
|
if (!array_key_exists($scriptName, $scripts)) {
|
||||||
|
$warnings[] = sprintf(
|
||||||
|
'Aliases for non-existent script "%s" found in "scripts-aliases"',
|
||||||
|
$scriptName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check for empty psr-0/psr-4 namespace prefixes
|
// check for empty psr-0/psr-4 namespace prefixes
|
||||||
if (isset($manifest['autoload']['psr-0'][''])) {
|
if (isset($manifest['autoload']['psr-0'][''])) {
|
||||||
$warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
|
$warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
|
||||||
|
|
|
@ -109,6 +109,32 @@ class RunScriptCommandTest extends TestCase
|
||||||
$this->assertStringContainsString('Run the codestyle fixer', $output, 'The custom description for the fix-cs script should be printed');
|
$this->assertStringContainsString('Run the codestyle fixer', $output, 'The custom description for the fix-cs script should be printed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCanDefineAliases(): void
|
||||||
|
{
|
||||||
|
$expectedAliases = ['one', 'two', 'three'];
|
||||||
|
|
||||||
|
$this->initTempComposer([
|
||||||
|
'scripts' => [
|
||||||
|
'test' => '@php test',
|
||||||
|
],
|
||||||
|
'scripts-aliases' => [
|
||||||
|
'test' => $expectedAliases,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$appTester = $this->getApplicationTester();
|
||||||
|
$appTester->run(['command' => 'test', '--help' => true, '--format' => 'json']);
|
||||||
|
|
||||||
|
$appTester->assertCommandIsSuccessful();
|
||||||
|
|
||||||
|
$output = $appTester->getDisplay();
|
||||||
|
$array = json_decode($output, true);
|
||||||
|
$actualAliases = $array['usage'];
|
||||||
|
array_shift($actualAliases);
|
||||||
|
|
||||||
|
$this->assertSame($expectedAliases, $actualAliases, 'The custom aliases for the test command should be printed');
|
||||||
|
}
|
||||||
|
|
||||||
public function testExecutionOfCustomSymfonyCommand(): void
|
public function testExecutionOfCustomSymfonyCommand(): void
|
||||||
{
|
{
|
||||||
$this->initTempComposer([
|
$this->initTempComposer([
|
||||||
|
|
|
@ -46,6 +46,17 @@ class ConfigValidatorTest extends TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testConfigValidatorWarnsOnScriptAliasForNonexistentScript(): void
|
||||||
|
{
|
||||||
|
$configValidator = new ConfigValidator(new NullIO());
|
||||||
|
[, , $warnings] = $configValidator->validate(__DIR__ . '/Fixtures/composer_scripts-aliases.json');
|
||||||
|
|
||||||
|
$this->assertContains(
|
||||||
|
'Aliases for non-existent script "phpcsxxx" found in "scripts-aliases"',
|
||||||
|
$warnings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testConfigValidatorWarnsOnUnnecessaryProvideReplace(): void
|
public function testConfigValidatorWarnsOnUnnecessaryProvideReplace(): void
|
||||||
{
|
{
|
||||||
$configValidator = new ConfigValidator(new NullIO());
|
$configValidator = new ConfigValidator(new NullIO());
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"test": "phpunit",
|
||||||
|
"phpcs": "phpcs"
|
||||||
|
},
|
||||||
|
"scripts-aliases": {
|
||||||
|
"test": ["t"],
|
||||||
|
"phpcsxxx": ["x"]
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue