pelagia-portal/App/components/layout/report-issue-actions.ts
Hardik 8b6d4e8ea6 feat(automation): issue-to-deploy pipeline — Report Issue button, Claude watcher, tag-triggered deploy
- Report Issue button in portal header files a Forgejo issue (portal + claude-queue labels)
- Windows scheduled watcher runs headless Claude Code on queued issues and opens a PR
- .forgejo/workflows/deploy.yml deploys v* release tags via the pms1 host runner (pm2 restart ppms)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 16:39:43 +05:30

52 lines
1.7 KiB
TypeScript

"use server";
import { auth } from "@/auth";
import { createForgejoIssue } from "@/lib/forgejo";
import { z } from "zod";
const PRIORITIES = ["P0 — Critical (broken / blocking)", "P1 — High", "P2 — Medium", "P3 — Low"] as const;
const reportSchema = z.object({
title: z.string().min(5, "Please give the issue a short title (min 5 characters)").max(150),
description: z.string().min(10, "Please describe the issue (min 10 characters)").max(5000),
priority: z.enum(PRIORITIES),
page: z.string().max(500).optional(),
});
type Result = { ok: true; issueNumber: number; issueUrl: string } | { error: string };
export async function reportIssue(formData: FormData): Promise<Result> {
const session = await auth();
if (!session?.user) return { error: "Unauthorized" };
const parsed = reportSchema.safeParse(Object.fromEntries(formData));
if (!parsed.success) return { error: parsed.error.errors[0].message };
const { title, description, priority, page } = parsed.data;
const body = [
"### Raised by",
`${session.user.name} (${session.user.email}, ${session.user.role}) — via portal Report Issue button`,
"",
"### Description",
description,
"",
"### Priority",
priority,
"",
"### Context",
`- Page: \`${page || "unknown"}\``,
`- Reported at: ${new Date().toISOString()}`,
].join("\n");
try {
const issue = await createForgejoIssue({
title: `[Issue]: ${title}`,
body,
labels: ["portal", "claude-queue"],
});
return { ok: true, issueNumber: issue.number, issueUrl: issue.html_url };
} catch (err) {
console.error("reportIssue failed:", err);
return { error: "Could not file the issue. Please try again or contact the administrator." };
}
}