Skip to content

Commit 6cfaf73

Browse files
committed
feat: change default webhook path to /webhooks/github/
- Update default github_app_route from "/" to "/webhooks/github/" - Update fallback webhook route defaults in core.py - Update documentation and code comments to reflect new default - Update sample configurations and README files for consistency - Update curl example in main README to use new default path BREAKING CHANGE: Default webhook path changed from "/" to "/webhooks/github/". Existing GitHub App webhook URLs need to be updated in GitHub App settings.
1 parent 799b618 commit 6cfaf73

File tree

8 files changed

+21
-24
lines changed

8 files changed

+21
-24
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
- Restructured samples into numbered progression
2020
- Updated README with detailed OAuth2 and rate limiting documentation
2121
- Consistent issue auto-closing across all samples
22+
- Default webhook path changed from `/` to `/webhooks/github/`
2223

2324
### Removed
2425
- Deprecated cruel_closer and oauth2_example samples
2526

2627
### Breaking Changes
2728
- OAuth2 routes now require oauth_session_secret parameter
2829
- Rate limiting parameters added to GitHubApp constructor
30+
- Default webhook path changed from `/` to `/webhooks/github/` - update your GitHub App webhook URL configuration
2931

3032
## [0.2.0] - 2025-09-11
3133

README.md

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ The above function will do `stuff here` for _every_ `issues` event received. Thi
4040

4141
Inside the function, you can access the received request via the conveniently named `request` variable. You can access its payload by simply getting it: `request.payload`
4242

43-
You can find a complete example (containing this cruel_closer function), in the samples folder of this repo. It is a fully functioning FastAPI Github App.
43+
You can find examples in the samples folder of this repo. The [samples](./samples/) include fully functioning FastAPI GitHub Apps demonstrating different features.
4444

4545
#### Run it locally
4646

@@ -60,15 +60,13 @@ uvicorn app:app --host 0.0.0.0 --port 5005 --reload --workers 1
6060
Now, you can send requests! The port is 5005 by default but that can also be overridden. Check `uvicorn app:app --help` for more details. Anyway! Now, on to sending test payloads!
6161

6262
```bash
63-
curl -H "X-GitHub-Event: <your_event>" -H "Content-Type: application/json" -X POST -d @./path/to/payload.json http://localhost:5005
63+
curl -H "X-GitHub-Event: <your_event>" -H "Content-Type: application/json" -X POST -d @./path/to/payload.json http://localhost:5005/webhooks/github/
6464
```
6565

6666
#### Install your GitHub App
6767

6868
**Settings** > **Applications** > **Configure**
6969

70-
> If you were to install the cruel closer app, any repositories that you give the GitHub app access to will cruelly close all new issues, be careful.
71-
7270
#### Deploy your GitHub App
7371

7472
Bear in mind that you will need to run the app _somewhere_. It is possible, and fairly easy, to host the app in something like Kubernetes, or simply containerised, in a machine somewhere. You will need to be careful to expose the FastAPI app port to the outside world so the app can receive the payloads from Github. The deployed FastAPI app will need to be reachable from the same URL you set as the `webhook url`. However, this is getting a little bit into Docker/Kubernetes territory so we will not go too deep.
@@ -77,14 +75,13 @@ Bear in mind that you will need to run the app _somewhere_. It is possible, and
7775

7876
### `GitHubApp` Instance Attributes
7977

80-
`payload`: In the context of a hook request, a Python dict representing the hook payload (raises a `RuntimeError`
81-
outside a hook context).
78+
`payload`: In the context of a webhook request, a Python dict representing the hook payload (raises a `GitHubAppError` outside a webhook context).
8279

8380
`installation_token`: The token used to authenticate as the app installation. This can be used to call api's not supported by `GhApi` like [Github's GraphQL API](https://docs.github.com/en/graphql/reference)
8481

8582
### `GithubApp` Instance Methods
8683

87-
`client`: a [GhApi](https://ghapi.fast.ai/) client authenticated as the app installation (raises a `RuntimeError` inside a hook context without a valid request)
84+
`client`: a [GhApi](https://ghapi.fast.ai/) client authenticated as the app installation (raises a `GitHubAppError` outside a webhook context without a valid installation)
8885

8986
## Rate Limiting
9087

@@ -158,7 +155,7 @@ FastAPI-GitHubApp includes built-in OAuth2 support for user authentication and a
158155

159156
### Setup
160157

161-
OAuth2 is enabled when you provide both `oauth_client_id` and `oauth_client_secret`. The `oauth_session_secret` is **required** for session management:
158+
OAuth2 is enabled when you provide both `oauth_client_id` and `oauth_client_secret` (via constructor parameters or environment variables). The `oauth_session_secret` is **required** for session management:
162159

163160
```python
164161
from githubapp import GitHubApp
@@ -168,7 +165,7 @@ github_app = GitHubApp(
168165
github_app_id=12345,
169166
github_app_key=private_key,
170167
github_app_secret=webhook_secret,
171-
# OAuth2 configuration - all required for OAuth2 to work
168+
# OAuth2 configuration - required for OAuth2 to work
172169
oauth_client_id="your_oauth_client_id",
173170
oauth_client_secret="your_oauth_client_secret",
174171
oauth_session_secret="your-secret-key-for-jwt", # Required!
@@ -180,6 +177,8 @@ github_app = GitHubApp(
180177
)
181178
```
182179

180+
Alternatively, use environment variables (see Environment Variables section below):
181+
183182
### OAuth2 Routes
184183

185184
When OAuth2 is configured, these routes are automatically mounted:
@@ -331,19 +330,15 @@ Environment variables use the `GITHUBAPP_OAUTH_` prefix (see Configuration table
331330
| `GITHUBAPP_ENABLE_OAUTH` | | `True` | Enable/disable OAuth2 routes when fully configured |
332331
| `GITHUBAPP_OAUTH_ROUTES_PREFIX` | | `/auth/github` | OAuth2 routes prefix |
333332

334-
You can find an example on how to init all these config variables in the [cruel_closer sample app](./samples/cruel_closer)
333+
You can find an example on how to init all these config variables in the [basic webhook sample app](./samples/01-basic-webhook)
335334

336335
#### OAuth2 Example
337336

338-
The [oauth2_example](./samples/oauth2_example) demonstrates GitHub OAuth2 authentication with web interface, protected routes, and session management. It shows two approaches:
337+
The [OAuth2 integration sample](./samples/03-oauth2-integration) demonstrates GitHub OAuth2 authentication with web interface, protected routes, and session management. It shows two approaches:
339338

340339
- **Environment-only configuration** (recommended): Load all settings from environment variables
341340
- **Constructor parameters**: Pass OAuth2 settings explicitly to GitHubApp
342341

343-
#### Cruel Closer
344-
345-
The cruel-closer sample app will use information of the received payload (which is received every time an issue is opened), will find said issue and **close it** without regard.
346-
347342
### Inspiration
348343
This was inspired by the following projects:
349344
- https://github.com/ffalor/flask-githubapplication

samples/02-configuration/constructor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def _env_bytes(name: str):
2424
github_app_id=int(os.getenv("GITHUBAPP_ID", "0")) or None,
2525
github_app_key=_env_bytes("GITHUBAPP_PRIVATE_KEY"),
2626
github_app_secret=_env_bytes("GITHUBAPP_WEBHOOK_SECRET"),
27-
github_app_route=os.getenv("GITHUBAPP_WEBHOOK_PATH", "/webhooks/github"),
27+
github_app_route=os.getenv("GITHUBAPP_WEBHOOK_PATH", "/webhooks/github/"),
2828
)
2929

3030

samples/03-oauth2-integration/.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
GITHUBAPP_ID=12345
33
GITHUBAPP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nYour-GitHub-App-Private-Key-Here\n-----END RSA PRIVATE KEY-----"
44
GITHUBAPP_WEBHOOK_SECRET=your-webhook-secret-here
5-
GITHUBAPP_WEBHOOK_PATH=/webhooks/github
5+
GITHUBAPP_WEBHOOK_PATH=/webhooks/github/
66

77
# OAuth2 Configuration (required for OAuth2 functionality)
88
GITHUBAPP_OAUTH_CLIENT_ID=Iv1.your-oauth-client-id

samples/03-oauth2-integration/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ This example demonstrates OAuth2 authentication with GitHub Apps and issue manag
1616

1717
Create a GitHub App with these settings:
1818
- **Homepage URL**: `http://localhost:8000`
19-
- **Webhook URL**: `http://localhost:8000/webhooks/github`
19+
- **Webhook URL**: `http://localhost:8000/webhooks/github/`
2020
- **Authorization callback URL**: `http://localhost:8000/auth/github/callback`
2121

2222
Required permissions:

samples/04-advanced-features/.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
GITHUBAPP_ID=12345
33
GITHUBAPP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nYour-GitHub-App-Private-Key-Here\n-----END RSA PRIVATE KEY-----"
44
GITHUBAPP_WEBHOOK_SECRET=your-webhook-secret-here
5-
GITHUBAPP_WEBHOOK_PATH=/webhooks/github
5+
GITHUBAPP_WEBHOOK_PATH=/webhooks/github/

samples/04-advanced-features/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ This example demonstrates advanced GitHub App features including rate limiting,
1616

1717
Create a GitHub App with these settings:
1818
- **Homepage URL**: `http://localhost:8000`
19-
- **Webhook URL**: `http://localhost:8000/webhooks/github`
19+
- **Webhook URL**: `http://localhost:8000/webhooks/github/`
2020

2121
Required permissions:
2222
- **Issues**: Write (to close issues and add comments)

src/githubapp/core.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def __init__(
177177
github_app_key: bytes = None,
178178
github_app_secret: bytes = None,
179179
github_app_url: str = None,
180-
github_app_route: str = "/",
180+
github_app_route: str = "/webhooks/github/",
181181
# OAuth2 (optional)
182182
oauth_client_id: str = None,
183183
oauth_client_secret: str = None,
@@ -198,7 +198,7 @@ def __init__(
198198
self.secret = github_app_secret
199199
self.router = APIRouter()
200200
self._initialized = False
201-
self._webhook_route = github_app_route or "/"
201+
self._webhook_route = github_app_route or "/webhooks/github/"
202202
# OAuth2 setup (moved to init_app to support env vars)
203203
self.oauth = None
204204
self._enable_oauth = False
@@ -338,7 +338,7 @@ def init_app(self, app: FastAPI, *, route: str = "/"):
338338
`GITHUBAPP_WEBHOOK_PATH`:
339339
340340
Path used for GitHub hook requests as a string.
341-
Default: '/'
341+
Default: '/webhooks/github/'
342342
"""
343343
# Idempotent setup: avoid mounting more than once
344344
if self._initialized:
@@ -348,7 +348,7 @@ def init_app(self, app: FastAPI, *, route: str = "/"):
348348
return
349349

350350
# Register router endpoint for GitHub webhook
351-
self._webhook_route = route or self._webhook_route or "/"
351+
self._webhook_route = route or self._webhook_route or "/webhooks/github/"
352352
self.router.post(self._webhook_route)(self._handle_request)
353353
app.include_router(self.router)
354354
# copy config from FastAPI app

0 commit comments

Comments
 (0)