Installation Run in your Symfony project root:
composer require common-gateway/github-bundle:dev-main
For Dockerized environments:
docker-compose exec php composer require common-gateway/github-bundle:dev-main
Install Entities & Schemas Execute the bundle’s installation command:
php bin/console commongateway:install common-gateway/github-bundle
This generates Doctrine entities and database migrations for GitHub issue CRUD operations.
First Use Case: Fetching Issues
Inject the CommonGateway\GithubBundle\Service\GithubService into a controller or command:
use CommonGateway\GithubBundle\Service\GithubService;
class IssueController extends AbstractController
{
public function __construct(private GithubService $githubService) {}
public function listIssues(): Response
{
$issues = $this->githubService->getIssues('owner', 'repo');
return $this->render('issues/index.html.twig', ['issues' => $issues]);
}
}
Configuration
Add GitHub credentials to .env:
GITHUB_TOKEN=your_github_personal_access_token
GITHUB_API_URL=https://api.github.com
CRUD Operations The bundle abstracts GitHub API interactions for issues:
$this->githubService->getIssues('symfony', 'symfony');
$this->githubService->createIssue('symfony', 'symfony', [
'title' => 'Bug Report',
'body' => 'Description...',
]);
updateIssue() and deleteIssue() with issue IDs.Event-Driven Integrations
Extend the bundle’s event system to trigger actions on issue events (e.g., IssueOpenedEvent):
// config/services.yaml
CommonGateway\GithubBundle\EventListener\IssueListener:
tags:
- { name: kernel.event_listener, event: issue.opened, method: onIssueOpened }
Doctrine Integration
The bundle generates entities for issues (e.g., Issue, Comment). Use them in repositories:
$repository = $this->getDoctrine()->getRepository(Issue::class);
$openIssues = $repository->findBy(['state' => 'open']);
API Rate Limiting Handle GitHub API rate limits via middleware or the bundle’s built-in retry logic:
$this->githubService->setRetryLimit(3); // Retry failed requests 3 times
$form = $this->createFormBuilder($issue)
->add('title', TextType::class)
->add('body', TextareaType::class)
->getForm();
issues Twig extension to render issue lists:
{% for issue in issues %}
<h3>{{ issue.title }}</h3>
<p>{{ issue.body|truncate(100) }}</p>
{% endfor %}
php bin/console app:sync-github-issues owner repo
Authentication
repo scope. Without it, API calls fail silently..env and test with:
$this->githubService->getRateLimit(); // Throws exception if token is invalid
Rate Limits
GithubService::setCache() method if available.Entity Mismatches
Issue entity may not map 1:1 to GitHub’s API. Fields like labels or assignees might require custom serialization.// src/Entity/Issue.php
use CommonGateway\GithubBundle\Entity\BaseIssue;
class Issue extends BaseIssue {
public function __construct() {
$this->labels = new ArrayCollection();
}
}
Database Schema
commongateway:install overwrites existing entities if they conflict. Backup your database first.--dry-run flag to preview changes:
php bin/console doctrine:schema:update --dry-run
Enable API Debugging
Add this to config/packages/dev/github_bundle.yaml:
github_bundle:
debug: true
Logs API requests/responses to var/log/dev.log.
Common Errors
repo scope and the user has access to the repo.Custom API Endpoints
Extend GithubService to support non-issue endpoints (e.g., pull requests):
// src/Service/ExtendedGithubService.php
class ExtendedGithubService extends GithubService {
public function getPullRequests(string $owner, string $repo): array {
return $this->client->getCollection('repo/pulls', [
'owner' => $owner,
'repo' => $repo,
]);
}
}
Webhook Listeners
Add a listener for GitHub webhooks (requires symfony/http-client):
// src/EventListener/GithubWebhookListener.php
class GithubWebhookListener {
public function onWebhook(Request $request, GithubService $githubService) {
$payload = json_decode($request->getContent(), true);
if ($payload['action'] === 'opened') {
$githubService->createComment($payload['issue']['number'], 'Auto-comment!');
}
}
}
Testing
Mock GithubService in tests:
$mockService = $this->createMock(GithubService::class);
$mockService->method('getIssues')->willReturn([$mockIssue]);
$this->container->set(GithubService::class, $mockService);
How can I help you explore Laravel packages today?