From e45b01f821622da4d8fed79b86e2779e09305b7c Mon Sep 17 00:00:00 2001 From: Andrew Howe Date: Fri, 29 May 2026 15:14:07 -0400 Subject: [PATCH 01/11] Add GitHub Enterprise Server support Enable CDash to post check runs and commit statuses to ghe installations in addition to github.com. Changes: - Add GITHUB_ENTERPRISE_URL config option (env var) - Pass enterprise URL to GitHubClient constructor with apiVersion=null (so it defaults to 'v3') so the PathPrepend plugin builds correct /api/v3/ paths for ghe - Add isGitHubUrl() helpers in GitHub.php and RepositoryUtils.php to match repository URLs against both github.com and the configured GHE host - Convert get_github_api_url() to construct /api/v3/repos/ paths for GHE repositories - Make DoneHandler always create/update the check when a revision exists, rather than requiring the pendingSubmissions recheck flag --- app/Http/Submission/Handlers/DoneHandler.php | 7 +++-- app/Utils/RepositoryUtils.php | 27 +++++++++++++++++++- app/cdash/app/Lib/Repository/GitHub.php | 18 +++++++++++-- config/cdash.php | 1 + 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/app/Http/Submission/Handlers/DoneHandler.php b/app/Http/Submission/Handlers/DoneHandler.php index 149f790e33..7b2ece70dc 100644 --- a/app/Http/Submission/Handlers/DoneHandler.php +++ b/app/Http/Submission/Handlers/DoneHandler.php @@ -63,10 +63,9 @@ public function endElement($parser, $name): void $this->Build->UpdateBuild($this->Build->Id, -1, -1); $this->Build->MarkAsDone(true); - // Should we re-run any checks that were previously marked - // as pending? - if ($pendingSubmissionsModel !== null && $pendingSubmissionsModel->recheck) { - $revision = \App\Models\Build::findOrFail((int) $this->Build->Id)->updateStep->revision ?? ''; + // Create or update the GitHub check for this commit. + $revision = \App\Models\Build::findOrFail((int) $this->Build->Id)->updateStep->revision ?? ''; + if ($revision !== '') { Repository::createOrUpdateCheck($revision); } diff --git a/app/Utils/RepositoryUtils.php b/app/Utils/RepositoryUtils.php index b18f0cc098..9aa9f092ac 100644 --- a/app/Utils/RepositoryUtils.php +++ b/app/Utils/RepositoryUtils.php @@ -14,6 +14,19 @@ class RepositoryUtils { + private static function isGitHubUrl(string $url): bool + { + if (str_contains($url, 'github.com')) { + return true; + } + $enterpriseUrl = config('cdash.github_enterprise_url'); + if ($enterpriseUrl !== null) { + $host = parse_url($enterpriseUrl, PHP_URL_HOST); + return $host !== false && str_contains($url, $host); + } + return false; + } + /** Return the GitHub diff URL */ public static function get_github_diff_url($projecturl, $directory, $file, $revision) { @@ -146,6 +159,18 @@ public static function post_pull_request_comment($projectid, $pull_request, $com /** Convert GitHub repository viewer URL into corresponding API URL. */ public static function get_github_api_url($github_url): string { + $enterpriseUrl = config('cdash.github_enterprise_url'); + if ($enterpriseUrl !== null) { + $host = parse_url($enterpriseUrl, PHP_URL_HOST); + if ($host !== false && str_contains($github_url, $host)) { + // For GHE, ...://// becomes ...:///api/v3/repos// + $idx = strpos($github_url, $host); + $idx2 = $idx + strlen($host) + 1; + $api_url = substr($github_url, 0, $idx) . $host . '/api/v3/repos/'; + $api_url .= substr($github_url, $idx2); + return $api_url; + } + } /* * For a URL of the form: * ...://github.com// @@ -166,7 +191,7 @@ public static function post_github_pull_request_comment(Project $project, $pull_ $repo = null; $repositories = $project->GetRepositories(); foreach ($repositories as $repository) { - if (str_contains($repository['url'], 'github.com')) { + if (self::isGitHubUrl($repository['url'])) { $repo = $repository; break; } diff --git a/app/cdash/app/Lib/Repository/GitHub.php b/app/cdash/app/Lib/Repository/GitHub.php index 32383b1374..15aef5a85b 100644 --- a/app/cdash/app/Lib/Repository/GitHub.php +++ b/app/cdash/app/Lib/Repository/GitHub.php @@ -76,7 +76,7 @@ public function __construct(Project $project) $repositories = $this->project->GetRepositories(); foreach ($repositories as $repo) { - if (str_contains($repo['url'], 'github.com')) { + if ($this->isGitHubUrl($repo['url'])) { $this->installationId = $repo['username']; break; } @@ -93,7 +93,8 @@ public function setApiClient(GitHubClient $client): void protected function initializeApiClient(): void { $builder = new GitHubBuilder(); - $apiClient = new GitHubClient($builder, 'machine-man-preview'); + $enterpriseUrl = config('cdash.github_enterprise_url'); + $apiClient = new GitHubClient($builder, null, $enterpriseUrl); $this->setApiClient($apiClient); } @@ -662,6 +663,19 @@ public function getRepository(): string return $this->repo; } + private function isGitHubUrl(string $url): bool + { + if (str_contains($url, 'github.com')) { + return true; + } + $enterpriseUrl = config('cdash.github_enterprise_url'); + if ($enterpriseUrl !== null) { + $host = parse_url($enterpriseUrl, PHP_URL_HOST); + return $host !== false && str_contains($url, $host); + } + return false; + } + protected function getRepositoryInformation(): void { $url = str_replace('//', '', $this->project->CvsUrl ?? ''); diff --git a/config/cdash.php b/config/cdash.php index 670da91ac7..018976e531 100755 --- a/config/cdash.php +++ b/config/cdash.php @@ -39,6 +39,7 @@ 'delete_old_subprojects' => env('DELETE_OLD_SUBPROJECTS', true), 'github_always_pass' => env('GITHUB_ALWAYS_PASS', false), 'github_app_id' => env('GITHUB_APP_ID', null), + 'github_enterprise_url' => env('GITHUB_ENTERPRISE_URL', null), 'github_private_key' => env('GITHUB_PRIVATE_KEY', null), 'github_webhook_secret' => env('GITHUB_WEBHOOK_SECRET', null), 'large_text_limit' => env('LARGE_TEXT_LIMIT', 0), From e6ddc3a7bc79fdaa71265b16648306c127048f6d Mon Sep 17 00:00:00 2001 From: arhowe00 Date: Tue, 2 Jun 2026 16:05:47 -0400 Subject: [PATCH 02/11] Guard createOrUpdateCheck with try/catch; inspired by getRepositoryService --- app/cdash/app/Model/Repository.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/cdash/app/Model/Repository.php b/app/cdash/app/Model/Repository.php index 3b410a38bb..3f122c03c6 100644 --- a/app/cdash/app/Model/Repository.php +++ b/app/cdash/app/Model/Repository.php @@ -70,7 +70,11 @@ public static function createOrUpdateCheck($sha): void $project = new Project(); $project->Id = $projectid; $project->Fill(); - $repositoryInterface = self::getRepositoryInterface($project); + try { + $repositoryInterface = self::getRepositoryInterface($project); + } catch (Exception $e) { + return; + } $repositoryInterface->createCheck($sha); } From 0f525ed2b3e35e74c1b8313dc0b3d21028e6f8f7 Mon Sep 17 00:00:00 2001 From: arhowe00 Date: Tue, 2 Jun 2026 16:20:18 -0400 Subject: [PATCH 03/11] Fix PHPStan warnings --- app/Utils/RepositoryUtils.php | 20 +++++++++++--------- app/cdash/app/Lib/Repository/GitHub.php | 6 +++--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/Utils/RepositoryUtils.php b/app/Utils/RepositoryUtils.php index 9aa9f092ac..49e1739e83 100644 --- a/app/Utils/RepositoryUtils.php +++ b/app/Utils/RepositoryUtils.php @@ -20,9 +20,9 @@ private static function isGitHubUrl(string $url): bool return true; } $enterpriseUrl = config('cdash.github_enterprise_url'); - if ($enterpriseUrl !== null) { + if (is_string($enterpriseUrl)) { $host = parse_url($enterpriseUrl, PHP_URL_HOST); - return $host !== false && str_contains($url, $host); + return is_string($host) && str_contains($url, $host); } return false; } @@ -160,15 +160,17 @@ public static function post_pull_request_comment($projectid, $pull_request, $com public static function get_github_api_url($github_url): string { $enterpriseUrl = config('cdash.github_enterprise_url'); - if ($enterpriseUrl !== null) { + if (is_string($enterpriseUrl)) { $host = parse_url($enterpriseUrl, PHP_URL_HOST); - if ($host !== false && str_contains($github_url, $host)) { - // For GHE, ...://// becomes ...:///api/v3/repos// + if (is_string($host)) { $idx = strpos($github_url, $host); - $idx2 = $idx + strlen($host) + 1; - $api_url = substr($github_url, 0, $idx) . $host . '/api/v3/repos/'; - $api_url .= substr($github_url, $idx2); - return $api_url; + if ($idx !== false) { + // For GHE, ...://// becomes ...:///api/v3/repos// + $idx2 = $idx + strlen($host) + 1; + $api_url = substr($github_url, 0, $idx) . $host . '/api/v3/repos/'; + $api_url .= substr($github_url, $idx2); + return $api_url; + } } } /* diff --git a/app/cdash/app/Lib/Repository/GitHub.php b/app/cdash/app/Lib/Repository/GitHub.php index 15aef5a85b..df0af20eb2 100644 --- a/app/cdash/app/Lib/Repository/GitHub.php +++ b/app/cdash/app/Lib/Repository/GitHub.php @@ -94,7 +94,7 @@ protected function initializeApiClient(): void { $builder = new GitHubBuilder(); $enterpriseUrl = config('cdash.github_enterprise_url'); - $apiClient = new GitHubClient($builder, null, $enterpriseUrl); + $apiClient = new GitHubClient($builder, null, is_string($enterpriseUrl) ? $enterpriseUrl : null); $this->setApiClient($apiClient); } @@ -669,9 +669,9 @@ private function isGitHubUrl(string $url): bool return true; } $enterpriseUrl = config('cdash.github_enterprise_url'); - if ($enterpriseUrl !== null) { + if (is_string($enterpriseUrl)) { $host = parse_url($enterpriseUrl, PHP_URL_HOST); - return $host !== false && str_contains($url, $host); + return is_string($host) && str_contains($url, $host); } return false; } From 62ea549b0e806d8dba8df2d7e9b54ac1ab4addb2 Mon Sep 17 00:00:00 2001 From: Andrew Howe Date: Wed, 10 Jun 2026 12:35:23 -0400 Subject: [PATCH 04/11] Extract getEnterpriseUrl() helper, treat empty string as null Centralizes config('cdash.github_enterprise_url') access into a single RepositoryUtils::getEnterpriseUrl() method that returns null for both null and empty string values, preventing empty strings from being passed to the GitHub API client constructor. --- app/Utils/RepositoryUtils.php | 14 ++++++++++---- app/cdash/app/Lib/Repository/GitHub.php | 9 +++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/Utils/RepositoryUtils.php b/app/Utils/RepositoryUtils.php index 49e1739e83..aac69280a3 100644 --- a/app/Utils/RepositoryUtils.php +++ b/app/Utils/RepositoryUtils.php @@ -14,13 +14,19 @@ class RepositoryUtils { + public static function getEnterpriseUrl(): ?string + { + $url = config('cdash.github_enterprise_url'); + return is_string($url) && $url !== '' ? $url : null; + } + private static function isGitHubUrl(string $url): bool { if (str_contains($url, 'github.com')) { return true; } - $enterpriseUrl = config('cdash.github_enterprise_url'); - if (is_string($enterpriseUrl)) { + $enterpriseUrl = self::getEnterpriseUrl(); + if ($enterpriseUrl !== null) { $host = parse_url($enterpriseUrl, PHP_URL_HOST); return is_string($host) && str_contains($url, $host); } @@ -159,8 +165,8 @@ public static function post_pull_request_comment($projectid, $pull_request, $com /** Convert GitHub repository viewer URL into corresponding API URL. */ public static function get_github_api_url($github_url): string { - $enterpriseUrl = config('cdash.github_enterprise_url'); - if (is_string($enterpriseUrl)) { + $enterpriseUrl = self::getEnterpriseUrl(); + if ($enterpriseUrl !== null) { $host = parse_url($enterpriseUrl, PHP_URL_HOST); if (is_string($host)) { $idx = strpos($github_url, $host); diff --git a/app/cdash/app/Lib/Repository/GitHub.php b/app/cdash/app/Lib/Repository/GitHub.php index df0af20eb2..d636cf164d 100644 --- a/app/cdash/app/Lib/Repository/GitHub.php +++ b/app/cdash/app/Lib/Repository/GitHub.php @@ -19,6 +19,7 @@ use App\Models\BuildUpdateFile; use App\Models\PendingSubmissions; +use App\Utils\RepositoryUtils; use CDash\Database; use CDash\Model\Build; use CDash\Model\BuildUpdate; @@ -93,8 +94,8 @@ public function setApiClient(GitHubClient $client): void protected function initializeApiClient(): void { $builder = new GitHubBuilder(); - $enterpriseUrl = config('cdash.github_enterprise_url'); - $apiClient = new GitHubClient($builder, null, is_string($enterpriseUrl) ? $enterpriseUrl : null); + $enterpriseUrl = RepositoryUtils::getEnterpriseUrl(); + $apiClient = new GitHubClient($builder, null, $enterpriseUrl); $this->setApiClient($apiClient); } @@ -668,8 +669,8 @@ private function isGitHubUrl(string $url): bool if (str_contains($url, 'github.com')) { return true; } - $enterpriseUrl = config('cdash.github_enterprise_url'); - if (is_string($enterpriseUrl)) { + $enterpriseUrl = RepositoryUtils::getEnterpriseUrl(); + if ($enterpriseUrl !== null) { $host = parse_url($enterpriseUrl, PHP_URL_HOST); return is_string($host) && str_contains($url, $host); } From 708cda9c6691a62a5e650c105b7cd249e32f7b9e Mon Sep 17 00:00:00 2001 From: Andrew Howe Date: Wed, 10 Jun 2026 12:35:43 -0400 Subject: [PATCH 05/11] Remove duplicate isGitHubUrl() from GitHub.php Keep the single copy in RepositoryUtils (now public) and call it from the GitHub class constructor. --- app/Utils/RepositoryUtils.php | 2 +- app/cdash/app/Lib/Repository/GitHub.php | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/app/Utils/RepositoryUtils.php b/app/Utils/RepositoryUtils.php index aac69280a3..bf9c8f41ce 100644 --- a/app/Utils/RepositoryUtils.php +++ b/app/Utils/RepositoryUtils.php @@ -20,7 +20,7 @@ public static function getEnterpriseUrl(): ?string return is_string($url) && $url !== '' ? $url : null; } - private static function isGitHubUrl(string $url): bool + public static function isGitHubUrl(string $url): bool { if (str_contains($url, 'github.com')) { return true; diff --git a/app/cdash/app/Lib/Repository/GitHub.php b/app/cdash/app/Lib/Repository/GitHub.php index d636cf164d..644d5db5e9 100644 --- a/app/cdash/app/Lib/Repository/GitHub.php +++ b/app/cdash/app/Lib/Repository/GitHub.php @@ -77,7 +77,7 @@ public function __construct(Project $project) $repositories = $this->project->GetRepositories(); foreach ($repositories as $repo) { - if ($this->isGitHubUrl($repo['url'])) { + if (RepositoryUtils::isGitHubUrl($repo['url'])) { $this->installationId = $repo['username']; break; } @@ -664,19 +664,6 @@ public function getRepository(): string return $this->repo; } - private function isGitHubUrl(string $url): bool - { - if (str_contains($url, 'github.com')) { - return true; - } - $enterpriseUrl = RepositoryUtils::getEnterpriseUrl(); - if ($enterpriseUrl !== null) { - $host = parse_url($enterpriseUrl, PHP_URL_HOST); - return is_string($host) && str_contains($url, $host); - } - return false; - } - protected function getRepositoryInformation(): void { $url = str_replace('//', '', $this->project->CvsUrl ?? ''); From 272efd1515087b994e693517bff5dc461d453210 Mon Sep 17 00:00:00 2001 From: Andrew Howe Date: Wed, 10 Jun 2026 12:36:00 -0400 Subject: [PATCH 06/11] Use Uri facade instead of parse_url for host extraction - Simplify get_github_api_url with if/else and Str::replaceFirst --- app/Utils/RepositoryUtils.php | 44 +++++++++++++---------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/app/Utils/RepositoryUtils.php b/app/Utils/RepositoryUtils.php index bf9c8f41ce..4abb3fc8d3 100644 --- a/app/Utils/RepositoryUtils.php +++ b/app/Utils/RepositoryUtils.php @@ -10,6 +10,8 @@ use CDash\Model\Project; use CDash\ServiceContainer; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Str; +use Illuminate\Support\Uri; use PDO; class RepositoryUtils @@ -27,7 +29,7 @@ public static function isGitHubUrl(string $url): bool } $enterpriseUrl = self::getEnterpriseUrl(); if ($enterpriseUrl !== null) { - $host = parse_url($enterpriseUrl, PHP_URL_HOST); + $host = Uri::of($enterpriseUrl)->host(); return is_string($host) && str_contains($url, $host); } return false; @@ -162,36 +164,22 @@ public static function post_pull_request_comment($projectid, $pull_request, $com } } - /** Convert GitHub repository viewer URL into corresponding API URL. */ - public static function get_github_api_url($github_url): string + /** + * Convert a GitHub repository viewer URL (e.g. https:////) + * into the corresponding REST API URL. + */ + public static function get_github_api_url(string $github_url): string { $enterpriseUrl = self::getEnterpriseUrl(); - if ($enterpriseUrl !== null) { - $host = parse_url($enterpriseUrl, PHP_URL_HOST); - if (is_string($host)) { - $idx = strpos($github_url, $host); - if ($idx !== false) { - // For GHE, ...://// becomes ...:///api/v3/repos// - $idx2 = $idx + strlen($host) + 1; - $api_url = substr($github_url, 0, $idx) . $host . '/api/v3/repos/'; - $api_url .= substr($github_url, $idx2); - return $api_url; - } - } + $host = $enterpriseUrl !== null ? Uri::of($enterpriseUrl)->host() : null; + + if (is_string($host) && str_contains($github_url, $host)) { + // GHE uses /api/v3/repos/ as the API base + return Str::replaceFirst($host . '/', $host . '/api/v3/repos/', $github_url); + } else { + // GitHub.com uses api.github.com/repos/ as the API base + return Str::replaceFirst('github.com/', 'api.github.com/repos/', $github_url); } - /* - * For a URL of the form: - * ...://github.com// - * We return: - * ...://api.github.com/repos// - */ - $idx1 = strpos($github_url, 'github.com'); - $idx2 = $idx1 + strlen('github.com/'); - $api_url = substr($github_url, 0, $idx2); - $api_url = str_replace('github.com', 'api.github.com', $api_url); - $api_url .= 'repos/'; - $api_url .= substr($github_url, $idx2); - return $api_url; } public static function post_github_pull_request_comment(Project $project, $pull_request, $comment, $cdash_url): void From e0eeff12d8516f935283fccda97e380cc5e3ad0b Mon Sep 17 00:00:00 2001 From: Andrew Howe Date: Tue, 16 Jun 2026 14:09:29 -0400 Subject: [PATCH 07/11] Revert Repository.php try/catch and DoneHandler.php check logic for testing --- app/Http/Submission/Handlers/DoneHandler.php | 7 ++++--- app/cdash/app/Model/Repository.php | 6 +----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/app/Http/Submission/Handlers/DoneHandler.php b/app/Http/Submission/Handlers/DoneHandler.php index 7b2ece70dc..149f790e33 100644 --- a/app/Http/Submission/Handlers/DoneHandler.php +++ b/app/Http/Submission/Handlers/DoneHandler.php @@ -63,9 +63,10 @@ public function endElement($parser, $name): void $this->Build->UpdateBuild($this->Build->Id, -1, -1); $this->Build->MarkAsDone(true); - // Create or update the GitHub check for this commit. - $revision = \App\Models\Build::findOrFail((int) $this->Build->Id)->updateStep->revision ?? ''; - if ($revision !== '') { + // Should we re-run any checks that were previously marked + // as pending? + if ($pendingSubmissionsModel !== null && $pendingSubmissionsModel->recheck) { + $revision = \App\Models\Build::findOrFail((int) $this->Build->Id)->updateStep->revision ?? ''; Repository::createOrUpdateCheck($revision); } diff --git a/app/cdash/app/Model/Repository.php b/app/cdash/app/Model/Repository.php index 3f122c03c6..3b410a38bb 100644 --- a/app/cdash/app/Model/Repository.php +++ b/app/cdash/app/Model/Repository.php @@ -70,11 +70,7 @@ public static function createOrUpdateCheck($sha): void $project = new Project(); $project->Id = $projectid; $project->Fill(); - try { - $repositoryInterface = self::getRepositoryInterface($project); - } catch (Exception $e) { - return; - } + $repositoryInterface = self::getRepositoryInterface($project); $repositoryInterface->createCheck($sha); } From 41518e46683b9403aa23adbf819189530d78e445 Mon Sep 17 00:00:00 2001 From: arhowe00 Date: Wed, 17 Jun 2026 10:20:31 -0400 Subject: [PATCH 08/11] Fix formatting --- app/Utils/RepositoryUtils.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/Utils/RepositoryUtils.php b/app/Utils/RepositoryUtils.php index 4abb3fc8d3..0caad6fb5a 100644 --- a/app/Utils/RepositoryUtils.php +++ b/app/Utils/RepositoryUtils.php @@ -176,10 +176,9 @@ public static function get_github_api_url(string $github_url): string if (is_string($host) && str_contains($github_url, $host)) { // GHE uses /api/v3/repos/ as the API base return Str::replaceFirst($host . '/', $host . '/api/v3/repos/', $github_url); - } else { - // GitHub.com uses api.github.com/repos/ as the API base - return Str::replaceFirst('github.com/', 'api.github.com/repos/', $github_url); } + // GitHub.com uses api.github.com/repos/ as the API base + return Str::replaceFirst('github.com/', 'api.github.com/repos/', $github_url); } public static function post_github_pull_request_comment(Project $project, $pull_request, $comment, $cdash_url): void From 6803aef790e889fffa0118051c47d5bc3a02ed23 Mon Sep 17 00:00:00 2001 From: arhowe00 Date: Wed, 17 Jun 2026 12:57:31 -0400 Subject: [PATCH 09/11] Adjust phpstan baseline --- phpstan-baseline.neon | 140 +++++++++++++++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 28 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 8f26dd0f91..ac2517b4da 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1204,9 +1204,9 @@ parameters: path: app/Http/Controllers/ProjectOverviewController.php - - rawMessage: 'Offset ''loctested'' might not exist on array{}|array{loctested: (array|float|int), locuntested?: (array|float|int)}.' + rawMessage: 'Offset ''loctested'' might not exist on array{}|array{loctested?: (array|float|int), locuntested?: (array|float|int)}.' identifier: offsetAccess.notFound - count: 5 + count: 6 path: app/Http/Controllers/ProjectOverviewController.php - @@ -1222,7 +1222,7 @@ parameters: path: app/Http/Controllers/ProjectOverviewController.php - - rawMessage: 'Offset ''locuntested'' might not exist on array{}|array{loctested: (array|float|int), locuntested?: (array|float|int)}.' + rawMessage: 'Offset ''locuntested'' might not exist on array{}|array{loctested?: (array|float|int), locuntested?: (array|float|int)}.' identifier: offsetAccess.notFound count: 2 path: app/Http/Controllers/ProjectOverviewController.php @@ -1248,7 +1248,7 @@ parameters: - rawMessage: 'Only numeric types are allowed in +, (array|float|int) given on the left side.' identifier: plus.leftNonNumeric - count: 6 + count: 8 path: app/Http/Controllers/ProjectOverviewController.php - @@ -4731,6 +4731,12 @@ parameters: count: 2 path: app/Jobs/ProcessSubmission.php + - + rawMessage: 'Call to deprecated function xml_parser_free().' + identifier: function.deprecated + count: 1 + path: app/Jobs/ProcessSubmission.php + - rawMessage: 'Cannot call method build() on mixed.' identifier: method.nonObject @@ -5178,6 +5184,12 @@ parameters: count: 1 path: app/Utils/RepositoryUtils.php + - + rawMessage: 'Call to deprecated function curl_close().' + identifier: function.deprecated + count: 1 + path: app/Utils/RepositoryUtils.php + - rawMessage: ''' Call to deprecated method executePrepared() of class CDash\Database: @@ -5436,12 +5448,6 @@ parameters: count: 1 path: app/Utils/RepositoryUtils.php - - - rawMessage: 'Method App\Utils\RepositoryUtils::get_github_api_url() has parameter $github_url with no type specified.' - identifier: missingType.parameter - count: 1 - path: app/Utils/RepositoryUtils.php - - rawMessage: 'Method App\Utils\RepositoryUtils::get_github_diff_url() has no return type specified.' identifier: missingType.return @@ -5628,12 +5634,6 @@ parameters: count: 1 path: app/Utils/RepositoryUtils.php - - - rawMessage: 'Only numeric types are allowed in +, int<0, max>|false given on the left side.' - identifier: plus.leftNonNumeric - count: 1 - path: app/Utils/RepositoryUtils.php - - rawMessage: 'Only numeric types are allowed in +, int|false given on the left side.' identifier: plus.leftNonNumeric @@ -7141,23 +7141,71 @@ parameters: path: app/cdash/app/Controller/Api/TestOverview.php - - rawMessage: 'Only booleans are allowed in an if condition, int|string given.' - identifier: if.condNotBoolean + rawMessage: 'Offset ''failed'' might not exist on non-empty-array{failed?: int<0, max>, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' + identifier: offsetAccess.notFound + count: 3 + path: app/cdash/app/Controller/Api/TestOverview.php + + - + rawMessage: 'Offset ''failed'' might not exist on non-empty-array{name?: mixed, subproject?: mixed, passed?: int<0, max>, failed?: int<0, max>, timeout?: int<0, max>, time?: mixed}.' + identifier: offsetAccess.notFound count: 1 path: app/cdash/app/Controller/Api/TestOverview.php - - rawMessage: 'Only numeric types are allowed in +, (array|float|int) given on the left side.' - identifier: plus.leftNonNumeric + rawMessage: 'Offset ''passed'' might not exist on non-empty-array{failed?: int<0, max>, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' + identifier: offsetAccess.notFound count: 1 path: app/cdash/app/Controller/Api/TestOverview.php - - rawMessage: 'Only numeric types are allowed in /, (array|float|int|int<1, max>) given on the right side.' - identifier: div.rightNonNumeric + rawMessage: 'Offset ''passed'' might not exist on non-empty-array{name?: mixed, subproject?: mixed, passed?: int<0, max>, failed?: int<0, max>, timeout?: int<0, max>, time?: mixed}.' + identifier: offsetAccess.notFound + count: 1 + path: app/cdash/app/Controller/Api/TestOverview.php + + - + rawMessage: 'Offset ''subproject'' might not exist on non-empty-array{failed?: int<0, max>, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' + identifier: offsetAccess.notFound + count: 1 + path: app/cdash/app/Controller/Api/TestOverview.php + + - + rawMessage: 'Offset ''time'' might not exist on non-empty-array{failed?: int<0, max>, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' + identifier: offsetAccess.notFound count: 2 path: app/cdash/app/Controller/Api/TestOverview.php + - + rawMessage: 'Offset ''time'' might not exist on non-empty-array{name?: mixed, subproject?: mixed, passed?: int<0, max>, failed?: int<0, max>, timeout?: int<0, max>, time?: mixed}.' + identifier: offsetAccess.notFound + count: 1 + path: app/cdash/app/Controller/Api/TestOverview.php + + - + rawMessage: 'Offset ''timeout'' might not exist on array{failed: 0, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' + identifier: offsetAccess.notFound + count: 1 + path: app/cdash/app/Controller/Api/TestOverview.php + + - + rawMessage: 'Offset ''timeout'' might not exist on non-empty-array{failed?: int<0, max>, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' + identifier: offsetAccess.notFound + count: 2 + path: app/cdash/app/Controller/Api/TestOverview.php + + - + rawMessage: 'Offset ''timeout'' might not exist on non-empty-array{name?: mixed, subproject?: mixed, passed?: int<0, max>, failed?: int<0, max>, timeout?: int<0, max>, time?: mixed}.' + identifier: offsetAccess.notFound + count: 1 + path: app/cdash/app/Controller/Api/TestOverview.php + + - + rawMessage: 'Only booleans are allowed in an if condition, int|string given.' + identifier: if.condNotBoolean + count: 1 + path: app/cdash/app/Controller/Api/TestOverview.php + - rawMessage: Short ternary operator is not allowed. Use null coalesce operator if applicable or consider using long ternary. identifier: ternary.shortNotAllowed @@ -7611,6 +7659,12 @@ parameters: count: 1 path: app/cdash/app/Model/Build.php + - + rawMessage: 'Method CDash\Model\Build::GetErrorDifferences() should return array{builderrorspositive: int, builderrorsnegative: int, buildwarningspositive: int, buildwarningsnegative: int, configureerrors: int, configurewarnings: int, testpassedpositive: int, testpassednegative: int, ...}|false but returns non-empty-array<''builderrorsnegative''|''builderrorspositive''|''buildwarningsnegati…''|''buildwarningspositi…''|''configureerrors''|''configurewarnings''|''testfailednegative''|''testfailedpositive''|''testnotrunnegative''|''testnotrunpositive''|''testpassednegative''|''testpassedpositive'', int>.' + identifier: return.type + count: 1 + path: app/cdash/app/Model/Build.php + - rawMessage: 'Method CDash\Model\Build::GetErrors() has parameter $propertyFilters with no value type specified in iterable type array.' identifier: missingType.iterableValue @@ -7983,12 +8037,6 @@ parameters: count: 1 path: app/cdash/app/Model/BuildConfigure.php - - - rawMessage: If condition is always false. - identifier: if.alwaysFalse - count: 1 - path: app/cdash/app/Model/BuildConfigure.php - - rawMessage: 'Method CDash\Model\BuildConfigure::AddLabel() has parameter $label with no type specified.' identifier: missingType.parameter @@ -13254,6 +13302,12 @@ parameters: count: 2 path: app/cdash/tests/case/CDash/DatabaseTest.php + - + rawMessage: 'Call to deprecated method setAccessible() of class ReflectionProperty.' + identifier: method.deprecated + count: 1 + path: app/cdash/tests/case/CDash/DatabaseTest.php + - rawMessage: 'Call to method PHPUnit\Framework\Assert::assertInstanceOf() with ''CDash\\Database'' and CDash\Database will always evaluate to true.' identifier: method.alreadyNarrowedType @@ -14214,6 +14268,12 @@ parameters: count: 1 path: app/cdash/tests/case/CDash/TestUseCaseTest.php + - + rawMessage: 'Call to deprecated method setAccessible() of class ReflectionProperty.' + identifier: method.deprecated + count: 1 + path: app/cdash/tests/case/CDash/TestUseCaseTest.php + - rawMessage: 'Call to method CDash\Test\UseCase\UseCase::createSubproject() with incorrect case: createSubProject' identifier: method.nameCase @@ -14676,6 +14736,12 @@ parameters: count: 1 path: app/cdash/tests/kwtest/kw_web_tester.php + - + rawMessage: 'Call to deprecated method setAccessible() of class ReflectionProperty.' + identifier: method.deprecated + count: 1 + path: app/cdash/tests/kwtest/kw_web_tester.php + - rawMessage: ''' Call to deprecated method uploadfile() of class KWWebTestCase: @@ -15363,6 +15429,12 @@ parameters: count: 1 path: app/cdash/tests/singletest.php + - + rawMessage: Variable $argv might not be defined. + identifier: variable.undefined + count: 1 + path: app/cdash/tests/singletest.php + - rawMessage: 'Path in require_once() "tests/test_branchcoverage.php" is not a file or it does not exist.' identifier: requireOnce.fileNotFound @@ -15807,6 +15879,12 @@ parameters: count: 1 path: app/cdash/tests/test_attachedfiles.php + - + rawMessage: 'Call to deprecated function curl_close().' + identifier: function.deprecated + count: 1 + path: app/cdash/tests/test_authtoken.php + - rawMessage: ''' Call to deprecated method getConfig() of class GuzzleHttp\Client: @@ -16152,6 +16230,12 @@ parameters: count: 1 path: app/cdash/tests/test_branchcoverage.php + - + rawMessage: 'Call to deprecated function curl_close().' + identifier: function.deprecated + count: 1 + path: app/cdash/tests/test_branchcoverage.php + - rawMessage: ''' Call to deprecated method getPdo() of class CDash\Database: From 860c2eb16d82828625e477ed6d22ccde53591a2f Mon Sep 17 00:00:00 2001 From: arhowe00 Date: Wed, 17 Jun 2026 16:57:12 -0400 Subject: [PATCH 10/11] Fix phpstan-baseline --- phpstan-baseline.neon | 134 +++++++----------------------------------- 1 file changed, 22 insertions(+), 112 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index ac2517b4da..cba973b246 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1204,9 +1204,9 @@ parameters: path: app/Http/Controllers/ProjectOverviewController.php - - rawMessage: 'Offset ''loctested'' might not exist on array{}|array{loctested?: (array|float|int), locuntested?: (array|float|int)}.' + rawMessage: 'Offset ''loctested'' might not exist on array{}|array{loctested: (array|float|int), locuntested?: (array|float|int)}.' identifier: offsetAccess.notFound - count: 6 + count: 5 path: app/Http/Controllers/ProjectOverviewController.php - @@ -1222,7 +1222,7 @@ parameters: path: app/Http/Controllers/ProjectOverviewController.php - - rawMessage: 'Offset ''locuntested'' might not exist on array{}|array{loctested?: (array|float|int), locuntested?: (array|float|int)}.' + rawMessage: 'Offset ''locuntested'' might not exist on array{}|array{loctested: (array|float|int), locuntested?: (array|float|int)}.' identifier: offsetAccess.notFound count: 2 path: app/Http/Controllers/ProjectOverviewController.php @@ -1248,7 +1248,7 @@ parameters: - rawMessage: 'Only numeric types are allowed in +, (array|float|int) given on the left side.' identifier: plus.leftNonNumeric - count: 8 + count: 6 path: app/Http/Controllers/ProjectOverviewController.php - @@ -4731,12 +4731,6 @@ parameters: count: 2 path: app/Jobs/ProcessSubmission.php - - - rawMessage: 'Call to deprecated function xml_parser_free().' - identifier: function.deprecated - count: 1 - path: app/Jobs/ProcessSubmission.php - - rawMessage: 'Cannot call method build() on mixed.' identifier: method.nonObject @@ -5184,12 +5178,6 @@ parameters: count: 1 path: app/Utils/RepositoryUtils.php - - - rawMessage: 'Call to deprecated function curl_close().' - identifier: function.deprecated - count: 1 - path: app/Utils/RepositoryUtils.php - - rawMessage: ''' Call to deprecated method executePrepared() of class CDash\Database: @@ -5634,6 +5622,12 @@ parameters: count: 1 path: app/Utils/RepositoryUtils.php + - + rawMessage: 'Only numeric types are allowed in +, int<0, max>|false given on the left side.' + identifier: plus.leftNonNumeric + count: 1 + path: app/Utils/RepositoryUtils.php + - rawMessage: 'Only numeric types are allowed in +, int|false given on the left side.' identifier: plus.leftNonNumeric @@ -7141,71 +7135,23 @@ parameters: path: app/cdash/app/Controller/Api/TestOverview.php - - rawMessage: 'Offset ''failed'' might not exist on non-empty-array{failed?: int<0, max>, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' - identifier: offsetAccess.notFound - count: 3 - path: app/cdash/app/Controller/Api/TestOverview.php - - - - rawMessage: 'Offset ''failed'' might not exist on non-empty-array{name?: mixed, subproject?: mixed, passed?: int<0, max>, failed?: int<0, max>, timeout?: int<0, max>, time?: mixed}.' - identifier: offsetAccess.notFound - count: 1 - path: app/cdash/app/Controller/Api/TestOverview.php - - - - rawMessage: 'Offset ''passed'' might not exist on non-empty-array{failed?: int<0, max>, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' - identifier: offsetAccess.notFound - count: 1 - path: app/cdash/app/Controller/Api/TestOverview.php - - - - rawMessage: 'Offset ''passed'' might not exist on non-empty-array{name?: mixed, subproject?: mixed, passed?: int<0, max>, failed?: int<0, max>, timeout?: int<0, max>, time?: mixed}.' - identifier: offsetAccess.notFound - count: 1 - path: app/cdash/app/Controller/Api/TestOverview.php - - - - rawMessage: 'Offset ''subproject'' might not exist on non-empty-array{failed?: int<0, max>, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' - identifier: offsetAccess.notFound - count: 1 - path: app/cdash/app/Controller/Api/TestOverview.php - - - - rawMessage: 'Offset ''time'' might not exist on non-empty-array{failed?: int<0, max>, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' - identifier: offsetAccess.notFound - count: 2 - path: app/cdash/app/Controller/Api/TestOverview.php - - - - rawMessage: 'Offset ''time'' might not exist on non-empty-array{name?: mixed, subproject?: mixed, passed?: int<0, max>, failed?: int<0, max>, timeout?: int<0, max>, time?: mixed}.' - identifier: offsetAccess.notFound + rawMessage: 'Only booleans are allowed in an if condition, int|string given.' + identifier: if.condNotBoolean count: 1 path: app/cdash/app/Controller/Api/TestOverview.php - - rawMessage: 'Offset ''timeout'' might not exist on array{failed: 0, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' - identifier: offsetAccess.notFound + rawMessage: 'Only numeric types are allowed in +, (array|float|int) given on the left side.' + identifier: plus.leftNonNumeric count: 1 path: app/cdash/app/Controller/Api/TestOverview.php - - rawMessage: 'Offset ''timeout'' might not exist on non-empty-array{failed?: int<0, max>, timeout?: int<0, max>, time?: mixed, passed?: int<0, max>, name?: mixed, subproject?: mixed}.' - identifier: offsetAccess.notFound + rawMessage: 'Only numeric types are allowed in /, (array|float|int|int<1, max>) given on the right side.' + identifier: div.rightNonNumeric count: 2 path: app/cdash/app/Controller/Api/TestOverview.php - - - rawMessage: 'Offset ''timeout'' might not exist on non-empty-array{name?: mixed, subproject?: mixed, passed?: int<0, max>, failed?: int<0, max>, timeout?: int<0, max>, time?: mixed}.' - identifier: offsetAccess.notFound - count: 1 - path: app/cdash/app/Controller/Api/TestOverview.php - - - - rawMessage: 'Only booleans are allowed in an if condition, int|string given.' - identifier: if.condNotBoolean - count: 1 - path: app/cdash/app/Controller/Api/TestOverview.php - - rawMessage: Short ternary operator is not allowed. Use null coalesce operator if applicable or consider using long ternary. identifier: ternary.shortNotAllowed @@ -7659,12 +7605,6 @@ parameters: count: 1 path: app/cdash/app/Model/Build.php - - - rawMessage: 'Method CDash\Model\Build::GetErrorDifferences() should return array{builderrorspositive: int, builderrorsnegative: int, buildwarningspositive: int, buildwarningsnegative: int, configureerrors: int, configurewarnings: int, testpassedpositive: int, testpassednegative: int, ...}|false but returns non-empty-array<''builderrorsnegative''|''builderrorspositive''|''buildwarningsnegati…''|''buildwarningspositi…''|''configureerrors''|''configurewarnings''|''testfailednegative''|''testfailedpositive''|''testnotrunnegative''|''testnotrunpositive''|''testpassednegative''|''testpassedpositive'', int>.' - identifier: return.type - count: 1 - path: app/cdash/app/Model/Build.php - - rawMessage: 'Method CDash\Model\Build::GetErrors() has parameter $propertyFilters with no value type specified in iterable type array.' identifier: missingType.iterableValue @@ -8037,6 +7977,12 @@ parameters: count: 1 path: app/cdash/app/Model/BuildConfigure.php + - + rawMessage: If condition is always false. + identifier: if.alwaysFalse + count: 1 + path: app/cdash/app/Model/BuildConfigure.php + - rawMessage: 'Method CDash\Model\BuildConfigure::AddLabel() has parameter $label with no type specified.' identifier: missingType.parameter @@ -13302,12 +13248,6 @@ parameters: count: 2 path: app/cdash/tests/case/CDash/DatabaseTest.php - - - rawMessage: 'Call to deprecated method setAccessible() of class ReflectionProperty.' - identifier: method.deprecated - count: 1 - path: app/cdash/tests/case/CDash/DatabaseTest.php - - rawMessage: 'Call to method PHPUnit\Framework\Assert::assertInstanceOf() with ''CDash\\Database'' and CDash\Database will always evaluate to true.' identifier: method.alreadyNarrowedType @@ -14268,12 +14208,6 @@ parameters: count: 1 path: app/cdash/tests/case/CDash/TestUseCaseTest.php - - - rawMessage: 'Call to deprecated method setAccessible() of class ReflectionProperty.' - identifier: method.deprecated - count: 1 - path: app/cdash/tests/case/CDash/TestUseCaseTest.php - - rawMessage: 'Call to method CDash\Test\UseCase\UseCase::createSubproject() with incorrect case: createSubProject' identifier: method.nameCase @@ -14736,12 +14670,6 @@ parameters: count: 1 path: app/cdash/tests/kwtest/kw_web_tester.php - - - rawMessage: 'Call to deprecated method setAccessible() of class ReflectionProperty.' - identifier: method.deprecated - count: 1 - path: app/cdash/tests/kwtest/kw_web_tester.php - - rawMessage: ''' Call to deprecated method uploadfile() of class KWWebTestCase: @@ -15429,12 +15357,6 @@ parameters: count: 1 path: app/cdash/tests/singletest.php - - - rawMessage: Variable $argv might not be defined. - identifier: variable.undefined - count: 1 - path: app/cdash/tests/singletest.php - - rawMessage: 'Path in require_once() "tests/test_branchcoverage.php" is not a file or it does not exist.' identifier: requireOnce.fileNotFound @@ -15879,12 +15801,6 @@ parameters: count: 1 path: app/cdash/tests/test_attachedfiles.php - - - rawMessage: 'Call to deprecated function curl_close().' - identifier: function.deprecated - count: 1 - path: app/cdash/tests/test_authtoken.php - - rawMessage: ''' Call to deprecated method getConfig() of class GuzzleHttp\Client: @@ -16230,12 +16146,6 @@ parameters: count: 1 path: app/cdash/tests/test_branchcoverage.php - - - rawMessage: 'Call to deprecated function curl_close().' - identifier: function.deprecated - count: 1 - path: app/cdash/tests/test_branchcoverage.php - - rawMessage: ''' Call to deprecated method getPdo() of class CDash\Database: From 0f631bba6a97b157e8c2e08b6e0db0f5a7b57950 Mon Sep 17 00:00:00 2001 From: William Allen Date: Wed, 17 Jun 2026 20:18:14 -0400 Subject: [PATCH 11/11] Regenerate PHPStan baseline --- phpstan-baseline.neon | 6 ------ 1 file changed, 6 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index cba973b246..629adc160b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -5622,12 +5622,6 @@ parameters: count: 1 path: app/Utils/RepositoryUtils.php - - - rawMessage: 'Only numeric types are allowed in +, int<0, max>|false given on the left side.' - identifier: plus.leftNonNumeric - count: 1 - path: app/Utils/RepositoryUtils.php - - rawMessage: 'Only numeric types are allowed in +, int|false given on the left side.' identifier: plus.leftNonNumeric