sin-github-issues / scripts /smoke-github-app-routing.mjs
OpenCode
Deploy latest SIN-GitHub-Issues runtime
cd455f6
Raw
History Blame Contribute Delete
3.7 kB
#!/usr/bin/env node
import { createHmac } from 'node:crypto';
import { readFile } from 'node:fs/promises';
import path from 'node:path';
const cwd = process.cwd();
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;
}
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 normalizeRoute(entry, defaultWebhookPath) {
return {
agentSlug: firstString(entry.agentSlug, entry.preferredAgentSlug, entry.appSlug),
appSlug: firstString(entry.appSlug),
botName: firstString(entry.botName),
appId: Number(firstString(String(entry.appId || '').trim(), readEnv(entry.appIdEnv))),
webhookPath: firstString(entry.routePath, entry.webhookPath, defaultWebhookPath || '/github/webhook'),
webhookSecret: firstString(entry.webhookSecret, readEnv(entry.webhookSecretEnv)),
};
}
async function main() {
const args = parseArgs(process.argv.slice(2));
const configPath = path.resolve(cwd, args.config || process.env.SIN_GITHUB_APP_ROUTING_PATH || './config/github-app-routing.local.json');
const baseUrl = firstString(args['base-url'], process.env.SIN_GITHUB_ISSUES_PUBLIC_BASE_URL, 'http://127.0.0.1:46031');
const agent = firstString(args.agent, args.slug, args['app-slug']);
if (!agent) throw new Error('missing_required_arg: --agent <slug-or-app-slug>');
const raw = await readFile(configPath, 'utf8');
const config = JSON.parse(raw);
const defaultWebhookPath = firstString(config.defaultWebhookPath, '/github/webhook');
const apps = Array.isArray(config.apps) ? config.apps.map((entry) => normalizeRoute(entry, defaultWebhookPath)) : [];
const target = apps.find((entry) => entry.agentSlug === agent || entry.appSlug === agent);
if (!target) throw new Error(`unknown_agent_route:${agent}`);
if (!target.webhookSecret) throw new Error(`missing_webhook_secret:${agent}`);
if (!Number.isFinite(target.appId)) throw new Error(`missing_app_id:${agent}`);
const payload = JSON.stringify({
action: args.action || 'opened',
installation: { id: Number(args['installation-id'] || 987654321), app_id: target.appId },
repository: { full_name: args.repo || 'OpenSIN-AI/OpenSIN-backend' },
});
const signature256 = `sha256=${createHmac('sha256', target.webhookSecret).update(payload).digest('hex')}`;
const response = await fetch(`${baseUrl.replace(/\/+$/, '')}${target.webhookPath}`, {
method: 'POST',
headers: {
'content-type': 'application/json',
'x-hub-signature-256': signature256,
'x-github-event': args.event || 'pull_request',
'x-github-delivery': args.delivery || `smoke-${target.appSlug || target.agentSlug}`,
},
body: payload,
});
const text = await response.text();
console.log(JSON.stringify({
ok: response.ok,
baseUrl,
routePath: target.webhookPath,
agentSlug: target.agentSlug,
appSlug: target.appSlug,
appId: target.appId,
status: response.status,
response: text ? JSON.parse(text) : null,
}, null, 2));
if (!response.ok) process.exitCode = 1;
}
main().catch((error) => {
console.error(error instanceof Error ? error.message : String(error));
process.exit(1);
});