"use server"; import { cutReleaseForWorkspace } from "yt-dlp-transcript-common/controller/cutRelease"; import { revalidateAfterReleaseCut } from "./revalidateAfterReleaseCut"; import { formValues, type FormState } from "../../lib/formState"; // The "Cut release" form's server action: a FormData adapter over the one // writer, `cutReleaseForWorkspace` (common/controller/cutRelease.ts), which the // CLI (`archilyzer release cut`) and POST /api/ops/cut-release call too. The // dirty-tree guard, the cut, the atomic write, the commit and every refusal's // sentence live there. // A failure carries what was submitted, so the form keeps the typed version // and the commit box (lib/formState.ts). export type CutReleaseState = FormState<{ version: string; committed: boolean }>; export async function cutReleaseAction( _prev: CutReleaseState | undefined, formData: FormData, ): Promise { const values = formValues(formData); const workspaceRaw = formData.get("workspace"); const versionRaw = formData.get("version"); const commitRaw = formData.get("commit"); const workspace = workspaceRaw === "editor" || workspaceRaw === "export" ? workspaceRaw : null; const version = typeof versionRaw === "string" ? versionRaw.trim() : ""; const shouldCommit = commitRaw === "true" || commitRaw === "on"; if (!workspace) { return { ok: false, error: "Invalid workspace.", values }; } if (!version) { return { ok: false, error: "Version is required.", values }; } const result = await cutReleaseForWorkspace({ workspace, version, commit: shouldCommit, }); if (!result.ok) { // The heading was written and only the commit after it failed (release 11 // slice O3, release 10 review L3): the pages that render this changelog // are stale all the same. The error already says the file changed. if (result.written) revalidateAfterReleaseCut(); return { ok: false, error: result.error, values }; } revalidateAfterReleaseCut(); return { ok: true, version: result.version, committed: result.committed }; }