diff --git a/CHANGELOG.md b/CHANGELOG.md index d9792c4..8f358c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -_Nothing yet._ +### Fixed + +- **`install` works.** The shipped config named the hook command + `Simtabi\GitCommitChecker\Commands\PreCommitHookCommand`, a namespace this package never had, + so `install` aborted with *"Class [...] not found"*. It now names + `Simtabi\Laranail\GitCommitChecker\Commands\PreCommitHookCommand`. +- **The config is read where the provider registers it.** Both commands read the bare + `git-commit-checker` key while the defaults live at `laranail.git-commit-checker`, so an + unpublished install iterated no hooks and the hook always reported itself disabled. + +### Deprecated + +- **A config published to `config/git-commit-checker.php`** is still honoured. Republish with + `--tag=laranail::git-commit-checker-config`, which now writes + `config/laranail/git-commit-checker.php`, and delete the old file. + +### Added + +- A `Quick start` section in the README. ## v0.1.0 diff --git a/README.md b/README.md index 9110bf4..7e8c0ce 100755 --- a/README.md +++ b/README.md @@ -16,6 +16,19 @@ Requires PHP `^8.4.1 || ^8.5` and Laravel `^13.0`. composer require laranail/git-commit-checker ``` +## Quick start + +```bash +# Write .git/hooks/pre-commit and, optionally, a pint.json preset +php artisan git-commit-checker:install + +# Every commit now runs Pint in --test mode over the changed PHP files; +# run the same check by hand without committing +php artisan git-commit-checker:pre-commit-hook +``` + +How the hook is wired is in [Architecture](docs/architecture.md); everything else is in the [documentation index](#documentation). + ## Documentation Full documentation is at diff --git a/config/config.php b/config/config.php index 48e499f..4ea6dd3 100644 --- a/config/config.php +++ b/config/config.php @@ -2,7 +2,7 @@ declare(strict_types=1); -use Simtabi\GitCommitChecker\Commands\PreCommitHookCommand; +use Simtabi\Laranail\GitCommitChecker\Commands\PreCommitHookCommand; return [ 'enabled' => env('GIT_COMMIT_CHECKER_ENABLED', true), diff --git a/src/Commands/Concerns/ReadsPackageConfig.php b/src/Commands/Concerns/ReadsPackageConfig.php new file mode 100644 index 0000000..06b6ca9 --- /dev/null +++ b/src/Commands/Concerns/ReadsPackageConfig.php @@ -0,0 +1,26 @@ +laravel['config']; + + $root = $config->has('git-commit-checker.hooks') ? 'git-commit-checker' : 'laranail.git-commit-checker'; + + return $config->get("{$root}.{$key}", $default); + } +} diff --git a/src/Commands/InstallCommand.php b/src/Commands/InstallCommand.php index 2e22754..d17ee7e 100644 --- a/src/Commands/InstallCommand.php +++ b/src/Commands/InstallCommand.php @@ -9,11 +9,13 @@ use Illuminate\Console\ConfirmableTrait; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Attribute\AsCommand; +use Simtabi\Laranail\GitCommitChecker\Commands\Concerns\ReadsPackageConfig; #[AsCommand('git-commit-checker:install', 'Install "pre_commit" hook into your git.')] class InstallCommand extends Command { use ConfirmableTrait; + use ReadsPackageConfig; public function handle(): int { @@ -29,7 +31,7 @@ public function handle(): int return self::FAILURE; } - foreach ($this->laravel['config']->get('git-commit-checker.hooks') as $hook => $command) { + foreach ($this->packageConfig('hooks', []) as $hook => $command) { $this->install($hook, $command) ? $this->components->info("Hook [$hook] is installed successfully.") : $this->components->error("Unable to install hook [$hook]."); @@ -88,7 +90,7 @@ protected function generateHookScript(string $signature): string protected function generatePintConfiguration(string $path): void { - $presets = $this->laravel['config']->get('git-commit-checker.pint.presets', []); + $presets = $this->packageConfig('pint.presets', []); if (empty($presets)) { $this->components->error('Do not found a list of supported presets'); @@ -104,7 +106,7 @@ protected function generatePintConfiguration(string $path): void json_encode( $preset !== 'recommended' ? ['preset' => $preset] - : $this->laravel['config']->get('git-commit-checker.pint.recommended_preset'), + : $this->packageConfig('pint.recommended_preset'), JSON_PRETTY_PRINT, ) . PHP_EOL, )) { diff --git a/src/Commands/PreCommitHookCommand.php b/src/Commands/PreCommitHookCommand.php index 9ad23cc..48ddf65 100644 --- a/src/Commands/PreCommitHookCommand.php +++ b/src/Commands/PreCommitHookCommand.php @@ -11,13 +11,16 @@ use Illuminate\Console\Command; use Symfony\Component\Process\Process; use Symfony\Component\Console\Attribute\AsCommand; +use Simtabi\Laranail\GitCommitChecker\Commands\Concerns\ReadsPackageConfig; #[AsCommand('git-commit-checker:pre-commit-hook', 'Git hook before commit')] class PreCommitHookCommand extends Command { + use ReadsPackageConfig; + public function handle(): int { - if (! $this->laravel['config']->get('git-commit-checker.enabled')) { + if (! $this->packageConfig('enabled')) { $this->components->info('git-commit-hook is disabled. Skipped.'); return self::SUCCESS; diff --git a/src/Providers/GitCommitCheckerServiceProvider.php b/src/Providers/GitCommitCheckerServiceProvider.php index 7b5b27c..bbec619 100644 --- a/src/Providers/GitCommitCheckerServiceProvider.php +++ b/src/Providers/GitCommitCheckerServiceProvider.php @@ -21,7 +21,7 @@ public function boot() if ($this->app->runningInConsole()) { $this->publishes([ - __DIR__ . '/../../config/config.php' => config_path('git-commit-checker.php'), + __DIR__ . '/../../config/config.php' => config_path('laranail/git-commit-checker.php'), ], 'laranail::git-commit-checker-config'); $this->publishes([ diff --git a/tests/Feature/ConfigTest.php b/tests/Feature/ConfigTest.php new file mode 100644 index 0000000..8e5479c --- /dev/null +++ b/tests/Feature/ConfigTest.php @@ -0,0 +1,52 @@ +toBeArray()->not->toBeEmpty(); + + foreach ($hooks as $hook => $class) { + expect(class_exists($class))->toBeTrue("hook [$hook] names a class that does not exist: $class") + ->and(is_subclass_of($class, Command::class))->toBeTrue(); + } + + expect($hooks['pre-commit'])->toBe(PreCommitHookCommand::class); +}); + +/** + * Registered at `laranail.git-commit-checker`, read at the bare `git-commit-checker` key: unpublished, + * `enabled` was null, so the hook reported "disabled" and checked nothing, ever. + */ +it('runs the hook when enabled at the registered key', function (): void { + Config::set('laranail.git-commit-checker.enabled', true); + + $this->artisan('git-commit-checker:pre-commit-hook') + ->doesntExpectOutputToContain('is disabled'); +}); + +it('skips the hook when disabled at the registered key', function (): void { + Config::set('laranail.git-commit-checker.enabled', false); + + $this->artisan('git-commit-checker:pre-commit-hook') + ->expectsOutputToContain('is disabled') + ->assertSuccessful(); +}); + +/** An application that published the old bare config/git-commit-checker.php keeps its override. */ +it('still honours a config published to the old bare path', function (): void { + Config::set('git-commit-checker', array_replace(Config::get('laranail.git-commit-checker'), ['enabled' => false])); + Config::set('laranail.git-commit-checker.enabled', true); + + $this->artisan('git-commit-checker:pre-commit-hook') + ->expectsOutputToContain('is disabled'); +});