@bridge_gpt/mcp-server 0.2.23 → 0.2.25
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/README.md +96 -24
- package/build/commands.generated.js +4 -4
- package/build/conductor/epic-reconcile.js +7 -1
- package/build/conductor/epic-runtime.js +5 -0
- package/build/connect-github-api.js +365 -0
- package/build/connect-github.js +415 -0
- package/build/decision-page-schema.js +34 -5
- package/build/decision-page-template.js +126 -39
- package/build/docs.generated.js +5 -0
- package/build/index.js +1872 -633
- package/build/init.js +29 -0
- package/build/install-bridge.js +739 -91
- package/build/install-doctor.js +64 -0
- package/build/pipelines.generated.js +122 -128
- package/build/readme.generated.js +1 -1
- package/build/sfcc/log-gate.js +85 -0
- package/build/sfcc/log-query.js +170 -0
- package/build/sfcc/register.js +10 -0
- package/build/sfcc/setup-status.js +33 -3
- package/build/start-tickets.js +48 -13
- package/build/version.generated.js +1 -1
- package/{CONDUCTOR.md → docs/CONDUCTOR.md} +2 -2
- package/docs/install/github-app.md +252 -0
- package/docs/install/mcp-tool-integrations.md +305 -0
- package/docs/install/sfcc-integration.md +140 -0
- package/package.json +5 -5
- package/pipelines/learn-repository.json +111 -119
- package/public/css/main.min.css +258 -65
- package/public/css/main.min.css.map +1 -1
- package/public/js/main.min.js +233 -74
- package/public/js/main.min.js.map +1 -1
- package/smoke-test/SMOKE-TEST.md +3 -2
|
@@ -19,7 +19,8 @@ import { getAmToken } from "./client.js";
|
|
|
19
19
|
* 2. Repo name set (REPO_NAME)
|
|
20
20
|
* 3. version config field is an SFCC version
|
|
21
21
|
* 4. dw.json found / instance unambiguous
|
|
22
|
-
* 5. AM token acquisition
|
|
22
|
+
* 5. AM token acquisition (OCAPI Account Manager — NOT log/WebDAV access)
|
|
23
|
+
* 6. SFCC Log Query capability (WebDAV Basic auth — independent of steps 3–5)
|
|
23
24
|
*
|
|
24
25
|
* Never throws; each check is caught independently so partial states are
|
|
25
26
|
* always reported. Output is completely secret-free.
|
|
@@ -97,8 +98,37 @@ export async function sfccSetupStatusTool(deps) {
|
|
|
97
98
|
tokenStatus = `✗ ${msg}`;
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
|
-
lines.push(`5. AM Token: ${tokenStatus}`);
|
|
101
|
-
|
|
101
|
+
lines.push(`5. AM Token (OCAPI): ${tokenStatus}`);
|
|
102
|
+
// 6. SFCC Log Query capability — WebDAV Basic auth, independent of OCAPI/AM.
|
|
103
|
+
// A single Bridge backend probe (secret-free) reports readiness. This is a
|
|
104
|
+
// separate credential surface: an SFCC repo can have OCAPI working (steps 3–5)
|
|
105
|
+
// while log/WebDAV access is not configured, and vice versa.
|
|
106
|
+
let logQueryStatus = "— Skipped (Bridge API not configured)";
|
|
107
|
+
if (apiKeyOk && repoOk) {
|
|
108
|
+
try {
|
|
109
|
+
const url = deps.buildGetUrl("/sfcc/logs/capability", { repo_name: deps.repoName });
|
|
110
|
+
const resp = await fetch(url, { headers: await deps.getGetHeaders() });
|
|
111
|
+
if (!resp.ok) {
|
|
112
|
+
logQueryStatus = `✗ Could not read (Bridge API ${resp.status})`;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const body = (await resp.json());
|
|
116
|
+
if (body?.configured === true) {
|
|
117
|
+
logQueryStatus = "✓ Configured (WebDAV log access ready)";
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const msg = typeof body?.message === "string" ? body.message : "Not configured";
|
|
121
|
+
logQueryStatus = `✗ ${msg}`;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
logQueryStatus = `✗ Resolution error: ${err instanceof Error ? err.message : String(err)}`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
lines.push(`6. SFCC Log Query (WebDAV): ${logQueryStatus}`);
|
|
130
|
+
lines.push("\nRun `check_permissions` to probe OCAPI access once steps 1–5 are all green. " +
|
|
131
|
+
"Step 6 (log/WebDAV access) is independent and gates `sfcc_log_query`.");
|
|
102
132
|
return {
|
|
103
133
|
content: [{ type: "text", text: lines.join("\n") }],
|
|
104
134
|
};
|
package/build/start-tickets.js
CHANGED
|
@@ -1469,9 +1469,10 @@ const defaultPruneStaleLaunchScriptsDeps = {
|
|
|
1469
1469
|
* recursively. Newer entries and unrelated files/dirs are left untouched.
|
|
1470
1470
|
*
|
|
1471
1471
|
* Fully fail-open: any error (missing parent dir, unreadable entry, stat/unlink
|
|
1472
|
-
* failure) is swallowed and never blocks or aborts a spawn
|
|
1473
|
-
*
|
|
1474
|
-
* {@link
|
|
1472
|
+
* failure) is swallowed and never blocks or aborts a spawn. (Unconditionally so,
|
|
1473
|
+
* unlike {@link materializeWorkerLaunchCommand}, whose inline fallback is gated on
|
|
1474
|
+
* {@link MAX_TERMINAL_COMMAND_BYTES} — pruning a stale temp dir has no launchable/
|
|
1475
|
+
* unlaunchable axis to gate on.)
|
|
1475
1476
|
*/
|
|
1476
1477
|
export async function pruneStaleLaunchScripts(deps = defaultPruneStaleLaunchScriptsDeps) {
|
|
1477
1478
|
try {
|
|
@@ -1523,27 +1524,54 @@ export const defaultWriteWorkerLaunchScript = async ({ platform, key, content, }
|
|
|
1523
1524
|
await writeFile(file, content, { mode: 0o600 });
|
|
1524
1525
|
return file;
|
|
1525
1526
|
};
|
|
1527
|
+
/**
|
|
1528
|
+
* Canonical maximum UTF-8 byte length of a single command line handed to a
|
|
1529
|
+
* terminal spawner. macOS `osascript`-driven Terminal/iTerm keystroke delivery
|
|
1530
|
+
* silently truncates (or mangles) a longer line, so a command at or below this
|
|
1531
|
+
* bound is "known-launchable" and anything above it is "known-unlaunchable".
|
|
1532
|
+
*
|
|
1533
|
+
* Exported so the launcher and every install-flow guard read the SAME number:
|
|
1534
|
+
* two independently-written literals would silently drift apart, and the whole
|
|
1535
|
+
* point of the bound is that the launcher's fallback decision and the caller's
|
|
1536
|
+
* final pre-spawn check agree.
|
|
1537
|
+
*/
|
|
1538
|
+
export const MAX_TERMINAL_COMMAND_BYTES = 1024;
|
|
1526
1539
|
/**
|
|
1527
1540
|
* Resolve the command actually handed to the terminal spawner for one worker.
|
|
1528
1541
|
* When `deps.writeWorkerLaunchScript` is provided, the full command is persisted
|
|
1529
|
-
* to a script and a short `source <path>` runner is returned
|
|
1530
|
-
* for any reason the original inline command is returned (fail-open — a launch
|
|
1531
|
-
* never aborts because a temp file could not be written). When the seam is
|
|
1542
|
+
* to a script and a short `source <path>` runner is returned. When the seam is
|
|
1532
1543
|
* absent, the inline command is returned unchanged (legacy behaviour).
|
|
1544
|
+
*
|
|
1545
|
+
* The fail-open on a failed write is CONDITIONAL, and the condition is the point.
|
|
1546
|
+
* Falling back to the inline command is only a fallback if the terminal can
|
|
1547
|
+
* actually run it: above {@link MAX_TERMINAL_COMMAND_BYTES} the spawner truncates
|
|
1548
|
+
* the line, so "fail-open" would deliver a corrupted command — a silent, confusing
|
|
1549
|
+
* failure strictly worse than a loud one. So a failed write falls back inline only
|
|
1550
|
+
* at or below the bound, and returns a structured failure above it.
|
|
1533
1551
|
*/
|
|
1534
1552
|
export async function materializeWorkerLaunchCommand(deps, key, fullCommand) {
|
|
1535
1553
|
if (!deps.writeWorkerLaunchScript)
|
|
1536
|
-
return fullCommand;
|
|
1554
|
+
return { ok: true, command: fullCommand };
|
|
1537
1555
|
try {
|
|
1538
1556
|
const scriptPath = await deps.writeWorkerLaunchScript({
|
|
1539
1557
|
platform: deps.platform,
|
|
1540
1558
|
key,
|
|
1541
1559
|
content: buildLaunchScriptContent(deps.platform, fullCommand),
|
|
1542
1560
|
});
|
|
1543
|
-
return buildLaunchScriptRunnerCommand(deps.platform, scriptPath);
|
|
1561
|
+
return { ok: true, command: buildLaunchScriptRunnerCommand(deps.platform, scriptPath) };
|
|
1544
1562
|
}
|
|
1545
1563
|
catch {
|
|
1546
|
-
|
|
1564
|
+
// Bytes, not `.length`: the bound is a byte bound, and a multibyte prompt can
|
|
1565
|
+
// sit under 1024 JS characters while being well over 1024 UTF-8 bytes.
|
|
1566
|
+
if (Buffer.byteLength(fullCommand, "utf8") <= MAX_TERMINAL_COMMAND_BYTES) {
|
|
1567
|
+
return { ok: true, command: fullCommand };
|
|
1568
|
+
}
|
|
1569
|
+
return {
|
|
1570
|
+
ok: false,
|
|
1571
|
+
reason: "launch-script-write-failed-oversized-command",
|
|
1572
|
+
error: "Could not write the temporary launch script, and the full command is too long to send " +
|
|
1573
|
+
"to the terminal directly. Check that the system temporary directory is writable.",
|
|
1574
|
+
};
|
|
1547
1575
|
}
|
|
1548
1576
|
}
|
|
1549
1577
|
// ---------------------------------------------------------------------------
|
|
@@ -1569,10 +1597,17 @@ export async function spawnTabsForCreatedWorktrees(deps, rows, terminal, buildSh
|
|
|
1569
1597
|
// agents, or conductor disabled). Never mutates process/global env.
|
|
1570
1598
|
const shellCommand = injectConductorEnvIntoShellCommand(deps.platform, baseShellCommand, row.conductorEnv);
|
|
1571
1599
|
// Deliver the (potentially multi-KB) command via a launch-script file so the
|
|
1572
|
-
// terminal spawn payload stays tiny and escaping-immune.
|
|
1573
|
-
//
|
|
1574
|
-
|
|
1575
|
-
const
|
|
1600
|
+
// terminal spawn payload stays tiny and escaping-immune. No-op when no writer
|
|
1601
|
+
// seam is configured; a failed write falls back inline only while the command
|
|
1602
|
+
// is still launchable (see materializeWorkerLaunchCommand).
|
|
1603
|
+
const materialized = await materializeWorkerLaunchCommand(deps, row.key, shellCommand);
|
|
1604
|
+
if (!materialized.ok) {
|
|
1605
|
+
// Known-unlaunchable: spawning the oversized inline command would deliver a
|
|
1606
|
+
// truncated line. Fail this row only — siblings still launch.
|
|
1607
|
+
out.push({ ...row, status: "spawn-failed", error: materialized.error });
|
|
1608
|
+
continue;
|
|
1609
|
+
}
|
|
1610
|
+
const result = await deps.spawnTerminalTab(deps, terminal, materialized.command, {
|
|
1576
1611
|
key: row.key,
|
|
1577
1612
|
worktreePath: row.path,
|
|
1578
1613
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// AUTO-GENERATED — do not edit manually. Regenerate with: npm run build
|
|
2
|
-
export const VERSION = "0.2.
|
|
2
|
+
export const VERSION = "0.2.25";
|
|
@@ -8,7 +8,7 @@ involve Conductor — you opt in per run with `--conductor`.
|
|
|
8
8
|
This document is the reference for Conductor's architecture, epic setup,
|
|
9
9
|
observability stream, local git hooks, and the per-repo done-gate / auto-merge
|
|
10
10
|
config. For the everyday `start-tickets` flags and cross-platform behavior, see
|
|
11
|
-
[README → CLI Subcommands](
|
|
11
|
+
[README → CLI Subcommands](../README.md#cli-subcommands).
|
|
12
12
|
|
|
13
13
|
## Epic Conductor v2 — how an epic is actually driven
|
|
14
14
|
|
|
@@ -81,7 +81,7 @@ blocks or aborts a spawn, and `--dry-run` performs no conductor side effects.
|
|
|
81
81
|
When `--conductor` is set, the spawn boundary also injects
|
|
82
82
|
`BRIDGE_MCP_PROFILE=conductor` so each worker registers the 8 conductor/event/
|
|
83
83
|
supervisor MCP tools (a plain `start-tickets` run stays on the default `core`
|
|
84
|
-
profile). See [README → Environment Variables](
|
|
84
|
+
profile). See [README → Environment Variables](../README.md#environment-variables).
|
|
85
85
|
|
|
86
86
|
## `conductor install-git-hooks` (BAPI-395)
|
|
87
87
|
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Installing the Bridge GitHub App
|
|
2
|
+
|
|
3
|
+
Bridge connects to GitHub through a **GitHub App**, not a personal access token. Once
|
|
4
|
+
the app is installed on your repository and linked to your Bridge project, Bridge can
|
|
5
|
+
open pull requests, run automated code review, read CI check status, and (when enabled)
|
|
6
|
+
auto-merge — all using short-lived, per-call installation tokens. Your code and
|
|
7
|
+
credentials stay on GitHub; Bridge mints a fresh token for each operation and stores no
|
|
8
|
+
long-lived GitHub token.
|
|
9
|
+
|
|
10
|
+
## The app
|
|
11
|
+
|
|
12
|
+
| | |
|
|
13
|
+
|---|---|
|
|
14
|
+
| **Name** | Bridge GPT - AI Tools for SFCC |
|
|
15
|
+
| **Owner** | [@Bridge-GPT](https://github.com/Bridge-GPT) |
|
|
16
|
+
| **Public install page** | <https://github.com/apps/bridge-gpt-ai-tools-for-sfcc> |
|
|
17
|
+
| **App ID** | `954077` |
|
|
18
|
+
| **Client ID** | `Iv23liBEyDUeD25W06ix` |
|
|
19
|
+
|
|
20
|
+
> The App ID and Client ID are **public** identifiers (GitHub shows them on the app's
|
|
21
|
+
> settings page). They are not secrets. Only the app's **private key** and webhook
|
|
22
|
+
> secret are sensitive, and those are held by whoever operates the Bridge deployment —
|
|
23
|
+
> see [Self-hosting / operator setup](#self-hosting--operator-setup) at the end. As an
|
|
24
|
+
> end user you never handle them.
|
|
25
|
+
|
|
26
|
+
## Prerequisites
|
|
27
|
+
|
|
28
|
+
- A GitHub repository you want Bridge to work on.
|
|
29
|
+
- Permission to install a GitHub App on the account that owns it:
|
|
30
|
+
- **Personal repo:** you can install it yourself.
|
|
31
|
+
- **Organization repo:** you must be an **organization owner**, or a member who can
|
|
32
|
+
*request* the install for an owner to approve. (GitHub decides which button you see —
|
|
33
|
+
**Install**, **Install & request**, or **Request** — based on your role.)
|
|
34
|
+
- Your Bridge project already registered (you have a Bridge API key and repo name).
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Option A — `connect-github` from your terminal (recommended)
|
|
39
|
+
|
|
40
|
+
If you already have a Bridge API key configured (you ran `install-bridge`), you can
|
|
41
|
+
connect GitHub without opening the Bridge web UI at all:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx -y @bridge_gpt/mcp-server@latest connect-github --repo <repo_name>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Omit `--repo` and the command infers the project from the current directory, asking you
|
|
48
|
+
to confirm.
|
|
49
|
+
|
|
50
|
+
What happens:
|
|
51
|
+
|
|
52
|
+
1. The command opens the GitHub App install screen in your browser.
|
|
53
|
+
2. On GitHub, choose the **account or organization** that owns the repository, pick the
|
|
54
|
+
repositories under **Repository access** (see [Choosing
|
|
55
|
+
repositories](#choosing-repositories)), and click **Install**.
|
|
56
|
+
3. GitHub returns to a page that just says *"GitHub connection received — return to your
|
|
57
|
+
terminal."* That page is intentionally blank of detail; your terminal is where the
|
|
58
|
+
flow continues.
|
|
59
|
+
4. Back in the terminal, the command shows the repositories your installation covers and
|
|
60
|
+
asks which one to connect. **Every connection is confirmed by hand** — even when the
|
|
61
|
+
installation contains exactly one repository. There is no `--yes` flag.
|
|
62
|
+
5. Choose one, and it prints the connected `owner/repo`.
|
|
63
|
+
|
|
64
|
+
**You are never asked for a GitHub token, password, or installation ID.** You
|
|
65
|
+
authenticate to GitHub in your own browser; the terminal only ever carries a short-lived
|
|
66
|
+
Bridge-issued handle. Bridge never sees a GitHub credential.
|
|
67
|
+
|
|
68
|
+
**If you decline at the confirmation prompt**, nothing is connected and nothing is
|
|
69
|
+
changed — re-run the command whenever you like.
|
|
70
|
+
|
|
71
|
+
**If it times out or fails**, no connection is made. Re-run the command; the request
|
|
72
|
+
expires after about 15 minutes, so a stale attempt is never left half-applied.
|
|
73
|
+
|
|
74
|
+
### Organization approval
|
|
75
|
+
|
|
76
|
+
If an organization owns the repository and you are not an owner, GitHub sends an
|
|
77
|
+
**approval request** to an owner instead of installing the app. That approval happens
|
|
78
|
+
entirely on GitHub's side and **does not return to your terminal**, so `connect-github`
|
|
79
|
+
cannot wait for it — the original request expires. This is a real limitation, not a bug.
|
|
80
|
+
|
|
81
|
+
Once an owner has approved the install, finish the connection with
|
|
82
|
+
[Option C](#option-c--manual-install--installation-id-fallback) below.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Option B — Connect GitHub button (web UI)
|
|
87
|
+
|
|
88
|
+
Bridge captures the installation automatically — you never copy an ID by hand.
|
|
89
|
+
|
|
90
|
+
1. Open your project's **Get Started** page in the Bridge web UI. The page opens directly
|
|
91
|
+
on the GitHub connection task — connecting your repository is what the page is for.
|
|
92
|
+
2. In the **1. Connect GitHub** panel, click **Connect GitHub**. Bridge mints a
|
|
93
|
+
short-lived, single-use link scoped to your project and sends you to GitHub's
|
|
94
|
+
app-install screen.
|
|
95
|
+
3. On GitHub, choose the **account or organization** that owns the repository.
|
|
96
|
+
4. Under **Repository access**, choose **Only select repositories** and pick the repo(s)
|
|
97
|
+
you want Bridge to cover (or **All repositories**). See
|
|
98
|
+
[Choosing repositories](#choosing-repositories) below.
|
|
99
|
+
5. Review the requested permissions and click **Install** (or **Install & request** /
|
|
100
|
+
**Request** if an org owner must approve).
|
|
101
|
+
6. GitHub redirects you back to Bridge. Bridge verifies the installation directly with
|
|
102
|
+
GitHub, links it to your project, and stores the installation automatically. If the
|
|
103
|
+
installation covers exactly one repo — or one repo clearly matches your project —
|
|
104
|
+
Bridge binds it for you; otherwise it shows a short **repository picker** so you can
|
|
105
|
+
confirm which repo maps to this project.
|
|
106
|
+
7. The outcome appears in the **1. Connect GitHub** panel itself — you should see
|
|
107
|
+
**GitHub connected** naming the repository Bridge linked.
|
|
108
|
+
|
|
109
|
+
That's it — no manual ID entry. If the automatic link fails for any reason, Bridge tells
|
|
110
|
+
you in that same panel and points you to Option C.
|
|
111
|
+
|
|
112
|
+
Connecting an editor over MCP is **optional** and is not a prerequisite for any of the
|
|
113
|
+
above. If you need it, the Get Started page keeps that setup in a collapsed
|
|
114
|
+
**"Need to connect an editor to the MCP?"** drawer below the GitHub panel — open it only
|
|
115
|
+
if you want it.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Option C — Manual install + Installation ID (fallback)
|
|
120
|
+
|
|
121
|
+
This is the **advanced fallback**, not the normal path — use it only if neither the
|
|
122
|
+
`connect-github` command (Option A) nor the one-click **Connect GitHub** button (Option B)
|
|
123
|
+
is available to you (for example an org admin-approval or GitHub Marketplace install), or
|
|
124
|
+
if automatic linking failed. Get Started links to it from the manual-fallback note under
|
|
125
|
+
the GitHub panel.
|
|
126
|
+
|
|
127
|
+
### 1. Install the app
|
|
128
|
+
|
|
129
|
+
Go to the public install page and install it on the owning account/organization,
|
|
130
|
+
selecting the repository/repositories you want Bridge to access:
|
|
131
|
+
|
|
132
|
+
<https://github.com/apps/bridge-gpt-ai-tools-for-sfcc/installations/new>
|
|
133
|
+
|
|
134
|
+
(Same repository-selection and permissions-review screen as Option B, steps 3–5.)
|
|
135
|
+
|
|
136
|
+
### 2. Find the Installation ID
|
|
137
|
+
|
|
138
|
+
The Installation ID is the trailing number in the app's **Configure** URL:
|
|
139
|
+
|
|
140
|
+
- **Personal account:** open **Settings → Applications → Installed GitHub Apps**, click
|
|
141
|
+
**Configure** next to *Bridge GPT - AI Tools for SFCC*. The URL is
|
|
142
|
+
`https://github.com/settings/installations/<INSTALLATION_ID>`.
|
|
143
|
+
- **Organization:** open **Organization Settings → Third-party Access → GitHub Apps**,
|
|
144
|
+
click **Configure** next to the app. The URL is
|
|
145
|
+
`https://github.com/organizations/<ORG>/settings/installations/<INSTALLATION_ID>`.
|
|
146
|
+
|
|
147
|
+
For example, `https://github.com/organizations/Bridge-GPT/settings/installations/61661616`
|
|
148
|
+
has Installation ID **`61661616`**.
|
|
149
|
+
|
|
150
|
+
### 3. Enter it in Bridge
|
|
151
|
+
|
|
152
|
+
On your project's **Setup** page, in the GitHub section, paste the **Installation ID**
|
|
153
|
+
into the field provided and save. Make sure the project's **version control system** is
|
|
154
|
+
set to `github`. Bridge fills in the account owner and repository from your project
|
|
155
|
+
settings.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Choosing repositories
|
|
160
|
+
|
|
161
|
+
When installing (any option), GitHub asks which repositories the app may access:
|
|
162
|
+
|
|
163
|
+
- **All repositories** — the app can access every current and future repo on the account.
|
|
164
|
+
- **Only select repositories** — pick specific repos from the **Select repositories**
|
|
165
|
+
dropdown. Recommended: grant only the repo(s) you actually want Bridge to work on.
|
|
166
|
+
|
|
167
|
+
You can change this later at any time: **Configure** the installation (paths above),
|
|
168
|
+
adjust **Repository access**, and click **Save**. If the app creates a repository, it is
|
|
169
|
+
automatically granted access to that repo.
|
|
170
|
+
|
|
171
|
+
## What the app can access
|
|
172
|
+
|
|
173
|
+
At install time GitHub shows the **authoritative** list of permissions the app requests —
|
|
174
|
+
review it there. Functionally, the Bridge integration exercises these GitHub permissions:
|
|
175
|
+
|
|
176
|
+
| Permission | Why |
|
|
177
|
+
|---|---|
|
|
178
|
+
| **Contents** (read & write) | Read repo files for parsing/review; manage branch refs when opening/cleaning up PRs |
|
|
179
|
+
| **Pull requests** (read & write) | List/read PRs and diffs; post review comments and reviews; merge when auto-merge is enabled |
|
|
180
|
+
| **Checks / Commit statuses** (read) | Poll CI check-run and status results for a commit |
|
|
181
|
+
| **Administration** (read) | Read branch-protection required-status-checks to resolve which checks must pass |
|
|
182
|
+
| **Metadata** (read) | Baseline repo metadata; verify the installation's repository list |
|
|
183
|
+
| **Webhook events** | Receive `pull_request`, `installation`, and review/merge events that drive automated review and merge |
|
|
184
|
+
|
|
185
|
+
> These are inferred from the GitHub REST endpoints the integration calls. The exact set
|
|
186
|
+
> the app is *registered* with is shown by GitHub on the install screen; treat that
|
|
187
|
+
> screen as the source of truth.
|
|
188
|
+
|
|
189
|
+
## Verifying the connection
|
|
190
|
+
|
|
191
|
+
After linking, confirm Bridge can act on the repo:
|
|
192
|
+
|
|
193
|
+
- The Bridge **Setup / integration status** should show version control as connected.
|
|
194
|
+
- A Bridge operation that needs GitHub — e.g. `create_pull_request`, `resolve_ci_checks`,
|
|
195
|
+
or `poll_ci_checks` from the MCP — should succeed rather than return a
|
|
196
|
+
"no VCS connection" refusal. (See
|
|
197
|
+
[MCP Tool Integration Dependencies](./mcp-tool-integrations.md) for which tools require
|
|
198
|
+
a VCS connection.)
|
|
199
|
+
|
|
200
|
+
If a GitHub-dependent tool refuses, the installation isn't linked to that project yet —
|
|
201
|
+
re-run Option A, or set the Installation ID via Option C.
|
|
202
|
+
|
|
203
|
+
## Managing or removing the app
|
|
204
|
+
|
|
205
|
+
- **Change repo access / review permissions:** **Configure** the installation (URLs
|
|
206
|
+
above) → adjust **Repository access** → **Save**.
|
|
207
|
+
- **Uninstall:** on the same Configure page, scroll to **Danger zone → Uninstall**.
|
|
208
|
+
Uninstalling revokes Bridge's access immediately; existing stored installation IDs stop
|
|
209
|
+
working.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Self-hosting / operator setup
|
|
214
|
+
|
|
215
|
+
*Skip this section if you are an end user connecting to a hosted Bridge deployment — it is
|
|
216
|
+
for whoever runs the Bridge API server.*
|
|
217
|
+
|
|
218
|
+
The GitHub App identity is configured **once per deployment** via environment variables.
|
|
219
|
+
Bridge uses the App private key to mint short-lived installation tokens on demand; it
|
|
220
|
+
persists no long-lived GitHub token.
|
|
221
|
+
|
|
222
|
+
| Env var | Value / purpose |
|
|
223
|
+
|---|---|
|
|
224
|
+
| `GIT_APP_ID` | The app's numeric App ID — `954077` for *Bridge GPT - AI Tools for SFCC*. |
|
|
225
|
+
| `GIT_PRIVATE_KEY` | **base64-encoded PEM** private key generated for the app (GitHub → app settings → *Generate a private key*). This is the one true secret. |
|
|
226
|
+
| `GITHUB_APP_INSTALL_URL` | The public install URL the **Connect GitHub** button sends users to: `https://github.com/apps/bridge-gpt-ai-tools-for-sfcc/installations/new`. |
|
|
227
|
+
| `GITHUB_WEBHOOK_SECRET` | App-level shared secret validating signed `installation` / merge webhooks. If unset, those webhooks are disabled (the redirect-callback path still works). |
|
|
228
|
+
| `BGPT_ENCRYPTION_KEY` | Fernet key used to encrypt per-repo credentials at rest. |
|
|
229
|
+
|
|
230
|
+
The app's **Setup URL** (in GitHub app settings) must point at the deployment's
|
|
231
|
+
`GET /setup/github/callback` endpoint so the post-install redirect can auto-link the
|
|
232
|
+
installation. Webhook endpoints used by the integration include the code-review hook
|
|
233
|
+
(e.g. `https://<deployment-host>/github/code-review`); configure these on the app to match
|
|
234
|
+
your deployment host.
|
|
235
|
+
|
|
236
|
+
> **Note:** the install URL is published from two independent places, and only one reads
|
|
237
|
+
> the environment. `GITHUB_APP_INSTALL_URL` drives the get-started **Connect GitHub**
|
|
238
|
+
> button. The setup *instructions* — the install-instructions API, the capability report's
|
|
239
|
+
> `configure_in`, and the generated README region — come from the `GITHUB_APP_INSTALL_URL`
|
|
240
|
+
> constant in `api/library/config/integration_instructions.py`, which is **not**
|
|
241
|
+
> env-overridable. Setting the env var alone will not correct the instructions. Keep the
|
|
242
|
+
> two in sync; after editing the constant, regenerate the README with
|
|
243
|
+
> `python scripts/sync_integration_readme.py`.
|
|
244
|
+
|
|
245
|
+
## See also
|
|
246
|
+
|
|
247
|
+
- [MCP Tool Integration Dependencies](./mcp-tool-integrations.md) — which MCP tools need a
|
|
248
|
+
VCS connection (BLOCK) vs merely degrade without one.
|
|
249
|
+
- [Installing the SFCC Integration (OCAPI)](./sfcc-integration.md) — the separate
|
|
250
|
+
Salesforce B2C sandbox integration.
|
|
251
|
+
- GitHub docs: [Installing a GitHub App from a third party](https://docs.github.com/en/apps/using-github-apps/installing-a-github-app-from-a-third-party),
|
|
252
|
+
[Reviewing and modifying installed GitHub Apps](https://docs.github.com/en/apps/using-github-apps/reviewing-and-modifying-installed-github-apps).
|