Skip to content

Commit 9fa3d1b

Browse files
committed
Adds support for GrumPHP and updates script installation commands in composer.json
1 parent 21beddd commit 9fa3d1b

11 files changed

Lines changed: 103 additions & 114 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.idea/
2+
.vscode/
23
public/
34
tmp/
45
vendor/

composer.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"friendsofphp/php-cs-fixer": "^3.94",
3535
"phpdocumentor/shim": "^3.9",
3636
"phpowermove/docblock": "^4.0",
37+
"phpro/grumphp": "^2.19",
3738
"phpspec/prophecy-phpunit": "^2.5",
3839
"phpunit/phpunit": "^12.5",
3940
"rector/rector": "^2.3",
@@ -56,7 +57,8 @@
5657
"config": {
5758
"allow-plugins": {
5859
"ergebnis/composer-normalize": true,
59-
"phpdocumentor/shim": true
60+
"phpdocumentor/shim": true,
61+
"phpro/grumphp": true
6062
},
6163
"platform": {
6264
"php": "8.3.0"
@@ -67,7 +69,10 @@
6769
"branch-alias": {
6870
"dev-main": "1.x-dev"
6971
},
70-
"class": "FastForward\\DevTools\\Composer\\Plugin"
72+
"class": "FastForward\\DevTools\\Composer\\Plugin",
73+
"grumphp": {
74+
"config-default-path": "grumphp.yml"
75+
}
7176
},
7277
"scripts": {
7378
"dev-tools": "dev-tools",

grumphp.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
grumphp:
2+
stop_on_failure: true
3+
4+
tasks:
5+
composer_script:
6+
script: 'dev-tools'
7+
triggered_by: ['php']
8+
9+
testsuites:
10+
git_pre_commit:
11+
tasks:
12+
- composer_script

src/Command/InstallScriptsCommand.php

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@
1818

1919
namespace FastForward\DevTools\Command;
2020

21-
use FastForward\DevTools\Composer\ScriptsInstallerTrait;
21+
use Composer\Factory;
22+
use Composer\Json\JsonManipulator;
2223
use Symfony\Component\Console\Input\InputInterface;
2324
use Symfony\Component\Console\Output\OutputInterface;
25+
use Symfony\Component\Filesystem\Path;
2426

2527
/**
2628
* Represents the command responsible for installing development scripts into `composer.json`.
2729
* This class MUST NOT be overridden and SHALL rely on the `ScriptsInstallerTrait`.
2830
*/
2931
final class InstallScriptsCommand extends AbstractCommand
3032
{
31-
use ScriptsInstallerTrait;
32-
3333
/**
3434
* Configures the current command.
3535
*
@@ -61,7 +61,38 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6161
{
6262
$output->writeln('<info>Starting script installation...</info>');
6363

64-
$this->installScripts($this->requireComposer(), $this->getIO());
64+
$file = Factory::getComposerFile();
65+
66+
if (! $this->filesystem->exists($file)) {
67+
return self::FAILURE;
68+
}
69+
70+
$contents = $this->filesystem->readFile($file);
71+
$manipulator = new JsonManipulator($contents);
72+
73+
$scripts = [
74+
'dev-tools' => 'dev-tools',
75+
'dev-tools:fix' => 'dev-tools --fix',
76+
];
77+
78+
$extra = [
79+
'grumphp' => [
80+
'config-default-path' => Path::makeRelative(
81+
dirname(__DIR__, 2) . '/grumphp.yml',
82+
$this->getCurrentWorkingDirectory(),
83+
),
84+
],
85+
];
86+
87+
foreach ($scripts as $name => $command) {
88+
$manipulator->addSubNode('scripts', $name, $command);
89+
}
90+
91+
foreach ($extra as $name => $config) {
92+
$manipulator->addSubNode('extra', $name, $config, true);
93+
}
94+
95+
$this->filesystem->dumpFile($file, $manipulator->getContents());
6596

6697
return self::SUCCESS;
6798
}

src/Command/ReportsCommand.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,20 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6363
$docsPath = $this->getAbsolutePath('public');
6464
$coveragePath = $this->getAbsolutePath('public/coverage');
6565

66+
$results = [];
67+
6668
$output->writeln('<info>Generating API documentation on path: ' . $docsPath . '</info>');
67-
$this->runCommand('docs', [
69+
$results[] = $this->runCommand('docs', [
6870
'--target' => $docsPath,
6971
], $output);
7072

7173
$output->writeln('<info>Generating test coverage report on path: ' . $coveragePath . '</info>');
72-
$this->runCommand('tests', [
74+
$results[] = $this->runCommand('tests', [
7375
'--coverage' => $coveragePath,
7476
], $output);
7577

7678
$output->writeln('<info>Frontpage generation completed!</info>');
7779

78-
return self::SUCCESS;
80+
return in_array(self::FAILURE, $results, true) ? self::FAILURE : self::SUCCESS;
7981
}
8082
}

src/Command/StandardsCommand.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6868
{
6969
$output->writeln('<info>Running code standards checks...</info>');
7070

71-
$this->runCommand('refactor', $input, $output);
72-
$this->runCommand('phpdoc', $input, $output);
73-
$this->runCommand('code-style', $input, $output);
74-
$this->runCommand('reports', $input, $output);
71+
$results = [];
72+
73+
$results[] = $this->runCommand('refactor', $input, $output);
74+
$results[] = $this->runCommand('phpdoc', $input, $output);
75+
$results[] = $this->runCommand('code-style', $input, $output);
76+
$results[] = $this->runCommand('reports', $input, $output);
7577

7678
$output->writeln('<info>All code standards checks completed!</info>');
7779

78-
return self::SUCCESS;
80+
return in_array(self::FAILURE, $results, true) ? self::FAILURE : self::SUCCESS;
7981
}
8082
}

src/Composer/Plugin.php

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020

2121
use Composer\Composer;
2222
use Composer\EventDispatcher\EventSubscriberInterface;
23-
use Composer\Installer\PackageEvent;
24-
use Composer\Installer\PackageEvents;
23+
use Composer\Script\Event;
2524
use Composer\IO\IOInterface;
2625
use Composer\Plugin\Capability\CommandProvider;
2726
use Composer\Plugin\Capable;
@@ -35,8 +34,6 @@
3534
*/
3635
final class Plugin implements Capable, EventSubscriberInterface, PluginInterface
3736
{
38-
use ScriptsInstallerTrait;
39-
4037
/**
4138
* Resolves the implemented Composer capabilities structure.
4239
*
@@ -63,7 +60,7 @@ public function getCapabilities(): array
6360
public static function getSubscribedEvents(): array
6461
{
6562
return [
66-
ScriptEvents::POST_INSTALL_CMD=> 'onPostInstall',
63+
ScriptEvents::POST_INSTALL_CMD => 'onPostInstall',
6764
ScriptEvents::POST_UPDATE_CMD => 'onPostUpdate',
6865
];
6966
}
@@ -74,13 +71,13 @@ public static function getSubscribedEvents(): array
7471
* This method MUST be triggered by `POST_INSTALL_CMD` and SHALL delegate
7572
* the actual work to the `installScripts` utility.
7673
*
77-
* @param PackageEvent $event the package installation event context
74+
* @param Event $event the Composer script event context
7875
*
7976
* @return void
8077
*/
81-
public function onPostInstall(PackageEvent $event): void
78+
public function onPostInstall(Event $event): void
8279
{
83-
$this->installScripts($event->getComposer(), $event->getIO());
80+
$event->getComposer()->getEventDispatcher()->dispatchScript('install-scripts', true);
8481
}
8582

8683
/**
@@ -89,13 +86,13 @@ public function onPostInstall(PackageEvent $event): void
8986
* This method MUST be triggered by `POST_UPDATE_CMD` and SHALL ensure
9087
* that all development scripts are correctly aligned in the root configuration.
9188
*
92-
* @param PackageEvent $event the package update event context
89+
* @param Event $event the Composer script event context
9390
*
9491
* @return void
9592
*/
96-
public function onPostUpdate(PackageEvent $event): void
93+
public function onPostUpdate(Event $event): void
9794
{
98-
$this->installScripts($event->getComposer(), $event->getIO());
95+
$event->getComposer()->getEventDispatcher()->dispatchScript('install-scripts', true);
9996
}
10097

10198
/**

src/Composer/ScriptsInstallerTrait.php

Lines changed: 0 additions & 66 deletions
This file was deleted.

tests/Command/ReportsCommandTest.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,23 @@ protected function getCommandHelp(): string
6969
public function executeWillRunDocsAndTestsCommand(): void
7070
{
7171
$docsCommand = $this->prophesize(Command::class);
72-
$docsCommand->ignoreValidationErrors()
73-
->shouldBeCalled();
7472
$docsCommand->run(Argument::any(), Argument::any())->willReturn(ReportsCommand::SUCCESS);
73+
$docsCommand->ignoreValidationErrors()->will(function () {});
7574

7675
$testsCommand = $this->prophesize(Command::class);
77-
$testsCommand->ignoreValidationErrors()
78-
->shouldBeCalled();
7976
$testsCommand->run(Argument::any(), Argument::any())->willReturn(ReportsCommand::SUCCESS);
77+
$testsCommand->ignoreValidationErrors()->will(function () {});
8078

8179
$this->application->find('docs')
8280
->willReturn($docsCommand->reveal());
8381
$this->application->find('tests')
8482
->willReturn($testsCommand->reveal());
8583

84+
$this->output->writeln('<info>Generating frontpage for Fast Forward documentation...</info>')->shouldBeCalled();
85+
$this->output->writeln('<info>Generating API documentation on path: /Users/mentordosnerds/Sites/github.com/php-fast-forward/dev-tools/public</info>')->shouldBeCalled();
86+
$this->output->writeln('<info>Generating test coverage report on path: /Users/mentordosnerds/Sites/github.com/php-fast-forward/dev-tools/public/coverage</info>')->shouldBeCalled();
87+
$this->output->writeln('<info>Frontpage generation completed!</info>')->shouldBeCalled();
88+
8689
self::assertSame(ReportsCommand::SUCCESS, $this->invokeExecute());
8790
}
8891
}

tests/Command/StandardsCommandTest.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,16 @@ public function executeWillRunSuiteSequentially(): void
7272

7373
foreach ($orderedCommands as $commandName) {
7474
$prophecy = $this->prophesize(Command::class);
75-
$prophecy->ignoreValidationErrors()
76-
->shouldBeCalled();
7775
$prophecy->run(Argument::any(), Argument::any())->willReturn(StandardsCommand::SUCCESS);
78-
76+
$prophecy->ignoreValidationErrors()->will(function () {});
7977
$this->application->find($commandName)
8078
->willReturn($prophecy->reveal());
8179
}
8280

81+
$this->output->writeln('<info>Running code standards checks...</info>')->shouldBeCalled();
82+
$this->output->writeln('<info>All code standards checks completed!</info>')->shouldBeCalled();
83+
$this->output->writeln(Argument::any())->shouldBeCalled();
84+
8385
self::assertSame(StandardsCommand::SUCCESS, $this->invokeExecute());
8486
}
8587
}

0 commit comments

Comments
 (0)