From 187dcb6aeb57225f6788950c0630b412da635183 Mon Sep 17 00:00:00 2001 From: Boy132 Date: Thu, 1 Jan 2026 04:13:15 +0100 Subject: [PATCH 1/7] add workflow job for phpstan --- .github/workflows/lint.yml | 69 ++++++++++++++++++++++++++++++++++++++ .github/workflows/pint.yml | 29 ---------------- 2 files changed, 69 insertions(+), 29 deletions(-) create mode 100644 .github/workflows/lint.yml delete mode 100644 .github/workflows/pint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..188c639 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,69 @@ +name: Lint + +on: + push: + branches: + - main + pull_request: + +jobs: + pint: + name: Pint + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.4 + tools: composer:v2 + coverage: none + + - name: Init composer + run: composer init --no-interaction + + - name: Install Laravel Pint + run: composer require "laravel/pint:^1.15.3" + + - name: Run Pint + run: vendor/bin/pint --test + phpstan: + name: PHPStan + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Clone Pelican Panel + run: git clone --depth=1 https://github.com/pelican-dev/panel pelican + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.4 + tools: composer:v2 + coverage: none + + - name: Install dependencies + run: | + cd pelican + composer install --no-scripts --no-progress --prefer-dist + composer require "stripe/stripe-php:^18.0" "kovah/laravel-socialite-oidc:^0.5" "krymosoftware/gameq:^4.0" + + - name: Setup .env file + run: cp pelican/.env.example pelican/.env + + - name: Move plugin folders + run: | + mkdir -p pelican/plugins + rsync -av --progress ./ pelican/plugins/ --exclude=pelican + + - name: Run PHPStan Analysis + run: | + cd pelican + vendor/bin/phpstan analyse plugins --memory-limit=-1 --error-format=github + diff --git a/.github/workflows/pint.yml b/.github/workflows/pint.yml deleted file mode 100644 index 002a204..0000000 --- a/.github/workflows/pint.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Pint - -on: - push: - branches: - - main - pull_request: - -jobs: - pint: - name: Pint - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up PHP - uses: shivammathur/setup-php@v2 - with: - php-version: 8.4 - tools: composer:v2 - coverage: none - - - name: Install Laravel Pint - run: composer global require laravel/pint - - - name: Run Laravel Pint - run: ~/.composer/vendor/bin/pint --test From aaf375bde920fb27742821af3f0f650dec3f147f Mon Sep 17 00:00:00 2001 From: Boy132 Date: Thu, 1 Jan 2026 16:34:15 +0100 Subject: [PATCH 2/7] use custom phpstan.neon --- .github/workflows/lint.yml | 3 ++- phpstan.neon | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 phpstan.neon diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 188c639..7e6d630 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -57,10 +57,11 @@ jobs: - name: Setup .env file run: cp pelican/.env.example pelican/.env - - name: Move plugin folders + - name: Move plugin folders and phpstan.neon run: | mkdir -p pelican/plugins rsync -av --progress ./ pelican/plugins/ --exclude=pelican + cp phpstan.neon laravel-project/phpstan.neon - name: Run PHPStan Analysis run: | diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..0712e48 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,9 @@ +includes: + - vendor/larastan/larastan/extension.neon + +parameters: + + paths: + - plugins + + level: 6 From 84d741ab0120ed365fb159e6a755bc42a316537c Mon Sep 17 00:00:00 2001 From: Boy132 Date: Thu, 1 Jan 2026 16:35:10 +0100 Subject: [PATCH 3/7] fix name --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7e6d630..d6fcb2c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -61,7 +61,7 @@ jobs: run: | mkdir -p pelican/plugins rsync -av --progress ./ pelican/plugins/ --exclude=pelican - cp phpstan.neon laravel-project/phpstan.neon + cp phpstan.neon pelican/phpstan.neon - name: Run PHPStan Analysis run: | From cbfe871f1b748ba778415fb1164edebd1bb1fc54 Mon Sep 17 00:00:00 2001 From: Boy132 Date: Thu, 1 Jan 2026 16:37:51 +0100 Subject: [PATCH 4/7] add ignoreErrors --- .github/workflows/lint.yml | 2 +- phpstan.neon | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d6fcb2c..77c7fda 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -66,5 +66,5 @@ jobs: - name: Run PHPStan Analysis run: | cd pelican - vendor/bin/phpstan analyse plugins --memory-limit=-1 --error-format=github + vendor/bin/phpstan analyse --memory-limit=-1 --error-format=github diff --git a/phpstan.neon b/phpstan.neon index 0712e48..2f4f28f 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -7,3 +7,8 @@ parameters: - plugins level: 6 + + ignoreErrors: + - identifier: argument.templateType + - identifier: missingType.generics + - identifier: larastan.noEnvCallsOutsideOfConfig From 394daa363219762804f23f08df3a596c95005d6a Mon Sep 17 00:00:00 2001 From: Boy132 Date: Thu, 1 Jan 2026 16:40:00 +0100 Subject: [PATCH 5/7] fix some errors --- billing/src/Models/Coupon.php | 4 ++-- billing/src/Models/Order.php | 12 ++++++------ billing/src/Models/Product.php | 4 ++-- billing/src/Models/ProductPrice.php | 2 +- phpstan.neon | 1 - 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/billing/src/Models/Coupon.php b/billing/src/Models/Coupon.php index c5e5cde..e31c31f 100644 --- a/billing/src/Models/Coupon.php +++ b/billing/src/Models/Coupon.php @@ -54,7 +54,7 @@ protected static function boot(): void static::deleted(function (self $model) { if (!is_null($model->stripe_coupon_id)) { /** @var StripeClient $stripeClient */ - $stripeClient = app(StripeClient::class); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + $stripeClient = app(StripeClient::class); $stripeClient->coupons->delete($model->stripe_coupon_id); $stripeClient->coupons->delete($model->stripe_promotion_id); @@ -65,7 +65,7 @@ protected static function boot(): void public function sync(): void { /** @var StripeClient $stripeClient */ - $stripeClient = app(StripeClient::class); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + $stripeClient = app(StripeClient::class); if (is_null($this->stripe_coupon_id)) { $data = [ diff --git a/billing/src/Models/Order.php b/billing/src/Models/Order.php index 389c9d2..69c1c95 100644 --- a/billing/src/Models/Order.php +++ b/billing/src/Models/Order.php @@ -75,7 +75,7 @@ public function checkExpire(): bool if ($this->status === OrderStatus::Active && !is_null($this->expires_at) && now('UTC') >= $this->expires_at) { try { if ($this->server) { - app(SuspensionService::class)->handle($this->server, SuspendAction::Suspend); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + app(SuspensionService::class)->handle($this->server, SuspendAction::Suspend); } } catch (Exception $exception) { report($exception); @@ -98,7 +98,7 @@ private function expireCheckoutSession(): void { if (!is_null($this->stripe_checkout_id)) { /** @var StripeClient $stripeClient */ - $stripeClient = app(StripeClient::class); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + $stripeClient = app(StripeClient::class); $session = $stripeClient->checkout->sessions->retrieve($this->stripe_checkout_id); @@ -111,7 +111,7 @@ private function expireCheckoutSession(): void public function getCheckoutSession(): Session { /** @var StripeClient $stripeClient */ - $stripeClient = app(StripeClient::class); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + $stripeClient = app(StripeClient::class); if (is_null($this->stripe_checkout_id)) { $session = $stripeClient->checkout->sessions->create([ @@ -165,7 +165,7 @@ public function activate(?string $stripePaymentId): void try { if ($this->server) { - app(SuspensionService::class)->handle($this->server, SuspendAction::Unsuspend); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + app(SuspensionService::class)->handle($this->server, SuspendAction::Unsuspend); } else { $this->createServer(); } @@ -178,7 +178,7 @@ public function close(): void { try { if ($this->server) { - app(SuspensionService::class)->handle($this->server, SuspendAction::Suspend); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + app(SuspensionService::class)->handle($this->server, SuspendAction::Suspend); } } catch (Exception $exception) { report($exception); @@ -228,7 +228,7 @@ public function createServer(): Server $object->setTags($product->tags); $object->setPorts($product->ports); - $server = app(ServerCreationService::class)->handle($data, $object); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + $server = app(ServerCreationService::class)->handle($data, $object); $this->update([ 'server_id' => $server->id, diff --git a/billing/src/Models/Product.php b/billing/src/Models/Product.php index b837a71..d07713b 100644 --- a/billing/src/Models/Product.php +++ b/billing/src/Models/Product.php @@ -74,7 +74,7 @@ protected static function boot(): void static::deleted(function (self $model) { if (!is_null($model->stripe_id)) { /** @var StripeClient $stripeClient */ - $stripeClient = app(StripeClient::class); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + $stripeClient = app(StripeClient::class); $stripeClient->products->delete($model->stripe_id); } @@ -99,7 +99,7 @@ public function getLabel(): string public function sync(): void { /** @var StripeClient $stripeClient */ - $stripeClient = app(StripeClient::class); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + $stripeClient = app(StripeClient::class); if (is_null($this->stripe_id)) { $stripeProduct = $stripeClient->products->create([ diff --git a/billing/src/Models/ProductPrice.php b/billing/src/Models/ProductPrice.php index 70d1c92..e8a1d45 100644 --- a/billing/src/Models/ProductPrice.php +++ b/billing/src/Models/ProductPrice.php @@ -65,7 +65,7 @@ public function sync(): void $this->product->sync(); /** @var StripeClient $stripeClient */ - $stripeClient = app(StripeClient::class); // @phpstan-ignore myCustomRules.forbiddenGlobalFunctions + $stripeClient = app(StripeClient::class); if (is_null($this->stripe_id)) { $stripePrice = $stripeClient->prices->create([ diff --git a/phpstan.neon b/phpstan.neon index 2f4f28f..d6d7566 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -9,6 +9,5 @@ parameters: level: 6 ignoreErrors: - - identifier: argument.templateType - identifier: missingType.generics - identifier: larastan.noEnvCallsOutsideOfConfig From b07b18cfd45202777a505ec0ebee3e5775c37f80 Mon Sep 17 00:00:00 2001 From: Boy132 Date: Thu, 1 Jan 2026 16:53:45 +0100 Subject: [PATCH 6/7] fix remaining errors --- billing/src/Filament/App/Widgets/ProductWidget.php | 2 +- .../src/Filament/Components/Actions/UploadLogsAction.php | 2 +- player-counter/database/Seeders/PlayerCounterSeeder.php | 1 + player-counter/src/Filament/Server/Pages/PlayersPage.php | 6 +++--- .../src/Filament/Server/Widgets/ServerPlayerWidget.php | 4 ++-- .../Server/Resources/Subdomains/SubdomainResource.php | 2 +- subdomains/src/Models/CloudflareDomain.php | 1 + subdomains/src/Models/Subdomain.php | 3 +++ .../src/Filament/Server/Pages/ServerResourcePage.php | 2 +- user-creatable-servers/src/Models/UserResourceLimits.php | 2 +- 10 files changed, 15 insertions(+), 10 deletions(-) diff --git a/billing/src/Filament/App/Widgets/ProductWidget.php b/billing/src/Filament/App/Widgets/ProductWidget.php index 37815de..ad08c08 100644 --- a/billing/src/Filament/App/Widgets/ProductWidget.php +++ b/billing/src/Filament/App/Widgets/ProductWidget.php @@ -22,7 +22,7 @@ class ProductWidget extends Widget implements HasActions, HasSchemas use InteractsWithActions; use InteractsWithSchemas; - protected string $view = 'billing::widget'; + protected string $view = 'billing::widget'; // @phpstan-ignore property.defaultValue public ?Product $product = null; diff --git a/pastefox-share/src/Filament/Components/Actions/UploadLogsAction.php b/pastefox-share/src/Filament/Components/Actions/UploadLogsAction.php index a26f5a1..b2aff9f 100644 --- a/pastefox-share/src/Filament/Components/Actions/UploadLogsAction.php +++ b/pastefox-share/src/Filament/Components/Actions/UploadLogsAction.php @@ -74,10 +74,10 @@ protected function setUp(): void } $response = Http::withHeaders($headers) - ->post('https://pastefox.com/api/pastes', $payload) ->timeout(30) ->connectTimeout(5) ->throw() + ->post('https://pastefox.com/api/pastes', $payload) ->json(); if ($response['success']) { diff --git a/player-counter/database/Seeders/PlayerCounterSeeder.php b/player-counter/database/Seeders/PlayerCounterSeeder.php index fc4e069..661a2b3 100644 --- a/player-counter/database/Seeders/PlayerCounterSeeder.php +++ b/player-counter/database/Seeders/PlayerCounterSeeder.php @@ -32,6 +32,7 @@ public function run(): void } } + // @phpstan-ignore if.alwaysTrue if ($this->command) { $this->command->info('Created game query types for minecraft and source'); } diff --git a/player-counter/src/Filament/Server/Pages/PlayersPage.php b/player-counter/src/Filament/Server/Pages/PlayersPage.php index 6da10ae..3558853 100644 --- a/player-counter/src/Filament/Server/Pages/PlayersPage.php +++ b/player-counter/src/Filament/Server/Pages/PlayersPage.php @@ -40,7 +40,7 @@ public static function canAccess(): bool /** @var Server $server */ $server = Filament::getTenant(); - return parent::canAccess() && $server->allocation && $server->egg->gameQuery()->exists(); + return parent::canAccess() && $server->allocation && $server->egg->gameQuery()->exists(); // @phpstan-ignore method.notFound } public static function getNavigationLabel(): string @@ -72,7 +72,7 @@ public function table(Table $table): Table $server = Filament::getTenant(); /** @var ?GameQuery $gameQuery */ - $gameQuery = $server->egg->gameQuery; + $gameQuery = $server->egg->gameQuery; // @phpstan-ignore property.notFound $isMinecraft = $gameQuery?->query_type->isMinecraft(); @@ -105,7 +105,7 @@ public function table(Table $table): Table $players = []; /** @var ?GameQuery $gameQuery */ - $gameQuery = $server->egg->gameQuery; + $gameQuery = $server->egg->gameQuery; // @phpstan-ignore property.notFound if ($gameQuery) { $data = $gameQuery->runQuery($server->allocation); diff --git a/player-counter/src/Filament/Server/Widgets/ServerPlayerWidget.php b/player-counter/src/Filament/Server/Widgets/ServerPlayerWidget.php index 80688da..2d7a8ca 100644 --- a/player-counter/src/Filament/Server/Widgets/ServerPlayerWidget.php +++ b/player-counter/src/Filament/Server/Widgets/ServerPlayerWidget.php @@ -17,7 +17,7 @@ public static function canView(): bool /** @var Server $server */ $server = Filament::getTenant(); - return !$server->isInConflictState() && $server->allocation && $server->egg->gameQuery()->exists() && !$server->retrieveStatus()->isOffline(); + return !$server->isInConflictState() && $server->allocation && $server->egg->gameQuery()->exists() && !$server->retrieveStatus()->isOffline(); // @phpstan-ignore method.notFound } protected function getStats(): array @@ -26,7 +26,7 @@ protected function getStats(): array $server = Filament::getTenant(); /** @var ?GameQuery $gameQuery */ - $gameQuery = $server->egg->gameQuery; + $gameQuery = $server->egg->gameQuery; // @phpstan-ignore property.notFound if (!$gameQuery) { return []; diff --git a/subdomains/src/Filament/Server/Resources/Subdomains/SubdomainResource.php b/subdomains/src/Filament/Server/Resources/Subdomains/SubdomainResource.php index ec372b3..584531b 100644 --- a/subdomains/src/Filament/Server/Resources/Subdomains/SubdomainResource.php +++ b/subdomains/src/Filament/Server/Resources/Subdomains/SubdomainResource.php @@ -60,7 +60,7 @@ protected static function getBadgeCount(): int /** @var Server $server */ $server = Filament::getTenant(); - return $server->subdomains->count(); + return $server->subdomains->count(); // @phpstan-ignore property.notFound } protected static function getBadgeLimit(): int diff --git a/subdomains/src/Models/CloudflareDomain.php b/subdomains/src/Models/CloudflareDomain.php index fa4ef19..dbe5dd7 100644 --- a/subdomains/src/Models/CloudflareDomain.php +++ b/subdomains/src/Models/CloudflareDomain.php @@ -34,6 +34,7 @@ public function subdomains(): HasMany public function fetchCloudflareId(): void { + // @phpstan-ignore staticMethod.notFound $response = Http::cloudflare()->get('zones', [ 'name' => $this->name, ])->json(); diff --git a/subdomains/src/Models/Subdomain.php b/subdomains/src/Models/Subdomain.php index 14cd323..f8e01f4 100644 --- a/subdomains/src/Models/Subdomain.php +++ b/subdomains/src/Models/Subdomain.php @@ -68,6 +68,7 @@ protected function createOnCloudflare(): void } if (!$this->cloudflare_id) { + // @phpstan-ignore staticMethod.notFound $response = Http::cloudflare()->post("zones/{$this->domain->cloudflare_id}/dns_records", [ 'name' => $this->name, 'ttl' => 120, @@ -94,6 +95,7 @@ protected function updateOnCloudflare(): void } if ($this->cloudflare_id) { + // @phpstan-ignore staticMethod.notFound Http::cloudflare()->patch("zones/{$this->domain->cloudflare_id}/dns_records/{$this->cloudflare_id}", [ 'name' => $this->name, 'ttl' => 120, @@ -108,6 +110,7 @@ protected function updateOnCloudflare(): void protected function deleteOnCloudflare(): void { if ($this->cloudflare_id) { + // @phpstan-ignore staticMethod.notFound Http::cloudflare()->delete("zones/{$this->domain->cloudflare_id}/dns_records/{$this->cloudflare_id}"); } } diff --git a/user-creatable-servers/src/Filament/Server/Pages/ServerResourcePage.php b/user-creatable-servers/src/Filament/Server/Pages/ServerResourcePage.php index 108e87a..6854a6a 100644 --- a/user-creatable-servers/src/Filament/Server/Pages/ServerResourcePage.php +++ b/user-creatable-servers/src/Filament/Server/Pages/ServerResourcePage.php @@ -163,7 +163,7 @@ public function save(): void try { /** @var DaemonServerRepository $repository */ - $repository = app(DaemonServerRepository::class); // @phpstan-ignore-line + $repository = app(DaemonServerRepository::class); $repository->setServer($server)->sync(); diff --git a/user-creatable-servers/src/Models/UserResourceLimits.php b/user-creatable-servers/src/Models/UserResourceLimits.php index c02ae29..5b15b48 100644 --- a/user-creatable-servers/src/Models/UserResourceLimits.php +++ b/user-creatable-servers/src/Models/UserResourceLimits.php @@ -148,7 +148,7 @@ public function createServer(string $name, int|Egg $egg, int $cpu, int $memory, $object->setPorts(array_filter(explode(',', config('user-creatable-servers.deployment_ports')))); /** @var ServerCreationService $service */ - $service = app(ServerCreationService::class); // @phpstan-ignore-line + $service = app(ServerCreationService::class); return $service->handle($data, $object); } From b1c97c06b5d1d00fc4b74adbe393f49eba9073d9 Mon Sep 17 00:00:00 2001 From: Boy132 Date: Thu, 1 Jan 2026 16:55:52 +0100 Subject: [PATCH 7/7] small cleanup --- .github/workflows/lint.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 77c7fda..defe8a4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -48,10 +48,14 @@ jobs: tools: composer:v2 coverage: none - - name: Install dependencies + - name: Install panel dependencies + run: | + cd pelican + composer install --no-interaction --no-suggest --no-progress --no-scripts + + - name: Install plugin dependencies run: | cd pelican - composer install --no-scripts --no-progress --prefer-dist composer require "stripe/stripe-php:^18.0" "kovah/laravel-socialite-oidc:^0.5" "krymosoftware/gameq:^4.0" - name: Setup .env file