Initialize git-contribution-graph project with Docker setup, environment configuration, and core functionality for merging contributions from GitHub, GitLab, and Gitea into an SVG heatmap.

This commit is contained in:
2026-05-28 19:35:44 +02:00
commit 342490035b
17 changed files with 881 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
<?php
namespace App\Service;
use Symfony\Contracts\HttpClient\HttpClientInterface;
/**
* Fetches the last 365 days of contributions from the GitHub GraphQL API.
*
* Required token scopes: read:user
*/
class GitHubProvider
{
private const GRAPHQL_URL = 'https://api.github.com/graphql';
private const QUERY = <<<'GRAPHQL'
query($username: String!, $from: DateTime!, $to: DateTime!) {
user(login: $username) {
contributionsCollection(from: $from, to: $to) {
contributionCalendar {
weeks {
contributionDays {
date
contributionCount
}
}
}
}
}
}
GRAPHQL;
public function __construct(private readonly HttpClientInterface $client) {}
/**
* @return array<string, int> date (Y-m-d) => contribution count
*/
public function fetch(string $username, string $token): array
{
$from = (new \DateTimeImmutable('-365 days'))->format('Y-m-d\T00:00:00\Z');
$to = (new \DateTimeImmutable())->format('Y-m-d\T23:59:59\Z');
$response = $this->client->request('POST', self::GRAPHQL_URL, [
'headers' => [
'Authorization' => "Bearer $token",
'Content-Type' => 'application/json',
],
'json' => [
'query' => self::QUERY,
'variables' => ['username' => $username, 'from' => $from, 'to' => $to],
],
]);
$data = $response->toArray();
if (isset($data['errors'])) {
throw new \RuntimeException('GitHub GraphQL error: ' . json_encode($data['errors']));
}
$result = [];
$weeks = $data['data']['user']['contributionsCollection']['contributionCalendar']['weeks'] ?? [];
foreach ($weeks as $week) {
foreach ($week['contributionDays'] as $day) {
if ($day['contributionCount'] > 0) {
$result[$day['date']] = $day['contributionCount'];
}
}
}
return $result;
}
}