GitHub App service that dispatches GitHub Actions workflows across repositories using scope-based policies.
- One bot, many repositories.
- Centralized dispatch endpoint for release operations.
- Scope-based controls so each request can run only allowed repositories/workflows/refs.
- Runtime: Node.js + TypeScript + Express
- Auth to GitHub: GitHub App installation tokens
- Auth to this service: static bearer token (
BOT_API_TOKEN) - Policy:
config/scopes.yml
In GitHub: Settings -> Developer settings -> GitHub Apps -> New GitHub App
Set:
- Webhook URL:
https://your-bot.example.com/webhook(placeholder for now) - Webhook secret: same as
GITHUB_WEBHOOK_SECRET - Permissions:
- Actions:
Read and write - Metadata:
Read-only
- Actions:
- Subscribe to events: optional for this MVP (dispatch works without incoming events)
After creating app:
- Note
App ID - Generate a private key (download
.pem) - Install app to required org/repositories
cp .env.example .envSet values in .env:
GITHUB_APP_IDGITHUB_APP_PRIVATE_KEYas one-line string with\\nfor line breaksGITHUB_WEBHOOK_SECRETBOT_API_TOKEN- Optional:
PORT,DRY_RUN,SCOPES_CONFIG_PATH
To convert pem into one line:
awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' private-key.pemEdit config/scopes.yml.
Each scope defines allowed:
- repositories (
owner/repo) - workflows (
release.ymlor workflow ID) - refs (
refs/heads/main, wildcards supported)
npm install
npm run devHealth check:
curl http://localhost:3000/healthzcurl -X POST http://localhost:3000/dispatch \
-H "Authorization: Bearer $BOT_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scope": "release",
"repository": "your-org/service-a",
"workflow": "release.yml",
"ref": "refs/heads/main",
"inputs": {
"version": "1.2.3"
}
}'Expected response: 202 Accepted
Configured:
- ESLint (
eslint.config.mjs) - Prettier (
.prettierrc.json) - lint-staged (in
package.json) - Husky hooks (
.husky/pre-commit,.husky/commit-msg) - commitlint (
commitlint.config.cjs)
Install and enable (choose one package manager):
npm run install:quality:npm
npm run setup:hooksyarn install:quality:yarn
yarn setup:hooksUseful checks:
npm run lint
npm run lint:fix
npm run format:check
npm run checkDRY_RUN=truevalidates scope and resolves installation without dispatching workflow.- Keep scope policies tight to avoid accidental broad access.