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.
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 1 | import { Form, Link, data, redirect } from "react-router"; |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 2 | |
| 3 | import type { Route } from "./+types/github-setup"; | |
| 4 | import { AuthCard } from "../components/auth-card"; | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 5 | import { GithubMark } from "../components/github"; |
| 6 | import { ErrorText, SubmitButton } from "../components/ui"; | |
| 7 | import { INSTALL_COOKIE, cookie, installWorkspace, installationSummary, readCookie, setupChoices } from "../lib/github"; | |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 8 | import { githubApp } from "../lib/github.server"; |
| 9 | import { page } from "../lib/meta"; | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 10 | import { assertSameOrigin, requireUser, roleIn } from "../lib/session.server"; |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 11 | |
| 12 | export function meta(args: Route.MetaArgs) { | |
| 13 | return page(args, { title: "Connecting GitHub · g1t" }); | |
| 14 | } | |
| 15 | ||
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 16 | type Problem = { kind: "error"; error: string; workspace: string | null; link: string | null }; |
| 17 | type Choice = { | |
| 18 | kind: "choose"; | |
| 19 | installation: { id: number; account: string; summary: string }; | |
| 20 | workspaces: { slug: string; name: string; added: boolean }[]; | |
| 21 | }; | |
| 22 | ||
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 23 | /** |
| 24 | * The app's Setup URL: GitHub returns here after an installation with | |
| 25 | * `installation_id`, `setup_action` and the state. The installation is | |
| 26 | * recorded against the workspace it was started for, after integrations | |
| 27 | * checks with the person's own GitHub token that they can see it. | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 28 | * |
| 29 | * Without g1t's state (the app was installed on GitHub directly, from | |
| 30 | * another browser, or the cookie was lost), the person chooses which of | |
| 31 | * the workspaces they own to add it to, checked the same way. | |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 32 | */ |
| 33 | export async function loader({ request, context }: Route.LoaderArgs) { | |
| 34 | const user = requireUser(context, request); | |
| 35 | const url = new URL(request.url); | |
| 36 | const clear = { "set-cookie": cookie(INSTALL_COOKIE, "", 0) }; | |
| 37 | const workspace = installWorkspace(readCookie(request.headers.get("cookie"), INSTALL_COOKIE), url.searchParams.get("state")); | |
| 38 | const action = url.searchParams.get("setup_action"); | |
| 39 | const installation = Number(url.searchParams.get("installation_id")); | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 40 | const problem = (error: string, at: string | null = workspace, link: string | null = null) => |
| 41 | data<Problem | Choice>({ kind: "error", error, workspace: at, link }, { headers: clear }); | |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 42 | // Repositories chosen again on GitHub: nothing to record, the picker |
| 43 | // lists what the installation can see now. | |
| 44 | if (!workspace && action === "update") throw redirect("/new/github", { headers: clear }); | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 45 | // An organization member asked an owner to approve: nothing to record yet. |
| 46 | if (action === "request") { | |
| 47 | const back = workspace ? `/new/github?workspace=${encodeURIComponent(workspace)}&` : "/new/github?"; | |
| 48 | throw redirect(`${back}requested=1`, { headers: clear }); | |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 49 | } |
| 50 | if (!Number.isSafeInteger(installation) || installation <= 0) { | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 51 | return problem("GitHub did not say which installation was made."); |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 52 | } |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 53 | if (workspace) { |
| 54 | const added = await githubApp.addInstallation(user, workspace, installation); | |
| 55 | if (!added.ok) return problem(added.error.message); | |
| 56 | throw redirect(`/new/github?workspace=${encodeURIComponent(workspace)}&installation=${installation}`, { headers: clear }); | |
| 57 | } | |
| 58 | const owned = (user.workspaces ?? []).filter((membership) => membership.role === "owner"); | |
| 59 | if (owned.length === 0) { | |
| 60 | return problem("Only a workspace owner can add a GitHub account. Ask an owner of your workspace to add it from Import from GitHub.", null); | |
| 61 | } | |
| 62 | const visible = await githubApp.visibleInstallations(user); | |
| 63 | if (!visible.ok) { | |
| 64 | // GitHub not linked, or its access ended: link it and come back here. | |
| 65 | const unlinked = visible.error.code === "not_found" || visible.error.code === "unauthenticated"; | |
| 66 | const here = `${url.pathname}${url.search}`; | |
| 67 | return problem(visible.error.message, null, unlinked ? `/auth/github?link=1&next=${encodeURIComponent(here)}` : null); | |
| 68 | } | |
| 69 | const found = visible.value.find((item) => item.id === installation); | |
| 70 | if (!found) { | |
| 71 | return problem( | |
| 72 | "Your GitHub account cannot see that installation. Install the app from your own GitHub account or an organization you manage.", | |
| 73 | null, | |
| 74 | ); | |
| 75 | } | |
| 76 | return data<Problem | Choice>( | |
| 77 | { | |
| 78 | kind: "choose", | |
| 79 | installation: { id: found.id, account: found.account, summary: installationSummary(found) }, | |
| 80 | workspaces: setupChoices(owned, found), | |
| 81 | }, | |
| 82 | { headers: clear }, | |
| 83 | ); | |
| 84 | } | |
| 85 | ||
| 86 | export async function action({ request, context }: Route.ActionArgs) { | |
| 87 | assertSameOrigin(request); | |
| 88 | const user = requireUser(context, request); | |
| 89 | const form = await request.formData(); | |
| 90 | const workspace = String(form.get("workspace") ?? "").toLowerCase(); | |
| 91 | const installation = Number(form.get("installation")); | |
| 92 | if (roleIn(user, workspace) !== "owner") return { error: "Only an owner of the workspace can add GitHub accounts to it." }; | |
| 93 | if (!Number.isSafeInteger(installation) || installation <= 0) return { error: "Choose an installation to add." }; | |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 94 | const added = await githubApp.addInstallation(user, workspace, installation); |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 95 | if (!added.ok) return { error: added.error.message }; |
| 96 | throw redirect(`/new/github?workspace=${encodeURIComponent(workspace)}&installation=${installation}`); | |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 97 | } |
| 98 | ||
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 99 | export default function GithubSetup({ loaderData, actionData }: Route.ComponentProps) { |
| 100 | if (loaderData.kind === "choose") { | |
| 101 | const { installation, workspaces } = loaderData; | |
| 102 | return ( | |
| 103 | <AuthCard | |
| 104 | title="Add a GitHub account" | |
| 105 | subtitle={`Add the installation on ${installation.account} to which workspace?`} | |
| 106 | footer={ | |
| 107 | <Link to="/new/github" className="text-fg underline underline-offset-4"> | |
| 108 | Not now | |
| 109 | </Link> | |
| 110 | } | |
| 111 | > | |
| 112 | <div className="flex items-center gap-3 rounded-md border border-line px-4 py-3"> | |
| 113 | <GithubMark className="size-5 shrink-0" /> | |
| 114 | <div className="min-w-0"> | |
| 115 | <p className="truncate font-mono text-sm">{installation.account}</p> | |
| 116 | <p className="text-xs text-faint">{installation.summary}</p> | |
| 117 | </div> | |
| 118 | </div> | |
| 119 | <ul className="mt-4 divide-y divide-line rounded-md border border-line"> | |
| 120 | {workspaces.map((option) => ( | |
| 121 | <li key={option.slug} className="flex items-center gap-3 px-4 py-2.5"> | |
| 122 | <div className="min-w-0"> | |
| 123 | <p className="truncate text-sm">{option.name}</p> | |
| 124 | {option.name !== option.slug && <p className="truncate font-mono text-xs text-faint">{option.slug}</p>} | |
| 125 | </div> | |
| 126 | <span className="ml-auto shrink-0"> | |
| 127 | {option.added ? ( | |
| 128 | <Link to={`/new/github?workspace=${option.slug}&installation=${installation.id}`} className="text-sm text-muted hover:text-fg"> | |
| 129 | Added · Open | |
| 130 | </Link> | |
| 131 | ) : ( | |
| 132 | <Form method="post"> | |
| 133 | <input type="hidden" name="installation" value={installation.id} /> | |
| 134 | <SubmitButton name="workspace" value={option.slug} pending="Adding…"> | |
| 135 | Add | |
| 136 | </SubmitButton> | |
| 137 | </Form> | |
| 138 | )} | |
| 139 | </span> | |
| 140 | </li> | |
| 141 | ))} | |
| 142 | </ul> | |
| 143 | <ErrorText>{actionData?.error}</ErrorText> | |
| 144 | </AuthCard> | |
| 145 | ); | |
| 146 | } | |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 147 | return ( |
| 148 | <AuthCard | |
| 149 | title="Connecting GitHub" | |
| 150 | subtitle="That did not work" | |
| 151 | footer={ | |
| 152 | <Link | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 153 | to={loaderData.workspace ? `/new/github?workspace=${loaderData.workspace}` : "/new/github"} |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 154 | className="text-fg underline underline-offset-4" |
| 155 | > | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 156 | Back to Import from GitHub |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 157 | </Link> |
| 158 | } | |
| 159 | > | |
| 160 | <p className="text-sm text-danger" role="alert"> | |
| 161 | {loaderData.error} | |
| 162 | </p> | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 163 | {loaderData.link && ( |
| 164 | <a | |
| 165 | href={loaderData.link} | |
| 166 | className="mt-4 inline-flex w-full items-center justify-center gap-2 rounded-md bg-fg px-3.5 py-2 text-sm font-medium text-bg hover:bg-fg-hover" | |
| 167 | > | |
| 168 | <GithubMark /> Link your GitHub account | |
| 169 | </a> | |
| 170 | )} | |
| An unknown behind count reads ?, not 0+; Code pages leave the description and topics to Files | 171 | </AuthCard> |
| 172 | ); | |
| 173 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.