Spaces:
Sleeping
Sleeping
| import { readFile } from 'node:fs/promises'; | |
| import path from 'node:path'; | |
| const cwd = process.cwd(); | |
| const args = process.argv.slice(2); | |
| function parseArgs(argv) { | |
| const out = {}; | |
| for (let i = 0; i < argv.length; i += 1) { | |
| const token = argv[i]; | |
| if (!token.startsWith('--')) continue; | |
| const key = token.slice(2); | |
| const next = argv[i + 1]; | |
| if (!next || next.startsWith('--')) { | |
| out[key] = 'true'; | |
| continue; | |
| } | |
| out[key] = next; | |
| i += 1; | |
| } | |
| return out; | |
| } | |
| const parsedArgs = parseArgs(args); | |
| const configPath = path.resolve( | |
| cwd, | |
| parsedArgs['config'] || process.env.SIN_GITHUB_APP_ROUTING_PATH || './config/github-app-routing.local.json', | |
| ); | |
| function firstString(...values) { | |
| for (const value of values) { | |
| if (typeof value === 'string' && value.trim()) return value.trim(); | |
| } | |
| return null; | |
| } | |
| function readEnv(name) { | |
| if (!name) return null; | |
| const value = process.env[name]; | |
| return typeof value === 'string' && value.trim() ? value.trim() : null; | |
| } | |
| function parseList(value) { | |
| if (!value || typeof value !== 'string') return []; | |
| return value | |
| .split(',') | |
| .map((item) => item.trim()) | |
| .filter(Boolean); | |
| } | |
| function toRoute(entry, defaultWebhookPath) { | |
| const appId = firstString(String(entry.appId || '').trim(), readEnv(entry.appIdEnv)); | |
| const clientId = firstString(entry.clientId, readEnv(entry.clientIdEnv)); | |
| const routePath = firstString(entry.routePath, entry.webhookPath, defaultWebhookPath || '/github/webhook'); | |
| const agentSlug = firstString(entry.agentSlug, entry.preferredAgentSlug, entry.appSlug); | |
| const privateKey = firstString(entry.privateKeyPem, readEnv(entry.privateKeyEnv)); | |
| const webhookSecret = firstString(entry.webhookSecret, readEnv(entry.webhookSecretEnv)); | |
| return { | |
| agentSlug, | |
| appSlug: firstString(entry.appSlug), | |
| botName: firstString(entry.botName), | |
| routePath, | |
| appId, | |
| clientId, | |
| privateKeyRef: firstString(entry.privateKeyEnv, entry.privateKeyPath, entry.privateKeyPem ? 'inline' : null), | |
| webhookSecretRef: firstString(entry.webhookSecretEnv, entry.webhookSecretPath, entry.webhookSecret ? 'inline' : null), | |
| privateKeyResolved: Boolean(privateKey), | |
| webhookSecretResolved: Boolean(webhookSecret), | |
| }; | |
| } | |
| async function main() { | |
| const raw = await readFile(configPath, 'utf8'); | |
| const config = JSON.parse(raw); | |
| const defaultWebhookPath = firstString(config.defaultWebhookPath, '/github/webhook'); | |
| const agentsFilter = new Set(parseList(parsedArgs.agents || parsedArgs.agent)); | |
| const configuredOnly = parsedArgs['configured-only'] === 'true'; | |
| const apps = (Array.isArray(config.apps) ? config.apps.map((entry) => toRoute(entry, defaultWebhookPath)) : []).filter((app) => { | |
| const matchesAgent = agentsFilter.size === 0 || agentsFilter.has(app.agentSlug || '') || agentsFilter.has(app.appSlug || ''); | |
| const isConfigured = !configuredOnly || Boolean(app.appId || app.clientId || app.privateKeyResolved || app.webhookSecretResolved); | |
| return matchesAgent && isConfigured; | |
| }); | |
| const missing = apps.flatMap((app) => { | |
| const failures = []; | |
| if (!app.agentSlug) failures.push('agentSlug'); | |
| if (!app.appId) failures.push('appId'); | |
| if (!app.clientId) failures.push('clientId'); | |
| if (!app.privateKeyResolved) failures.push('privateKey'); | |
| if (!app.webhookSecretResolved) failures.push('webhookSecret'); | |
| return failures.length ? [{ agentSlug: app.agentSlug || app.appSlug || 'unknown', missing: failures }] : []; | |
| }); | |
| console.log(JSON.stringify({ | |
| ok: missing.length === 0, | |
| configPath, | |
| defaultWebhookPath, | |
| filters: { | |
| agents: [...agentsFilter], | |
| configuredOnly, | |
| }, | |
| apps, | |
| missing, | |
| }, null, 2)); | |
| if (missing.length > 0) process.exitCode = 1; | |
| } | |
| main().catch((error) => { | |
| console.error(error instanceof Error ? error.message : String(error)); | |
| process.exit(1); | |
| }); | |