feat: add GitHub App maker to self-hosted Git configuration#3049
feat: add GitHub App maker to self-hosted Git configuration#3049HarshMN2345 wants to merge 1 commit into
Conversation
Self-hosted instances without VCS configured now see an inline GitHub App maker in Project Settings → Git instead of a static docs link. Uses the GitHub App manifest flow to pre-configure webhooks, permissions, and callback URLs automatically. Includes CSRF protection via sessionStorage, proper hostname validation, and extracts all required env vars (_APP_VCS_GITHUB_APP_NAME, _APP_VCS_GITHUB_PRIVATE_KEY, _APP_VCS_GITHUB_APP_ID, _APP_VCS_GITHUB_CLIENT_ID, _APP_VCS_GITHUB_CLIENT_SECRET, _APP_VCS_GITHUB_WEBHOOK_SECRET) ready to paste into .env. The connectGit component (used mid-flow in function/site creation) is updated to link back to settings instead of external docs, and migrated to Svelte 5 runes.
Greptile SummaryThis PR adds a
Confidence Score: 3/5The change should not be merged until the PEM newline encoding is fixed; users who follow the flow today will copy a broken .env block and fail to start their instance. The broken PEM encoding is the central output of the new feature — every user who completes the manifest flow and pastes the generated env vars will get a malformed private key entry that Docker cannot parse. The Svelte event syntax issue could cause the reset and submit buttons to stop working in Svelte 5 mode. src/lib/components/git/gitHubAppMaker.svelte needs the PEM line-encoding fix and the on:click to onclick updates before this is safe to ship.
|
| Filename | Overview |
|---|---|
| src/lib/components/git/gitHubAppMaker.svelte | New component implementing the GitHub App manifest flow; contains a bug where the PEM private key embedded newlines break standard .env file format, and uses mixed Svelte 4/5 event syntax. |
| src/lib/components/git/connectGit.svelte | Migrated from Svelte 4 to Svelte 5 runes; replaces static docs link with a settings-page link — straightforward and correct. |
| src/routes/(console)/project-[region]-[project]/settings/updateInstallations.svelte | Replaces a static Alert with the new GitHubAppMaker component under the existing isSelfHosted && !isVcsEnabled guard; minimal change with correct scoping. |
| src/lib/components/git/index.ts | Adds export for GitHubAppMaker — trivial barrel-file change. |
Reviews (1): Last reviewed commit: "feat: add GitHub App maker to self-hoste..." | Re-trigger Greptile
|
|
||
| const envVars = $derived.by(() => { | ||
| if (!credentials) return ''; | ||
| const pem = credentials.pem.replace(/\n$/, ''); |
There was a problem hiding this comment.
The PEM private key from GitHub contains embedded newlines (it is a multi-line block), so after only stripping the trailing newline the resulting
_APP_VCS_GITHUB_PRIVATE_KEY value spans multiple lines. Standard Docker env_file parsing and most dotenv libraries do not support multi-line values in the shell-quoted format, meaning the pasted block would produce a broken .env and the server would fail to load the private key. The newlines inside the PEM should be escaped to literal sequences so the value fits on a single line.
| const pem = credentials.pem.replace(/\n$/, ''); | |
| const pem = credentials.pem.replace(/\n/g, '\\n').replace(/\\n$/, ''); |
| <Button secondary on:click={reset}> | ||
| <Icon slot="start" icon={IconRefresh} size="s" /> | ||
| Create another GitHub App | ||
| </Button> |
There was a problem hiding this comment.
The two
Button component usages here use Svelte 4's on:click directive while the native <button> on line 210 uses the Svelte 5 onclick attribute. The rest of this component is already written in Svelte 5 runes style ($state, $derived). Using the old event directive on a component that may not forward it via createEventDispatcher can silently drop the handler in Svelte 5 mode.
| <Button secondary on:click={reset}> | |
| <Icon slot="start" icon={IconRefresh} size="s" /> | |
| Create another GitHub App | |
| </Button> | |
| <Button secondary onclick={reset}> | |
| <Icon slot="start" icon={IconRefresh} size="s" /> | |
| Create another GitHub App | |
| </Button> |
| required /> | ||
| {/if} | ||
| <div> | ||
| <Button on:click={submit} disabled={!isValid}>Create GitHub App</Button> |
There was a problem hiding this comment.
Same
on:click / onclick inconsistency as the reset button — this Button instance should also use the Svelte 5 onclick attribute to stay consistent with the runes-based component.
| <Button on:click={submit} disabled={!isValid}>Create GitHub App</Button> | |
| <Button onclick={submit} disabled={!isValid}>Create GitHub App</Button> |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| try { | ||
| const response = await fetch( | ||
| `https://api.github.com/app-manifests/${code}/conversions`, | ||
| { method: 'POST', headers: { Accept: 'application/vnd.github+json' } } | ||
| ); | ||
| if (!response.ok) { | ||
| const body = await response.json().catch(() => null); | ||
| throw new Error(body?.message ?? `GitHub API returned ${response.status}`); | ||
| } | ||
| const data = await response.json(); | ||
| credentials = data as GitHubAppCredentials; |
There was a problem hiding this comment.
Client-side credential exchange exposes secrets in browser DevTools
The call to https://api.github.com/app-manifests/${code}/conversions is made directly from the browser. The response includes the GitHub App private key (pem), client_secret, and webhook_secret. These appear in plain text in the browser's network panel and are stored in Svelte reactive state for the lifetime of the page. For an admin setup page it may be an acceptable tradeoff, but worth an explicit acknowledgment: any browser extension or XSS vector active on this page could read those values before the user copies and discards them.
Self-hosted instances without VCS configured now see an inline GitHub App maker in Project Settings → Git instead of a static docs link.
Uses the GitHub App manifest flow to pre-configure webhooks, permissions, and callback URLs automatically. Includes CSRF protection via sessionStorage, proper hostname validation, and extracts all required env vars (_APP_VCS_GITHUB_APP_NAME, _APP_VCS_GITHUB_PRIVATE_KEY, _APP_VCS_GITHUB_APP_ID, _APP_VCS_GITHUB_CLIENT_ID, _APP_VCS_GITHUB_CLIENT_SECRET, _APP_VCS_GITHUB_WEBHOOK_SECRET) ready to paste into .env.
What does this PR do?
(Provide a description of what this PR does.)
Test Plan
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)
Related PRs and Issues
(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)
Have you read the Contributing Guidelines on issues?
(Write your answer here.)