Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 1 | /** |
| 2 | * "Add CI": a starter workflow for a repository that has no checks, worked | |
| 3 | * out from what is at its root (lib/starter-workflow.ts), committed on a | |
| 4 | * new branch as the person asking and opened as their pull request. Its | |
| 5 | * runs then become the repository's checks, and it can be required. | |
| 6 | */ | |
| 7 | import type { RepoPath, User } from "@g1t/contracts"; | |
| 8 | ||
| 9 | import { repos, work } from "./services.server"; | |
| 10 | import { STARTER_PATH, freeBranch, starterDescription, starterWorkflow } from "./starter-workflow"; | |
| 11 | ||
| 12 | export type AddedCi = { number: number }; | |
| 13 | ||
| 14 | export async function addCi(user: User, path: RepoPath): Promise<{ ok: true; value: AddedCi } | { ok: false; message: string }> { | |
| 15 | const repo = await repos.get(path, user); | |
| 16 | if (!repo.ok) return { ok: false, message: repo.error.message }; | |
| 17 | const defaultBranch = repo.value.defaultBranch; | |
| 18 | const [root, branches] = await Promise.all([repos.tree(path, user, null, ""), repos.branches(path, user)]); | |
| 19 | if (!root.ok) return { ok: false, message: root.error.message }; | |
| 20 | if (!root.value.head) return { ok: false, message: `${defaultBranch} has no commits yet. Push a first commit, then add CI.` }; | |
| 21 | const names = root.value.entries.map((entry) => entry.name); | |
| 22 | const packageJson = names.includes("package.json") | |
| 23 | ? await repos.blob(path, user, defaultBranch, "package.json").then((found) => (found.ok ? found.value.text : null)) | |
| 24 | : null; | |
| 25 | const { yaml, stacks } = starterWorkflow({ names, packageJson }, defaultBranch); | |
| 26 | const branch = freeBranch(branches.ok ? branches.value.map((known) => known.name) : []); | |
| 27 | const committed = await repos.commitFile(path, user, { | |
| 28 | branch, | |
| 29 | path: STARTER_PATH, | |
| 30 | content: yaml, | |
| 31 | message: "Add CI workflow", | |
| 32 | }); | |
| 33 | if (!committed.ok) return { ok: false, message: committed.error.message }; | |
| 34 | const opened = await work.openPull(user, path, { | |
| 35 | branch, | |
| 36 | title: "Add CI", | |
| 37 | body: starterDescription(stacks, defaultBranch), | |
| 38 | agent: user.username, | |
| 39 | runtime: "external", | |
| 40 | }); | |
| 41 | if (!opened.ok) return { ok: false, message: opened.error.message }; | |
| 42 | return { ok: true, value: { number: opened.value.number } }; | |
| 43 | } |