Skip to content
45 linesCodeBlameRaw
1/**
2 * "Set up a security policy": commits a SECURITY.md on a new branch as the
3 * person asking and opens it as their pull request, then goes to it, as
4 * "Set up code scanning" does with its workflow. It adds a file to the
5 * repository: Push.
6 */
7import { redirect } from "react-router";
8
9import type { Route } from "./+types/security-policy-setup";
10import { refusal, requireWritableRepo } from "../../lib/access.server";
11import { securityPolicyBranch, securityPolicyPullBody, securityPolicyTemplate } from "../../lib/security-overview";
12import { advisories, repos, work } from "../../lib/services.server";
13import { assertSameOrigin, requireUser } from "../../lib/session.server";
14
15export async function action({ request, params, context }: Route.ActionArgs) {
16 assertSameOrigin(request);
17 const user = requireUser(context, request);
18 await requireWritableRepo(context, params);
19 const refused = await refusal(context, params, "push");
20 if (refused) return { error: refused };
21 const path = { namespace: params.owner, name: params.repo };
22 const base = `/${params.owner}/${params.repo}`;
23 const [branches, reporting] = await Promise.all([repos.branches(path, user), advisories.reportSettings(path, user)]);
24 const branch = securityPolicyBranch(branches.ok ? branches.value.map((known) => known.name) : []);
25 const committed = await repos.commitFile(path, user, {
26 branch,
27 path: "SECURITY.md",
28 content: securityPolicyTemplate(`${params.owner}/${params.repo}`, reporting.ok && reporting.value.privateVulnerabilityReporting, base),
29 message: "Add a security policy",
30 });
31 if (!committed.ok) return { error: committed.error.message };
32 const opened = await work.openPull(user, path, {
33 branch,
34 title: "Add a security policy",
35 body: securityPolicyPullBody("SECURITY.md"),
36 agent: user.username,
37 runtime: "external",
38 });
39 if (!opened.ok) return { error: opened.error.message };
40 throw redirect(`${base}/pull/${opened.value.number}`);
41}
42
43export async function loader({ params }: Route.LoaderArgs) {
44 throw redirect(`/${params.owner}/${params.repo}/security`);
45}