Initial commit: SDLC Orchestrator replacing n8n
Lightweight Hono webhook router that receives Gitea events and creates Coder workspaces for each SDLC stage (analyse, architect, develop, review, test, rework, release, maintenance). Includes k8s manifests for deployment and the Coder workspace template moved from babble. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { Hono } from "hono";
|
||||
import { logger } from "hono/logger";
|
||||
import { serve } from "@hono/node-server";
|
||||
import cron from "node-cron";
|
||||
|
||||
import { loadConfig } from "./config.js";
|
||||
import { CoderClient } from "./services/coder.js";
|
||||
import { GiteaClient } from "./services/gitea.js";
|
||||
|
||||
import { issueTriage } from "./handlers/issue-triage.js";
|
||||
import { issueLabel } from "./handlers/issue-label.js";
|
||||
import { issueComment } from "./handlers/issue-comment.js";
|
||||
import { prReview } from "./handlers/pr-review.js";
|
||||
import { prRework } from "./handlers/pr-rework.js";
|
||||
import { release } from "./handlers/release.js";
|
||||
import { runMaintenance, type MaintenanceRepo } from "./handlers/maintenance.js";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Bootstrap
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const config = loadConfig();
|
||||
const coderClient = new CoderClient(config);
|
||||
const giteaClient = new GiteaClient(config);
|
||||
|
||||
const app = new Hono();
|
||||
app.use("*", logger());
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Health check
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
app.get("/health", (c) => c.json({ status: "ok" }));
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Webhook endpoints — same paths as the n8n webhooks so Gitea config
|
||||
// can stay unchanged (just point to new host).
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
app.post("/webhook/gitea-issue-triage", issueTriage(config, coderClient, giteaClient));
|
||||
app.post("/webhook/gitea-issue-label", issueLabel(config, coderClient, giteaClient));
|
||||
app.post("/webhook/gitea-issue-comment", issueComment(config, coderClient));
|
||||
app.post("/webhook/gitea-pr-review", prReview(config, coderClient, giteaClient));
|
||||
app.post("/webhook/gitea-pr-review-rework", prRework(config, coderClient, giteaClient));
|
||||
app.post("/webhook/gitea-release", release(config, coderClient, giteaClient));
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Scheduled maintenance cron (Monday 9:00 AM)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const maintenanceRepos = parseMaintenanceRepos();
|
||||
if (maintenanceRepos.length > 0) {
|
||||
const maintenanceFn = runMaintenance(config, coderClient, maintenanceRepos);
|
||||
|
||||
cron.schedule("0 9 * * 1", () => {
|
||||
console.log("[cron] running weekly maintenance");
|
||||
maintenanceFn().catch((err) =>
|
||||
console.error("[cron] maintenance failed:", err),
|
||||
);
|
||||
});
|
||||
|
||||
console.log(
|
||||
`Maintenance cron scheduled for ${maintenanceRepos.length} repo(s)`,
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Start
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
serve({ fetch: app.fetch, port: config.port }, (info) => {
|
||||
console.log(`SDLC Orchestrator listening on :${info.port}`);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parse MAINTENANCE_REPOS env var.
|
||||
* Format: comma-separated "org/repo=clone_url" entries.
|
||||
* Example: "claude/babble=https://gitea.samson.media/claude/babble.git"
|
||||
*/
|
||||
function parseMaintenanceRepos(): MaintenanceRepo[] {
|
||||
const raw = process.env.MAINTENANCE_REPOS;
|
||||
if (!raw) return [];
|
||||
|
||||
return raw.split(",").map((entry) => {
|
||||
const [fullName, cloneUrl] = entry.trim().split("=");
|
||||
const [org, repo] = fullName.split("/");
|
||||
return { org, repo, cloneUrl };
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user