From a4c8e0b6000d0cee1af38242cd1959db55152769 Mon Sep 17 00:00:00 2001 From: Jordan Partridge Date: Fri, 12 Dec 2025 08:41:00 -0700 Subject: [PATCH 1/2] feat: add Laravel service provider for zero-config setup Fixes #3 - Add PrServiceProvider with auto-discovery support - Create publishable config/pr.php configuration file - Auto-configure PullRequests facade on Laravel boot - Read token from config('services.github.token') or GITHUB_TOKEN env - Exclude service provider from PHPStan analysis (Laravel not required) --- composer.json | 7 +++++ config/pr.php | 20 ++++++++++++++ phpstan.neon | 2 ++ src/PrServiceProvider.php | 58 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 config/pr.php create mode 100644 src/PrServiceProvider.php diff --git a/composer.json b/composer.json index ffa1261..abb9bb4 100644 --- a/composer.json +++ b/composer.json @@ -43,6 +43,13 @@ "pestphp/pest-plugin": true } }, + "extra": { + "laravel": { + "providers": [ + "ConduitUI\\Pr\\PrServiceProvider" + ] + } + }, "minimum-stability": "dev", "prefer-stable": true } diff --git a/config/pr.php b/config/pr.php new file mode 100644 index 0000000..b6db9f3 --- /dev/null +++ b/config/pr.php @@ -0,0 +1,20 @@ + [ + 'token' => env('GITHUB_TOKEN'), + ], +]; diff --git a/phpstan.neon b/phpstan.neon index 5cc331b..8a01e7c 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,6 +2,8 @@ parameters: level: 8 paths: - src + excludePaths: + - src/PrServiceProvider.php tmpDir: build/phpstan ignoreErrors: - diff --git a/src/PrServiceProvider.php b/src/PrServiceProvider.php new file mode 100644 index 0000000..53a60e5 --- /dev/null +++ b/src/PrServiceProvider.php @@ -0,0 +1,58 @@ +mergeConfigFrom( + __DIR__.'/../config/pr.php', + 'pr' + ); + + $this->app->singleton(PrServiceInterface::class, function ($app) { + $token = $app['config']->get('pr.github.token') + ?? $app['config']->get('services.github.token') + ?? env('GITHUB_TOKEN'); + + if (! $token) { + throw new \RuntimeException( + 'GitHub token not configured. Set GITHUB_TOKEN environment variable or publish and configure the pr.php config file.' + ); + } + + return new GitHubPrService(new Connector($token)); + }); + + $this->app->singleton(GitHubPrService::class, function ($app) { + return $app->make(PrServiceInterface::class); + }); + } + + /** + * Bootstrap services. + */ + public function boot(): void + { + if ($this->app->runningInConsole()) { + $this->publishes([ + __DIR__.'/../config/pr.php' => config_path('pr.php'), + ], 'pr-config'); + } + + // Auto-configure the PullRequests facade + $service = $this->app->make(PrServiceInterface::class); + PullRequests::setService($service); + } +} From 6adaa47fa734cc47009e088ab9aeb3716b20068d Mon Sep 17 00:00:00 2001 From: Jordan Partridge Date: Fri, 12 Dec 2025 09:04:46 -0700 Subject: [PATCH 2/2] Fix CodeRabbit issues in PrServiceProvider - Extract token resolution to helper method that properly handles empty strings (trim + explicit check instead of ?? operator) - Make boot() lazy - only configures facade if token is available, preventing app crashes when PR package is installed but not used - Add explanatory comment for PHPStan exclusion Addresses CodeRabbit review comments on empty string handling and eager resolution in boot(). --- phpstan.neon | 2 ++ src/PrServiceProvider.php | 36 +++++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 8a01e7c..94e9bd2 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -3,6 +3,8 @@ parameters: paths: - src excludePaths: + # Excluded because it depends on Laravel's ServiceProvider which isn't available + # in the non-Laravel test environment. The class is only used in Laravel apps. - src/PrServiceProvider.php tmpDir: build/phpstan ignoreErrors: diff --git a/src/PrServiceProvider.php b/src/PrServiceProvider.php index 53a60e5..ea3c61d 100644 --- a/src/PrServiceProvider.php +++ b/src/PrServiceProvider.php @@ -22,11 +22,9 @@ public function register(): void ); $this->app->singleton(PrServiceInterface::class, function ($app) { - $token = $app['config']->get('pr.github.token') - ?? $app['config']->get('services.github.token') - ?? env('GITHUB_TOKEN'); + $token = $this->resolveToken($app); - if (! $token) { + if ($token === null) { throw new \RuntimeException( 'GitHub token not configured. Set GITHUB_TOKEN environment variable or publish and configure the pr.php config file.' ); @@ -51,8 +49,32 @@ public function boot(): void ], 'pr-config'); } - // Auto-configure the PullRequests facade - $service = $this->app->make(PrServiceInterface::class); - PullRequests::setService($service); + // Auto-configure the PullRequests facade only if token is available + // This prevents crashing apps that don't need PR functionality + if ($this->resolveToken($this->app) !== null) { + PullRequests::setService($this->app->make(PrServiceInterface::class)); + } + } + + /** + * Resolve the GitHub token from available configuration sources. + * + * @param \Illuminate\Contracts\Foundation\Application $app + */ + private function resolveToken($app): ?string + { + $sources = [ + $app['config']->get('pr.github.token'), + $app['config']->get('services.github.token'), + env('GITHUB_TOKEN'), + ]; + + foreach ($sources as $token) { + if (is_string($token) && trim($token) !== '') { + return trim($token); + } + } + + return null; } }