-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add Checks API, file contents, and Laravel 13 support #119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| parameters: | ||
| ignoreErrors: | ||
| - | ||
| message: "#^Instantiated class JordanPartridge\\\\GithubClient\\\\Exceptions\\\\ResourceNotFoundException not found\\.$#" | ||
| count: 1 | ||
| path: src/Connectors/GithubConnector.php | ||
|
Comment on lines
+3
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Search for ResourceNotFoundException class definition
rg -n 'class ResourceNotFoundException' --type phpRepository: jordanpartridge/github-client Length of output: 55 Do not suppress instantiation of non-existent The baseline suppresses a fatal error: "Instantiated class Fix by either creating the 🤖 Prompt for AI Agents |
||
|
|
||
| - | ||
| message: "#^Missing parameter \\$message \\(string\\) in call to JordanPartridge\\\\GithubClient\\\\Exceptions\\\\NetworkException constructor\\.$#" | ||
| count: 1 | ||
| path: src/Connectors/GithubConnector.php | ||
|
Comment on lines
+8
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Find NetworkException constructor calls with 'reason:' parameter
rg -n -A3 'new NetworkException\(' src/Connectors/GithubConnector.phpRepository: jordanpartridge/github-client Length of output: 301 🏁 Script executed: #!/bin/bash
# Find NetworkException class definition
find . -name "*.php" -type f | xargs grep -l "class NetworkException"Repository: jordanpartridge/github-client Length of output: 110 🏁 Script executed: #!/bin/bash
# Check the constructor of NetworkException
rg -A10 "class NetworkException" --type phpRepository: jordanpartridge/github-client Length of output: 750 🏁 Script executed: #!/bin/bash
# Find all NetworkException constructor calls
rg -n "new NetworkException\(" --type php -A4Repository: jordanpartridge/github-client Length of output: 1114 Critical: Fix mismatched parameter name instead of suppressing the error. Lines 8-11 and 18-21 in phpstan-baseline.neon suppress errors about incorrect public function __construct(
string $operation,
string $message,
int $code = 0,
?\Throwable $previous = null,
)However, new NetworkException(
operation: 'GitHub API request',
reason: "Server error ({$status}): {$message}", // ✗ wrong parameter name
previous: $senderException,
)This will cause a fatal TypeError at runtime: unknown parameter Fix in GithubConnector.php: Corrected code new NetworkException(
operation: 'GitHub API request',
- reason: "Server error ({$status}): {$message}",
+ message: "Server error ({$status}): {$message}",
previous: $senderException,
)🤖 Prompt for AI Agents |
||
|
|
||
| - | ||
| message: "#^Strict comparison using \\=\\=\\= between non\\-falsy\\-string and '' will always evaluate to false\\.$#" | ||
| count: 1 | ||
| path: src/Connectors/GithubConnector.php | ||
|
Comment on lines
+13
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Verify if the redundant empty string check is intentional. The baseline suppresses PHPStan's warning about if (! $this->token || $this->token === '')The empty string case is already covered by Options:
♻️ Suggested simplification-if (! $this->token || $this->token === '') {
+if (! $this->token) {
return null;
}Then remove lines 13-16 from this baseline file. 🤖 Prompt for AI Agents |
||
|
|
||
| - | ||
| message: "#^Unknown parameter \\$reason in call to JordanPartridge\\\\GithubClient\\\\Exceptions\\\\NetworkException constructor\\.$#" | ||
| count: 1 | ||
| path: src/Connectors/GithubConnector.php | ||
|
Comment on lines
+1
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reconsider using a baseline for actual bugs. PHPStan baselines are designed for:
However, this baseline suppresses 3 critical bugs that will cause runtime failures:
These should be fixed immediately, not suppressed. Baseline files hide issues from static analysis, giving false confidence that the code is correct. Recommendation: Fix the critical bugs first, then decide if any remaining suppressions (like the redundant comparison) warrant a baseline entry. Would you like me to open a separate issue to track fixing these bugs? 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
| use JordanPartridge\GithubClient\Exceptions\NetworkException; | ||
| use JordanPartridge\GithubClient\Requests\RateLimit\Get; | ||
| use JordanPartridge\GithubClient\Resources\ActionsResource; | ||
| use JordanPartridge\GithubClient\Resources\ChecksResource; | ||
| use JordanPartridge\GithubClient\Resources\CommentsResource; | ||
| use JordanPartridge\GithubClient\Resources\CommitResource; | ||
| use JordanPartridge\GithubClient\Resources\FileResource; | ||
|
|
@@ -57,6 +58,11 @@ public function actions(): ActionsResource | |
| return new ActionsResource($this); | ||
| } | ||
|
|
||
| public function checks(): ChecksResource | ||
| { | ||
| return new ChecksResource($this); | ||
| } | ||
|
Comment on lines
+61
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check current facade annotations and verify checks() is missing
echo "=== Current facade annotations ==="
rg -A 10 '@method' src/Facades/Github.php
echo ""
echo "=== Checking if checks() annotation exists ==="
rg 'checks\(\)' src/Facades/Github.php || echo "checks() annotation NOT found - needs to be added"Repository: jordanpartridge/github-client Length of output: 932 Add missing The new Add this annotation with the other `@method` static \JordanPartridge\GithubClient\Resources\ChecksResource checks()🤖 Prompt for AI Agents |
||
|
|
||
| public function issues(): IssuesResource | ||
| { | ||
| return new IssuesResource($this); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| <?php | ||
|
|
||
| namespace JordanPartridge\GithubClient\Requests\Checks; | ||
|
|
||
| use Saloon\Enums\Method; | ||
| use Saloon\Http\Request; | ||
|
|
||
| class GetCheckRunsForRef extends Request | ||
| { | ||
| protected Method $method = Method::GET; | ||
|
|
||
| public function __construct( | ||
| protected string $owner, | ||
| protected string $repo, | ||
| protected string $ref, | ||
| protected ?int $perPage = null, | ||
| protected ?int $page = null, | ||
| ) {} | ||
|
|
||
| public function resolveEndpoint(): string | ||
| { | ||
| return "/repos/{$this->owner}/{$this->repo}/commits/{$this->ref}/check-runs"; | ||
| } | ||
|
|
||
| protected function defaultQuery(): array | ||
| { | ||
| return array_filter([ | ||
| 'per_page' => $this->perPage, | ||
| 'page' => $this->page, | ||
| ], fn ($value) => $value !== null); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| <?php | ||
|
|
||
| namespace JordanPartridge\GithubClient\Requests\Checks; | ||
|
|
||
| use Saloon\Enums\Method; | ||
| use Saloon\Http\Request; | ||
|
|
||
| class GetCombinedStatus extends Request | ||
| { | ||
| protected Method $method = Method::GET; | ||
|
|
||
| public function __construct( | ||
| protected string $owner, | ||
| protected string $repo, | ||
| protected string $ref, | ||
| ) {} | ||
|
|
||
| public function resolveEndpoint(): string | ||
| { | ||
| return "/repos/{$this->owner}/{$this->repo}/commits/{$this->ref}/status"; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| <?php | ||
|
|
||
| namespace JordanPartridge\GithubClient\Requests\Files; | ||
|
|
||
| use Saloon\Enums\Method; | ||
| use Saloon\Http\Request; | ||
|
|
||
| class GetContents extends Request | ||
| { | ||
| protected Method $method = Method::GET; | ||
|
|
||
| public function __construct( | ||
| protected string $owner, | ||
| protected string $repo, | ||
| protected string $path, | ||
| protected ?string $ref = null, | ||
| ) {} | ||
|
|
||
| public function resolveEndpoint(): string | ||
| { | ||
| return "/repos/{$this->owner}/{$this->repo}/contents/{$this->path}"; | ||
| } | ||
|
|
||
| protected function defaultQuery(): array | ||
| { | ||
| return array_filter([ | ||
| 'ref' => $this->ref, | ||
| ], fn ($value) => $value !== null); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,63 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <?php | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| namespace JordanPartridge\GithubClient\Resources; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use JordanPartridge\GithubClient\Requests\Checks\GetCheckRunsForRef; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use JordanPartridge\GithubClient\Requests\Checks\GetCombinedStatus; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| readonly class ChecksResource extends BaseResource | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Get check runs for a commit reference (SHA, branch, or tag). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @return array{total_count: int, check_runs: array<int, array<string, mixed>>} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public function forRef(string $owner, string $repo, string $ref): array | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $response = $this->github()->connector()->send( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new GetCheckRunsForRef($owner, $repo, $ref), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return $response->json(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Get the combined commit status for a reference. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Returns the overall state (success, failure, pending) and individual statuses. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @return array{state: string, statuses: array<int, array<string, mixed>>, total_count: int} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public function combinedStatus(string $owner, string $repo, string $ref): array | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $response = $this->github()->connector()->send( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new GetCombinedStatus($owner, $repo, $ref), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return $response->json(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Check if all checks pass for a given ref. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public function allPassing(string $owner, string $repo, string $ref): bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $checkRuns = $this->forRef($owner, $repo, $ref); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (empty($checkRuns['check_runs'])) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| foreach ($checkRuns['check_runs'] as $run) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ($run['status'] !== 'completed') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ($run['conclusion'] !== 'success' && $run['conclusion'] !== 'skipped') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+43
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pagination gap may cause false positives when many check runs exist.
Consider either:
🐛 Option 1: Detect pagination truncation and throw public function allPassing(string $owner, string $repo, string $ref): bool
{
$checkRuns = $this->forRef($owner, $repo, $ref);
+ // Guard against incomplete results due to pagination
+ if ($checkRuns['total_count'] > count($checkRuns['check_runs'])) {
+ throw new \RuntimeException(
+ "Check runs response is paginated ({$checkRuns['total_count']} total, " .
+ count($checkRuns['check_runs']) . " returned). Cannot reliably determine all passing."
+ );
+ }
+
if (empty($checkRuns['check_runs'])) {
return true;
}🐛 Option 2: Fetch all pages (more complete solution) public function allPassing(string $owner, string $repo, string $ref): bool
{
- $checkRuns = $this->forRef($owner, $repo, $ref);
-
- if (empty($checkRuns['check_runs'])) {
- return true;
- }
+ $page = 1;
+ $perPage = 100; // Max allowed by GitHub API
+
+ do {
+ $response = $this->forRef($owner, $repo, $ref, $perPage, $page);
+ $checkRuns = $response['check_runs'];
+
+ foreach ($checkRuns as $run) {
+ if ($run['status'] !== 'completed') {
+ return false;
+ }
+
+ if ($run['conclusion'] !== 'success' && $run['conclusion'] !== 'skipped') {
+ return false;
+ }
+ }
+
+ $page++;
+ $hasMore = count($checkRuns) === $perPage;
+ } while ($hasMore);
- foreach ($checkRuns['check_runs'] as $run) {
- if ($run['status'] !== 'completed') {
- return false;
- }
-
- if ($run['conclusion'] !== 'success' && $run['conclusion'] !== 'skipped') {
- return false;
- }
- }
-
return true;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| namespace JordanPartridge\GithubClient\Resources; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use InvalidArgumentException; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use JordanPartridge\GithubClient\Requests\Files\GetContents; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use JordanPartridge\GithubClient\Requests\Files\Index; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use JordanPartridge\GithubClient\ValueObjects\Repo; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use Saloon\Http\Response; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -19,4 +20,32 @@ public function all(string $repo_name, string $commit_sha): Response | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return $this->github()->connector()->send(new Index($repo->fullName(), $commit_sha)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Get the contents of a file at a specific ref (branch, tag, or SHA). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @return array{name: string, path: string, sha: string, size: int, content: string, encoding: string} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public function contents(string $owner, string $repo, string $path, ?string $ref = null): array | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $response = $this->github()->connector()->send( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new GetContents($owner, $repo, $path, $ref), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return $response->json(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Get the decoded contents of a file at a specific ref. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public function getContent(string $owner, string $repo, string $path, ?string $ref = null): string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $data = $this->contents($owner, $repo, $path, $ref); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ($data['encoding'] === 'base64') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return base64_decode($data['content']); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return $data['content']; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+41
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential runtime errors in Several edge cases could cause issues:
🛡️ Proposed fix with defensive checks public function getContent(string $owner, string $repo, string $path, ?string $ref = null): string
{
$data = $this->contents($owner, $repo, $path, $ref);
+ if (!isset($data['content'], $data['encoding'])) {
+ throw new \RuntimeException('Path does not point to a file or content is unavailable');
+ }
+
if ($data['encoding'] === 'base64') {
- return base64_decode($data['content']);
+ $decoded = base64_decode($data['content'], true);
+ if ($decoded === false) {
+ throw new \RuntimeException('Failed to decode base64 content');
+ }
+ return $decoded;
}
return $data['content'];
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
What version of orchestra/testbench is compatible with Laravel 13 (illuminate/* v13), and do spatie/laravel-package-tools v1.16 or v2.0 officially support Laravel 13?💡 Result:
Laravel 13 (illuminate/ v13) + orchestra/testbench:* use orchestra/testbench
^11.0(11.x) — it requireslaravel/framework ^13.0.0. [1](Testbench Core is also on 11.x for Laravel 13.) [2]
spatie/laravel-package-tools v1.16.x: does not officially support Laravel 13 —
1.16.0only allowsilluminate/contracts ^9.28|^10.0[3] and1.16.6only up to^11.0. [4]spatie/laravel-package-tools v2.0: there is no 2.x release on Packagist (current releases are 1.x; e.g. latest shown is
1.93.0). [5]If you need Laravel 13 support,
spatie/laravel-package-tools 1.93.0explicitly supportsilluminate/contracts ^13.0. [6]Sources: [1] (packagist.org) [2] (packagist.org) [3] (packages.ecosyste.ms) [4] (packages.ecosyste.ms) [5] (packages.ecosyste.ms) [6] (packagist.org)
Citations:
🏁 Script executed:
Repository: jordanpartridge/github-client
Length of output: 3286
Update orchestra/testbench and spatie/laravel-package-tools to properly support Laravel 13.
Line 31 claims support for
illuminate/contracts ^13.0, but the dev and runtime dependency constraints are incomplete:^8.0||^9.0||^10.0||^11.0||^12.0— testbench 12.x is incompatible with Laravel 13. Add^13.0to the constraint.^1.16|^2.0— versions 1.16.0 through 1.92.x do not support Laravel 13 (only 1.93.0+). Tighten to^1.93|^2.0(noting that 2.x does not yet exist on Packagist, so effectively^1.93.0).🤖 Prompt for AI Agents