Skip to content

Commit 114e27f

Browse files
add getting started and features sections to README
1 parent 22078bd commit 114e27f

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed

README.md

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,194 @@
9797
9898
## Getting Started
9999
100+
django-github-app provides a router-based system for handling GitHub webhook events, built on top of [gidgethub](https://github.com/gidgethub/gidgethub). The router matches incoming webhooks to your handler functions based on the event type and optional action.
101+
102+
Each handler receives two key arguments:
103+
104+
- `event`: A `gidgethub.sansio.Event` containing the webhook payload
105+
- `gh`: A `gidgethub.abc.GitHubAPI` instance for making API calls
106+
107+
<add note about `django_github_app.github.AsyncGitHubAPI` which is what actually is passed as `gh`. it's an opinionated implementation of the abstract GitHubAPI provided by gidgethub and uses httpx as it's client>
108+
109+
Here's an example:
110+
111+
```python
112+
from django_github_app.routing import Router
113+
114+
gh = Router()
115+
116+
# Handle any issue event
117+
@gh.event("issues")
118+
async def handle_issue(event, gh, *args, **kwargs):
119+
issue = event.data["issue"]
120+
labels = []
121+
122+
# Add labels based on issue title
123+
title = issue["title"].lower()
124+
if "bug" in title:
125+
labels.append("bug")
126+
if "feature" in title:
127+
labels.append("enhancement")
128+
129+
if labels:
130+
await gh.post(
131+
issue["labels_url"],
132+
data=labels
133+
)
134+
135+
# Handle specific issue actions
136+
@gh.event("issues", action="opened")
137+
async def welcome_new_issue(event, gh, *args, **kwargs):
138+
"""Post a comment when a new issue is opened"""
139+
url = event.data["issue"]["comments_url"]
140+
await gh.post(url, data={
141+
"body": "Thanks for opening an issue! We'll take a look soon."
142+
})
143+
```
144+
145+
In this example, we automatically label issues based on their title and post a welcome comment on newly opened issues. The router ensures each webhook is directed to the appropriate handler based on the event type and action.
146+
147+
> [!NOTE]
148+
> Handlers must be async functions as django-github-app uses gidgethub for webhook event routing which only supports async operations. Sync support is planned to better integrate with Django projects that don't use async.
149+
150+
For more information about GitHub webhook events and payloads, see:
151+
152+
- [Webhook events and payloads](https://docs.github.com/en/webhooks/webhook-events-and-payloads)
153+
- [About webhooks](https://docs.github.com/en/webhooks/about-webhooks)
154+
155+
## Features
156+
157+
### GitHub API Client
158+
159+
The library provides `AsyncGitHubAPI`, an implementation of gidgethub's abstract `GitHubAPI` class that handles authentication and uses [httpx](https://github.com/encode/httpx) as its HTTP client. While it's automatically provided in webhook handlers, you can also use it directly in your code:
160+
161+
```python
162+
from django_github_app.github import AsyncGitHubAPI
163+
from django_github_app.models import Installation
164+
165+
# Access public endpoints without authentication
166+
async def get_public_repo():
167+
async with AsyncGitHubAPI() as gh:
168+
return await gh.getitem("/repos/django/django")
169+
170+
# Interact as the GitHub App installation
171+
async def create_comment(repo_full_name: str):
172+
# Get the installation for the repository
173+
installation = await Installation.objects.aget(repositories__full_name=repo_full_name)
174+
175+
async with AsyncGitHubAPI(installation_id=installation.installation_id) as gh:
176+
await gh.post(
177+
f"/repos/{repo_full_name}/issues/1/comments",
178+
data={"body": "Hello!"}
179+
)
180+
```
181+
182+
The client automatically handles authentication and token refresh when an installation ID is provided. The installation ID is GitHub's identifier for where your app is installed, which you can get from the `installation_id` field on the `Installation` model.
183+
184+
### Models
185+
186+
#### `EventLog`
187+
188+
Stores incoming webhook events with their payload and timestamp. Includes automatic cleanup of old events based on the `DAYS_TO_KEEP_EVENTS` setting via a `EventLog.objects.acleanup_events` manager method.
189+
190+
#### `Installation`
191+
192+
Represents where your GitHub App is installed. Stores the installation ID and metadata from GitHub, and provides methods for authentication:
193+
194+
```python
195+
from django_github_app.models import Installation
196+
197+
# Get an installation and its access token
198+
installation = await Installation.objects.aget(repositories__full_name="owner/repo")
199+
async with AsyncGitHubAPI(installation_id=installation.installation_id) as gh:
200+
# Do something as the installation
201+
```
202+
203+
#### `Repository`
204+
205+
Represents repositories where your app is installed. Provides convenience methods for common GitHub operations:
206+
207+
```python
208+
from django_github_app.models import Repository
209+
210+
# Get issues for a repository
211+
repo = await Repository.objects.aget(full_name="owner/repo")
212+
issues = await repo.aget_issues()
213+
```
214+
215+
All models provide both async and sync versions of their methods, though async is recommended for better performance.
216+
100217
## Configuration
101218
219+
Configuration of django-github-app is done through a `GITHUB_APP` dictionary in your Django project's `DJANGO_SETTINGS_MODULE`.
220+
221+
Here is an example configuration with the default values shown:
222+
223+
```python
224+
GITHUB_APP = {
225+
"APP_ID": "",
226+
"AUTO_CLEANUP_EVENTS": True,
227+
"CLIENT_ID": "",
228+
"DAYS_TO_KEEP_EVENTS": 7,
229+
"NAME": "",
230+
"PRIVATE_KEY": "",
231+
"WEBHOOK_SECRET": "",
232+
}
233+
```
234+
235+
The following settings are required:
236+
237+
- `APP_ID`
238+
- `CLIENT_ID`
239+
- `NAME`
240+
- `PRIVATE_KEY`
241+
- `WEBHOOK_SECRET`
242+
243+
### `APP_ID`
244+
245+
> ❗ **Required** | `str`
246+
247+
The GitHub App's unique identifier. Obtained when registering your GitHub App.
248+
249+
### `AUTO_CLEANUP_EVENTS`
250+
251+
> **Optional** | `bool` | Default: `True`
252+
253+
Boolean flag to enable automatic cleanup of old webhook events.
254+
255+
### `CLIENT_ID`
256+
257+
>**Required** | `str`
258+
259+
The GitHub App's client ID. Obtained when registering your GitHub App.
260+
261+
### `DAYS_TO_KEEP_EVENTS`
262+
263+
> **Optional** | `int` | Default: `7`
264+
265+
Number of days to retain webhook events before cleanup.
266+
267+
### `NAME`
268+
269+
> ❗ **Required** | `str`
270+
271+
The GitHub App's name as registered on GitHub.
272+
273+
### `PRIVATE_KEY`
274+
275+
>**Required** | `str`
276+
277+
The GitHub App's private key for authentication. Can be provided as:
278+
279+
- Raw key contents in environment variable
280+
- File contents read from disk: `Path("path/to/key.pem").read_text()`
281+
282+
### `WEBHOOK_SECRET`
283+
284+
> **Required** | `str`
285+
286+
Secret used to verify webhook payloads from GitHub.
287+
102288
## License
103289
104290
django-github-app is licensed under the MIT license. See the [`LICENSE`](LICENSE) file for more information.

0 commit comments

Comments
 (0)