Skip to content

GitHub App one-click install flow#18

Merged
RahulModugula merged 2 commits into
mainfrom
github-app-install
Apr 11, 2026
Merged

GitHub App one-click install flow#18
RahulModugula merged 2 commits into
mainfrom
github-app-install

Conversation

@RahulModugula

Copy link
Copy Markdown
Owner

Summary

  • Replaces the 15-step manual webhook setup with a single redirect: users visit /api/github/app/install and are sent directly to GitHub's App authorization page
  • OAuth callback at /api/github/app/callback receives the installation_id, fetches account details via JWT-authenticated GitHub API, and stores the record in memory (keyed by installation_id)
  • New endpoints: GET /api/github/app/installations (JSON list), POST /api/github/app/webhook (handles installation and pull_request events, dispatches reviews into the existing pipeline)
  • Self-hoster landing page at GET /api/github/ with an "Install Odin on GitHub" button
  • All endpoints return 503 with setup instructions when ODIN_GITHUB_APP_ID is not configured
  • JWT signing uses PyJWT when available, falls back to cryptography.hazmat primitives — no new hard dependencies added

New env vars

Variable Description
ODIN_GITHUB_APP_ID Numeric GitHub App ID
ODIN_GITHUB_APP_CLIENT_ID OAuth client ID / app slug
ODIN_GITHUB_APP_CLIENT_SECRET OAuth client secret
ODIN_GITHUB_APP_PRIVATE_KEY PEM private key (newlines as \n)
ODIN_GITHUB_APP_WEBHOOK_SECRET Webhook HMAC secret

Test plan

  • test_install_redirect_returns_302_when_configured — redirect fires when app is configured
  • test_install_redirect_returns_503_when_not_configured — 503 with helpful message when unconfigured
  • test_callback_stores_installation_and_returns_200 — callback persists record and returns HTML
  • test_callback_stores_record_in_memory — installation dict contains correct account login
  • test_installations_list_returns_json — list endpoint returns correct JSON shape
  • test_app_webhook_rejects_bad_signature — HMAC verification blocks unsigned requests
  • test_app_webhook_accepts_valid_installation_event — signed installation events are accepted
  • test_landing_page_shows_install_button_when_configured — landing page renders install button
  • 14 tests total, all passing

Copilot AI review requested due to automatic review settings April 11, 2026 13:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements a one-click GitHub App installation flow and webhook ingestion so self-hosters can connect Odin to GitHub without the previous manual webhook setup.

Changes:

  • Adds backend/app/api/github_app.py with install redirect, OAuth callback, installations listing, webhook handler, and a simple landing page.
  • Registers the new GitHub App router under /api/github and extends settings with GitHub App env vars.
  • Adds end-to-end tests covering redirects, callback persistence, installations listing, webhook signature verification, and landing page rendering.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 9 comments.

File Description
backend/app/api/github_app.py New router implementing install/callback/installations/webhook + landing page for GitHub App setup.
backend/app/main.py Includes the new GitHub App router under /api/github.
backend/app/config.py Adds GitHub App-related settings/env vars to Settings.
backend/tests/test_github_app.py Adds tests for the GitHub App install flow, callback, installations list, webhook signature checks, and landing page.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

) -> dict[str, str]:
"""Receive and dispatch GitHub App webhook events.

Handles: installation, pull_request, push.
raise HTTPException(status_code=401, detail="Invalid webhook signature")

event_type = request.headers.get("X-GitHub-Event", "")
payload: dict[str, Any] = json.loads(payload_bytes)
Comment thread backend/tests/test_github_app.py Outdated
Comment on lines +8 to +10
from unittest.mock import AsyncMock, patch

import pytest
Comment thread backend/tests/test_github_app.py Outdated
import pytest
from fastapi.testclient import TestClient

from app.api.github_app import _installations, _make_jwt
@github_app_router.get("/app/install")
async def github_app_install() -> RedirectResponse:
"""Redirect the user to the GitHub App installation page."""
_require_app_configured()
"""Process installation created/deleted events."""
action = payload.get("action", "")
installation = payload.get("installation", {})
installation_id: int = installation.get("id", 0)
Comment on lines +341 to +345
payload_bytes = await request.body()
sig_header = request.headers.get("X-Hub-Signature-256")

if not _verify_app_webhook_signature(payload_bytes, sig_header):
logger.warning("app webhook signature verification failed")
Comment on lines +106 to +110
@github_app_router.get("/", response_class=HTMLResponse, include_in_schema=False)
async def landing_page() -> HTMLResponse:
"""Self-hoster landing page with a one-click GitHub App install button."""
app_configured = bool(settings.github_app_id and settings.github_app_client_id)
if app_configured:
Comment thread backend/app/config.py
# GitHub App integration (one-click install flow)
github_app_id: str = ""
github_app_client_id: str = ""
github_app_client_secret: str = ""
<p>Installation ID: <code>{installation_id}</code></p>
</body>
</html>"""
return HTMLResponse(content=html, status_code=200)
Replaces the 15-step manual webhook setup with a single redirect.
Visiting /api/github/app/install sends the user to the GitHub App
authorization page; the callback stores the installation and shows a
confirmation page. Includes JWT generation (PyJWT with cryptography
fallback), installation storage, app webhook handler, and a self-hoster
landing page. All endpoints return 503 with setup instructions when
ODIN_GITHUB_APP_ID is unset. 14 new tests.
@RahulModugula
RahulModugula merged commit 7c1f6ce into main Apr 11, 2026
7 checks passed
@RahulModugula
RahulModugula deleted the github-app-install branch April 11, 2026 13:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants