GitHub

Table of contents

About

The GitHub class provides a typed, error-aware interface for the most common GitHub REST API v3 operations. It uses the Request class internally and follows the same conventions as the other Pancake API clients.

A companion GitHubAppCredentials value object carries GitHub App installation credentials when app-based authentication is required.

Requirements

  • libcurl must be enabled in your PHP configuration.
  • An internet connection or access to a GitHub Enterprise Server instance.
  • A personal access token or GitHub App installation token for endpoints that require authentication.

Authentication

Unauthenticated (public endpoints)

use GuiBranco\Pancake\GitHub;

$client = new GitHub();
$response = $client->getRateLimit();
echo $response->getBody();

User token

Pass a personal access token (classic or fine-grained) or OAuth token as the first constructor argument.

$client = new GitHub('ghp_yourPersonalAccessToken');
$response = $client->getAuthenticatedUser();
$user = $response->getBodyAsJson();
echo $user->login;

GitHub App installation token

Use GitHubAppCredentials to wrap the numeric app ID and the installation access token you obtained from the GitHub Apps API.

use GuiBranco\Pancake\GitHub;
use GuiBranco\Pancake\GitHubAppCredentials;

$creds  = new GitHubAppCredentials(123456, 'ghs_yourInstallationToken');
$client = new GitHub(null, $creds);

$response = $client->getRepository('my-org', 'my-repo');
$repo = $response->getBodyAsJson();
echo $repo->full_name;

Both credentials at once

When both a user token and app credentials are supplied, the client uses the user token by default. The app token acts as a fallback when no user token is present.

$creds  = new GitHubAppCredentials(123456, 'ghs_installationToken');
$client = new GitHub('ghp_userToken', $creds);

Error handling

All methods return ?Response. The precise behaviour when a request fails is controlled by constructor options.

Silent mode (default)

Failed requests return null. No exception is thrown.

$client = new GitHub('ghp_token');
$response = $client->getIssue('owner', 'repo', 99999);

if ($response === null) {
    echo 'Issue not found or request failed.';
}

Throw mode

Pass true as the fourth constructor argument ($throwOnError) to throw a RequestException whenever a request returns a non-2xx status code or a network error occurs.

use GuiBranco\Pancake\RequestException;

$client = new GitHub('ghp_token', null, null, true);

try {
    $response = $client->getIssue('owner', 'repo', 99999);
} catch (RequestException $e) {
    echo 'Error ' . $e->getCode() . ': ' . $e->getMessage();
}

Ignored status codes

Pass an array of HTTP status codes (or -1 for cURL errors) as the fifth argument. Matching responses return null silently — no log entry, no exception — even when throw mode is active.

// Treat "not found" responses as an expected absence, not an error.
$client = new GitHub('ghp_token', null, null, false, [404]);
$response = $client->getIssue('owner', 'repo', 99999);
// $response is null; no exception, no log entry.

Logging errors

Supply any object implementing ILogger as the third argument. The logger receives a structured object with statusCode, message, url, and body fields whenever a non-ignored error occurs (and throw mode is off).

use GuiBranco\Pancake\Logger;

$logger = new Logger($loggerUrl, $apiKey, $apiToken);
$client = new GitHub('ghp_token', null, $logger);

// Errors are forwarded to the logger automatically.
$client->getRepository('owner', 'nonexistent-repo');

Available methods

Rate limit

$response = $client->getRateLimit();
$data = $response->getBodyAsJson();
echo $data->resources->core->remaining;

Users

// Public user profile
$response = $client->getUser('octocat');
$user = $response->getBodyAsJson();
echo $user->name;

// Authenticated user (requires token)
$response = $client->getAuthenticatedUser();
$user = $response->getBodyAsJson();
echo $user->login;

Repositories

// Single repository
$response = $client->getRepository('octocat', 'Hello-World');

// Public repositories for a user
$response = $client->listUserRepositories('octocat', ['per_page' => 10]);

// Repositories accessible to the authenticated user
$response = $client->listAuthenticatedUserRepositories(['visibility' => 'private']);

Issues

// Fetch a single issue
$response = $client->getIssue('owner', 'repo', 42);

// List issues with optional filters
$response = $client->listIssues('owner', 'repo', [
    'state'    => 'open',
    'per_page' => 50,
]);

// Create an issue
$response = $client->createIssue('owner', 'repo', [
    'title'     => 'Something is broken',
    'body'      => 'Steps to reproduce ...',
    'labels'    => ['bug'],
    'assignees' => ['octocat'],
]);

// Update an issue (e.g. close it)
$response = $client->updateIssue('owner', 'repo', 42, [
    'state' => 'closed',
]);

Pull requests

// Fetch a single pull request
$response = $client->getPullRequest('owner', 'repo', 7);

// List pull requests
$response = $client->listPullRequests('owner', 'repo', [
    'state'    => 'open',
    'per_page' => 20,
]);

Releases

// List releases
$response = $client->listReleases('owner', 'repo', ['per_page' => 5]);

// Latest published release
$response = $client->getLatestRelease('owner', 'repo');
$release  = $response->getBodyAsJson();
echo $release->tag_name;

Repository contents

// File or directory at the default branch
$response = $client->getContents('owner', 'repo', 'src/GitHub.php');

// File at a specific branch or tag
$response = $client->getContents('owner', 'repo', 'README.md', 'develop');

$file    = $response->getBodyAsJson();
$decoded = base64_decode($file->content);