@auto-agents/github-app-installer 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +67 -0
- package/package.json +57 -0
- package/src/cli.ts +72 -0
- package/src/config.ts +52 -0
- package/src/github.ts +35 -0
- package/src/handler.ts +68 -0
- package/src/index.ts +25 -0
- package/src/manifest.ts +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Geoff Seemueller
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# auto-agents-github-app-installer
|
|
2
|
+
|
|
3
|
+
Register a GitHub App for [auto-agents](https://github.com/geoffsee/auto-agents)'s code-review bot
|
|
4
|
+
via the [GitHub App Manifest Flow](https://docs.github.com/en/apps/sharing-github-apps/registering-a-github-app-from-a-manifest).
|
|
5
|
+
|
|
6
|
+
Run it from any repository — it spins up a local Bun server, opens your browser
|
|
7
|
+
to GitHub's app-registration form, exchanges the returned code for credentials,
|
|
8
|
+
and writes them where auto-agents expects.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
bunx auto-agents-github-app-installer
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
For an organization-owned app:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
GITHUB_ORG=my-org APP_NAME=my-auto-agents-bot bunx auto-agents-github-app-installer
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Environment variables
|
|
23
|
+
|
|
24
|
+
| Variable | Default | Purpose |
|
|
25
|
+
| ------------- | --------------------------------------- | --------------------------------------------------------------------------------------------- |
|
|
26
|
+
| `PORT` | `3000` | Port for the local callback server. |
|
|
27
|
+
| `GITHUB_ORG` | _(personal)_ | Register the app under this organization. |
|
|
28
|
+
| `APP_NAME` | `auto-agents-dev-bot` | Default name for the new app (editable on GitHub). |
|
|
29
|
+
| `WEBHOOK_URL` | `https://example.com/auto-agents-webhook` | Webhook target embedded in the manifest. GitHub requires a public URL even with `active=false`. |
|
|
30
|
+
|
|
31
|
+
### What it writes
|
|
32
|
+
|
|
33
|
+
- `~/.config/auto-agents/dev-ui-bot.pem` — the app's private key, `chmod 600`.
|
|
34
|
+
- `./.env.github-app` in the current directory — `DEV_BOT_APP_ID`, `DEV_BOT_PRIVATE_KEY`, etc.
|
|
35
|
+
|
|
36
|
+
After the flow completes:
|
|
37
|
+
|
|
38
|
+
1. Install the app on a repo via the URL printed in the terminal.
|
|
39
|
+
2. Copy the installation ID from the resulting URL into `DEV_BOT_INSTALLATION_ID` in `.env.github-app`.
|
|
40
|
+
3. `source .env.github-app && auto-agents`.
|
|
41
|
+
|
|
42
|
+
## Programmatic use
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { run } from "auto-agents-github-app-installer";
|
|
46
|
+
|
|
47
|
+
await run({
|
|
48
|
+
port: 4000,
|
|
49
|
+
owner: "my-org",
|
|
50
|
+
appName: "my-bot",
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Lower-level building blocks are exported from the package root: `buildManifest`,
|
|
55
|
+
`createHandler`, `convertCode`, `writeAppCredentials`, `formatEnvFile`,
|
|
56
|
+
`defaultConfigPaths`, `githubNewAppUrl`.
|
|
57
|
+
|
|
58
|
+
## Development
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
bun install
|
|
62
|
+
bun test
|
|
63
|
+
bun run typecheck
|
|
64
|
+
bun src/cli.ts # run locally
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Built on [Bun](https://bun.com); the published bin requires `bun` (use `bunx`, not `npx`).
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@auto-agents/github-app-installer",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Register a GitHub App for auto-agents via the App Manifest Flow. Run `bunx @auto-agents/github-app-installer` in any repo.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Geoff Seemueller",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/geoffsee/auto-agents-github-app-installer"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/geoffsee/auto-agents-github-app-installer/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/geoffsee/auto-agents-github-app-installer#readme",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"module": "./src/index.ts",
|
|
17
|
+
"main": "./src/index.ts",
|
|
18
|
+
"types": "./src/index.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": "./src/index.ts"
|
|
21
|
+
},
|
|
22
|
+
"bin": {
|
|
23
|
+
"auto-agents-github-app-installer": "./src/cli.ts"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"src",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"start": "bun src/cli.ts",
|
|
32
|
+
"test": "bun test",
|
|
33
|
+
"typecheck": "bunx tsc --noEmit",
|
|
34
|
+
"release": "bunx release-it",
|
|
35
|
+
"release:patch": "bunx release-it patch",
|
|
36
|
+
"release:minor": "bunx release-it minor",
|
|
37
|
+
"release:major": "bunx release-it major"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"auto-agents",
|
|
41
|
+
"github-app",
|
|
42
|
+
"github-app-manifest",
|
|
43
|
+
"code-review"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"bun": ">=1.3.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/bun": "latest"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"typescript": "^5"
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import {
|
|
3
|
+
type ConfigPaths,
|
|
4
|
+
defaultConfigPaths,
|
|
5
|
+
writeAppCredentials,
|
|
6
|
+
} from "./config.ts";
|
|
7
|
+
import { convertCode } from "./github.ts";
|
|
8
|
+
import { createHandler } from "./handler.ts";
|
|
9
|
+
import { buildManifest } from "./manifest.ts";
|
|
10
|
+
|
|
11
|
+
export interface RunOptions {
|
|
12
|
+
port?: number;
|
|
13
|
+
owner?: string;
|
|
14
|
+
appName?: string;
|
|
15
|
+
hookUrl?: string;
|
|
16
|
+
openBrowser?: (url: string) => void;
|
|
17
|
+
configPaths?: ConfigPaths;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function defaultOpenBrowser(url: string): void {
|
|
21
|
+
const cmd =
|
|
22
|
+
process.platform === "darwin"
|
|
23
|
+
? ["open", url]
|
|
24
|
+
: process.platform === "win32"
|
|
25
|
+
? ["cmd", "/c", "start", url]
|
|
26
|
+
: ["xdg-open", url];
|
|
27
|
+
Bun.spawn(cmd, { stdout: "ignore", stderr: "ignore" });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function run(opts: RunOptions = {}): Promise<void> {
|
|
31
|
+
const port = opts.port ?? Number(process.env.PORT ?? 3000);
|
|
32
|
+
const owner = opts.owner ?? process.env.GITHUB_ORG;
|
|
33
|
+
const appName = opts.appName ?? process.env.APP_NAME ?? "auto-agents-dev-bot";
|
|
34
|
+
const hookUrl = opts.hookUrl ?? process.env.WEBHOOK_URL;
|
|
35
|
+
const openBrowser = opts.openBrowser ?? defaultOpenBrowser;
|
|
36
|
+
|
|
37
|
+
const baseUrl = `http://localhost:${port}`;
|
|
38
|
+
const manifest = buildManifest({ appName, baseUrl, hookUrl });
|
|
39
|
+
const state = crypto.randomUUID();
|
|
40
|
+
const paths = opts.configPaths ?? defaultConfigPaths();
|
|
41
|
+
|
|
42
|
+
let resolveDone: () => void;
|
|
43
|
+
const done = new Promise<void>((r) => {
|
|
44
|
+
resolveDone = r;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const server = Bun.serve({
|
|
48
|
+
port,
|
|
49
|
+
fetch: createHandler({
|
|
50
|
+
manifest,
|
|
51
|
+
state,
|
|
52
|
+
owner,
|
|
53
|
+
exchangeCode: (code) => convertCode(code),
|
|
54
|
+
onSuccess: async (app) => {
|
|
55
|
+
await writeAppCredentials(app, paths);
|
|
56
|
+
queueMicrotask(() => {
|
|
57
|
+
server.stop();
|
|
58
|
+
resolveDone();
|
|
59
|
+
});
|
|
60
|
+
return { pemPath: paths.pemPath, envPath: paths.envPath };
|
|
61
|
+
},
|
|
62
|
+
}),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
console.log(`Listening on ${baseUrl} — opening browser…`);
|
|
66
|
+
openBrowser(baseUrl);
|
|
67
|
+
await done;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (import.meta.main) {
|
|
71
|
+
await run();
|
|
72
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
import type { AppCredentials } from "./github.ts";
|
|
6
|
+
|
|
7
|
+
export interface ConfigPaths {
|
|
8
|
+
configDir: string;
|
|
9
|
+
pemPath: string;
|
|
10
|
+
envPath: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const DEFAULT_ENV_FILE = ".env.github-app";
|
|
14
|
+
export const DEFAULT_PEM_NAME = "dev-ui-bot.pem";
|
|
15
|
+
|
|
16
|
+
export function defaultConfigPaths(cwd: string = process.cwd()): ConfigPaths {
|
|
17
|
+
const configDir = join(homedir(), ".config", "auto-agents");
|
|
18
|
+
return {
|
|
19
|
+
configDir,
|
|
20
|
+
pemPath: join(configDir, DEFAULT_PEM_NAME),
|
|
21
|
+
envPath: join(cwd, DEFAULT_ENV_FILE),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function formatEnvFile(
|
|
26
|
+
app: AppCredentials,
|
|
27
|
+
pemPath: string,
|
|
28
|
+
now: Date = new Date(),
|
|
29
|
+
): string {
|
|
30
|
+
return [
|
|
31
|
+
`# Generated by auto-agents-github-app-installer on ${now.toISOString()}`,
|
|
32
|
+
`# Install the app at ${app.html_url}/installations/new then fill in DEV_BOT_INSTALLATION_ID below.`,
|
|
33
|
+
`DEV_BOT_APP_ID=${app.id}`,
|
|
34
|
+
`DEV_BOT_INSTALLATION_ID=`,
|
|
35
|
+
`DEV_BOT_PRIVATE_KEY=${pemPath}`,
|
|
36
|
+
`# Reference values (not consumed by auto-agents):`,
|
|
37
|
+
`CLIENT_ID=${app.client_id}`,
|
|
38
|
+
`CLIENT_SECRET=${app.client_secret}`,
|
|
39
|
+
`WEBHOOK_SECRET=${app.webhook_secret}`,
|
|
40
|
+
"",
|
|
41
|
+
].join("\n");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function writeAppCredentials(
|
|
45
|
+
app: AppCredentials,
|
|
46
|
+
paths: ConfigPaths,
|
|
47
|
+
): Promise<void> {
|
|
48
|
+
await mkdir(paths.configDir, { recursive: true, mode: 0o700 });
|
|
49
|
+
await Bun.write(paths.pemPath, app.pem);
|
|
50
|
+
await Bun.$`chmod 600 ${paths.pemPath}`.quiet();
|
|
51
|
+
await Bun.write(paths.envPath, formatEnvFile(app, paths.pemPath));
|
|
52
|
+
}
|
package/src/github.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface AppCredentials {
|
|
2
|
+
id: number;
|
|
3
|
+
html_url: string;
|
|
4
|
+
pem: string;
|
|
5
|
+
client_id: string;
|
|
6
|
+
client_secret: string;
|
|
7
|
+
webhook_secret: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
11
|
+
|
|
12
|
+
export async function convertCode(
|
|
13
|
+
code: string,
|
|
14
|
+
fetchImpl: FetchLike = fetch,
|
|
15
|
+
): Promise<AppCredentials> {
|
|
16
|
+
const res = await fetchImpl(
|
|
17
|
+
`https://api.github.com/app-manifests/${code}/conversions`,
|
|
18
|
+
{
|
|
19
|
+
method: "POST",
|
|
20
|
+
headers: {
|
|
21
|
+
accept: "application/vnd.github+json",
|
|
22
|
+
"x-github-api-version": "2022-11-28",
|
|
23
|
+
"user-agent": "auto-agents-github-app-manifest",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`GitHub manifest conversion failed (${res.status}): ${await res.text()}`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return (await res.json()) as AppCredentials;
|
|
35
|
+
}
|
package/src/handler.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { AppCredentials } from "./github.ts";
|
|
2
|
+
import type { AppManifest } from "./manifest.ts";
|
|
3
|
+
import { githubNewAppUrl } from "./manifest.ts";
|
|
4
|
+
|
|
5
|
+
export interface HandlerDeps {
|
|
6
|
+
manifest: AppManifest;
|
|
7
|
+
state: string;
|
|
8
|
+
owner?: string;
|
|
9
|
+
exchangeCode: (code: string) => Promise<AppCredentials>;
|
|
10
|
+
onSuccess: (app: AppCredentials) => Promise<{ pemPath: string; envPath: string }>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function createHandler(deps: HandlerDeps): (req: Request) => Promise<Response> {
|
|
14
|
+
return async (req) => {
|
|
15
|
+
const url = new URL(req.url);
|
|
16
|
+
|
|
17
|
+
if (url.pathname === "/") {
|
|
18
|
+
const manifestJson = JSON.stringify(deps.manifest).replaceAll("'", "'");
|
|
19
|
+
const action = githubNewAppUrl(deps.state, deps.owner);
|
|
20
|
+
return new Response(
|
|
21
|
+
`<!doctype html>
|
|
22
|
+
<form id="f" action="${action}" method="post">
|
|
23
|
+
<input type="hidden" name="manifest" value='${manifestJson}' />
|
|
24
|
+
<button>Create GitHub App</button>
|
|
25
|
+
</form>
|
|
26
|
+
<script>document.getElementById("f").submit()</script>`,
|
|
27
|
+
{ headers: { "content-type": "text/html" } },
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (url.pathname === "/callback") {
|
|
32
|
+
if (url.searchParams.get("state") !== deps.state) {
|
|
33
|
+
return new Response("Invalid state", { status: 400 });
|
|
34
|
+
}
|
|
35
|
+
const code = url.searchParams.get("code");
|
|
36
|
+
if (!code) return new Response("Missing code", { status: 400 });
|
|
37
|
+
|
|
38
|
+
let app: AppCredentials;
|
|
39
|
+
try {
|
|
40
|
+
app = await deps.exchangeCode(code);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
43
|
+
return new Response(msg, { status: 502 });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const { pemPath, envPath } = await deps.onSuccess(app);
|
|
47
|
+
|
|
48
|
+
return new Response(
|
|
49
|
+
[
|
|
50
|
+
`Created GitHub App: ${app.html_url}`,
|
|
51
|
+
``,
|
|
52
|
+
`Wrote:`,
|
|
53
|
+
` ${pemPath} (private key, chmod 600)`,
|
|
54
|
+
` ${envPath} (DEV_BOT_APP_ID, DEV_BOT_PRIVATE_KEY)`,
|
|
55
|
+
``,
|
|
56
|
+
`Next steps:`,
|
|
57
|
+
` 1. Install the app on your repo: ${app.html_url}/installations/new`,
|
|
58
|
+
` 2. Copy the installation ID from the URL and set DEV_BOT_INSTALLATION_ID in ${envPath}.`,
|
|
59
|
+
` 3. source ${envPath} && auto-agents`,
|
|
60
|
+
``,
|
|
61
|
+
].join("\n"),
|
|
62
|
+
{ headers: { "content-type": "text/plain" } },
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return new Response("Not found", { status: 404 });
|
|
67
|
+
};
|
|
68
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export { run } from "./cli.ts";
|
|
2
|
+
export type { RunOptions } from "./cli.ts";
|
|
3
|
+
|
|
4
|
+
export {
|
|
5
|
+
buildManifest,
|
|
6
|
+
githubNewAppUrl,
|
|
7
|
+
DEFAULT_HOMEPAGE_URL,
|
|
8
|
+
DEFAULT_HOOK_URL,
|
|
9
|
+
} from "./manifest.ts";
|
|
10
|
+
export type { AppManifest, ManifestOptions } from "./manifest.ts";
|
|
11
|
+
|
|
12
|
+
export { convertCode } from "./github.ts";
|
|
13
|
+
export type { AppCredentials, FetchLike } from "./github.ts";
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
defaultConfigPaths,
|
|
17
|
+
formatEnvFile,
|
|
18
|
+
writeAppCredentials,
|
|
19
|
+
DEFAULT_ENV_FILE,
|
|
20
|
+
DEFAULT_PEM_NAME,
|
|
21
|
+
} from "./config.ts";
|
|
22
|
+
export type { ConfigPaths } from "./config.ts";
|
|
23
|
+
|
|
24
|
+
export { createHandler } from "./handler.ts";
|
|
25
|
+
export type { HandlerDeps } from "./handler.ts";
|
package/src/manifest.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface ManifestOptions {
|
|
2
|
+
appName: string;
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
homepageUrl?: string;
|
|
5
|
+
hookUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface AppManifest {
|
|
9
|
+
name: string;
|
|
10
|
+
url: string;
|
|
11
|
+
hook_attributes: { url: string; active: boolean };
|
|
12
|
+
redirect_url: string;
|
|
13
|
+
callback_urls: string[];
|
|
14
|
+
public: boolean;
|
|
15
|
+
default_permissions: Record<string, string>;
|
|
16
|
+
default_events: string[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const DEFAULT_HOMEPAGE_URL = "https://github.com/geoffsee/auto-agents";
|
|
20
|
+
|
|
21
|
+
// GitHub rejects manifests whose hook URL isn't publicly reachable, even when
|
|
22
|
+
// active=false. auto-agents doesn't consume webhooks for this dev bot, so default
|
|
23
|
+
// to a placeholder that passes validation; callers can override via hookUrl.
|
|
24
|
+
export const DEFAULT_HOOK_URL = "https://example.com/auto-agents-webhook";
|
|
25
|
+
|
|
26
|
+
export function buildManifest(opts: ManifestOptions): AppManifest {
|
|
27
|
+
return {
|
|
28
|
+
name: opts.appName,
|
|
29
|
+
url: opts.homepageUrl ?? DEFAULT_HOMEPAGE_URL,
|
|
30
|
+
hook_attributes: { url: opts.hookUrl ?? DEFAULT_HOOK_URL, active: false },
|
|
31
|
+
redirect_url: `${opts.baseUrl}/callback`,
|
|
32
|
+
callback_urls: [`${opts.baseUrl}/callback`],
|
|
33
|
+
public: false,
|
|
34
|
+
default_permissions: {
|
|
35
|
+
contents: "read",
|
|
36
|
+
pull_requests: "write",
|
|
37
|
+
issues: "write",
|
|
38
|
+
metadata: "read",
|
|
39
|
+
},
|
|
40
|
+
default_events: [],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function githubNewAppUrl(state: string, owner?: string): string {
|
|
45
|
+
return owner
|
|
46
|
+
? `https://github.com/organizations/${owner}/settings/apps/new?state=${state}`
|
|
47
|
+
: `https://github.com/settings/apps/new?state=${state}`;
|
|
48
|
+
}
|