@fragno-dev/github-app-fragment
v0.0.1
Published
A Fragno fragment
Readme
github-app-fragment
A Fragno fragment that integrates a GitHub App using installation-only authentication. Includes a CLI to run a local server and call all fragment routes for integration testing.
Features
- JWT + installation access token auth
- Webhook-driven installation and repository tracking
- Explicit repo linking for access control
- Pull request listing + review creation
- CLI for serving and exercising all routes
GitHub App Setup (UI)
- Go to GitHub Settings → Developer settings → GitHub Apps → New GitHub App.
- Fill in:
- GitHub App name (any unique name)
- Homepage URL (can be your project URL)
- Webhook URL: use your tunnel URL +
/api/github-app-fragment/webhooks - Webhook secret: set a random secret (keep it)
- Permissions (Repository):
- Pull requests: Read & write
- Metadata: Read-only (default)
- Subscribe to webhook events:
installationinstallation_repositories
- Generate a private key and download the
.pemfile. - Install the App on the repositories you want to test with.
Generating the PEM private key
- Open your GitHub App settings page.
- Scroll to Private keys.
- Click Generate a private key.
- Download the
.pemfile and store it securely.
Environment
GITHUB_APP_ID=123456
GITHUB_APP_SLUG=my-github-app
GITHUB_APP_PRIVATE_KEY_FILE=./my-github-app.private-key.pem
GITHUB_APP_WEBHOOK_SECRET=super-secret
# Optional
GITHUB_APP_API_BASE_URL=https://api.github.com
GITHUB_APP_API_VERSION=2022-11-28
GITHUB_APP_WEB_BASE_URL=https://github.com
GITHUB_APP_DEFAULT_LINK_KEY=default
GITHUB_APP_TOKEN_CACHE_TTL_SECONDS=3300If you use GITHUB_APP_PRIVATE_KEY, store it as a single line with \n escapes.
CLI (Local Integration Testing)
Build once:
pnpm exec turbo build --filter=@fragno-dev/github-app-fragment --output-logs=errors-onlyStart a local server (SQLite):
pnpm exec fragno-github-app serve --port 6173Use a custom SQLite path:
pnpm exec fragno-github-app serve --db-path ./github-app.sqliteExpose it with your tunnel and set the GitHub App webhook URL to:
https://<tunnel-host>/api/github-app-fragment/webhooksCall routes from the CLI:
export FRAGNO_GITHUB_APP_BASE_URL=http://localhost:6173/api/github-app-fragment
pnpm exec fragno-github-app installations list
pnpm exec fragno-github-app installations repos --installation-id <id>
pnpm exec fragno-github-app repositories link --installation-id <id> --repo-id <repo>
pnpm exec fragno-github-app pulls list --owner <owner> --repo <repo>Send a signed webhook payload (optional):
pnpm exec fragno-github-app webhooks send \
--event installation \
--installation-id <id> \
--payload '{"installation":{"id":"<id>"},"action":"created"}'Server Usage (Framework Integration)
import {
createGitHubAppFragment,
type GitHubAppFragmentConfig,
} from "@fragno-dev/github-app-fragment";
import { InMemoryAdapter } from "@fragno-dev/db/adapters/in-memory";
const config: GitHubAppFragmentConfig = {
appId: process.env.GITHUB_APP_ID ?? "",
appSlug: process.env.GITHUB_APP_SLUG ?? "",
privateKeyPem: process.env.GITHUB_APP_PRIVATE_KEY ?? "",
webhookSecret: process.env.GITHUB_APP_WEBHOOK_SECRET ?? "",
webhook: (register) => {
register("installation.deleted", async ({ payload }) => {
// Optional: cleanup app-specific state when an installation is removed in GitHub.
console.log("GitHub app uninstalled", payload.installation.id);
});
},
};
const fragment = createGitHubAppFragment(config, {
databaseAdapter: new InMemoryAdapter(),
outbox: { enabled: true },
});
// Public service access to both the raw App instance and helper client
const app = fragment.services.app;
const githubApiClient = fragment.services.githubApiClient;
export const { GET, POST } = fragment.handlersFor("next-js");Routes
POST /webhooksGET /installationsGET /installations/:installationId/reposGET /repositories/linkedPOST /repositories/linkPOST /repositories/unlinkGET /repositories/:owner/:repo/pullsPOST /repositories/:owner/:repo/pulls/:number/reviewsPOST /installations/:installationId/sync
Client Usage
import { createGitHubAppFragmentClients } from "@fragno-dev/github-app-fragment";
const github = createGitHubAppFragmentClients({ baseUrl: "/" });
const syncInstallation = github.useSyncInstallation();Development
pnpm exec turbo types:check --filter=@fragno-dev/github-app-fragment --output-logs=errors-only
pnpm exec turbo build --filter=@fragno-dev/github-app-fragment --output-logs=errors-only
pnpm exec turbo test --filter=@fragno-dev/github-app-fragment --output-logs=errors-only