mergie-cli 0.1.0 → 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/README.md CHANGED
@@ -30,7 +30,8 @@ review (just the new commits since last time) awkward, and can't help you naviga
30
30
 
31
31
  - **[Bun](https://bun.sh)** ≥ 1.2 (mergie's runtime).
32
32
  - **git** and the **[GitHub CLI](https://cli.github.com) (`gh`)**, authenticated
33
- (`gh auth login`). mergie reuses `gh`'s token for all API access and your git config for cloning.
33
+ (`gh auth login`). mergie reuses `gh`'s token for **both** API access and cloning it clones over
34
+ HTTPS via gh's credential helper, so **no SSH key or host-key setup is needed**.
34
35
  - *(Optional, for AI features)* Claude access for the Claude Agent SDK — e.g. an
35
36
  `ANTHROPIC_API_KEY` in your environment.
36
37
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mergie-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Review GitHub pull requests from a fast local web UI, driven by a small CLI.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "author": "Ayush Poddar",
@@ -174,13 +174,15 @@ function makeWorkspace(input: WorkspaceInputs): Workspace {
174
174
  const artifacts = artifactsRepo(db);
175
175
  const aiReviews = aiReviewsRepo(db);
176
176
  const aiReviewTracker = createAiReviewTracker();
177
- const sshUrl = `git@github.com:${ref.owner}/${ref.repo}.git`;
177
+ // Clone over HTTPS on the PR's own host (honours GitHub Enterprise), authed by
178
+ // the gh credential helper — reuses the user's gh login, no SSH setup needed.
179
+ const remoteUrl = `https://${ref.host}/${ref.owner}/${ref.repo}.git`;
178
180
  let cloned = false;
179
181
  let baselineSha = "";
180
182
 
181
183
  async function ensureClone(): Promise<void> {
182
184
  if (cloned) return;
183
- await git.cloneOrFetch(sshUrl, [`refs/pull/${ref.number}/head`, meta.baseRef]);
185
+ await git.cloneOrFetch(remoteUrl, [`refs/pull/${ref.number}/head`, meta.baseRef]);
184
186
  baselineSha = (await git.mergeBase(`origin/${meta.baseRef}`, meta.headSha)) || meta.baseRef;
185
187
  cloned = true;
186
188
  }
@@ -320,7 +322,7 @@ function makeWorkspace(input: WorkspaceInputs): Workspace {
320
322
  pr.body = fresh.body;
321
323
  pr.baseRef = fresh.baseRef;
322
324
  pr.headRef = fresh.headRef;
323
- await git.cloneOrFetch(sshUrl, [`refs/pull/${ref.number}/head`, fresh.baseRef]);
325
+ await git.cloneOrFetch(remoteUrl, [`refs/pull/${ref.number}/head`, fresh.baseRef]);
324
326
  baselineSha = (await git.mergeBase(`origin/${fresh.baseRef}`, fresh.headSha)) || fresh.baseRef;
325
327
  cloned = true;
326
328
  },
@@ -37,16 +37,18 @@ export interface GitService {
37
37
  /**
38
38
  * Ensure the repository is available locally and up to date.
39
39
  *
40
- * - If `<cloneDir>/.git` is absent: runs `git clone <sshUrl> <cloneDir>`.
40
+ * - If `<cloneDir>/.git` is absent: runs `git clone <remoteUrl> <cloneDir>`.
41
41
  * - If present: runs `git -C <cloneDir> fetch origin <refs...>`.
42
42
  *
43
+ * Both paths authenticate HTTPS remotes through the gh CLI credential helper
44
+ * (see {@link GH_CREDENTIAL_ARGS}), so no SSH key or host-key trust is needed.
43
45
  * Throws if the git process exits with a non-zero code; the error message
44
46
  * includes stderr so callers can surface the reason.
45
47
  *
46
- * @param sshUrl - SSH remote URL, e.g. `git@github.com:org/repo.git`.
47
- * @param refs - Ref names / refspecs to fetch (e.g. `["main", "refs/pull/1/head"]`).
48
+ * @param remoteUrl - HTTPS remote URL, e.g. `https://github.com/org/repo.git`.
49
+ * @param refs - Ref names / refspecs to fetch (e.g. `["main", "refs/pull/1/head"]`).
48
50
  */
49
- cloneOrFetch(sshUrl: string, refs: string[]): Promise<void>;
51
+ cloneOrFetch(remoteUrl: string, refs: string[]): Promise<void>;
50
52
 
51
53
  /**
52
54
  * List commits in the range `startSha..endSha`, ordered oldest → newest.
@@ -164,6 +166,18 @@ function wsArgs(ignoreWhitespace: boolean | undefined): readonly string[] {
164
166
  return ignoreWhitespace ? [IGNORE_WHITESPACE_ARG] : [];
165
167
  }
166
168
 
169
+ /**
170
+ * Per-command git config that authenticates HTTPS remotes via the **gh CLI's
171
+ * credential helper**, so cloning/fetching reuses the user's existing `gh`
172
+ * login (no separate SSH key or host-key trust required). The empty first
173
+ * helper resets any inherited helper; the second delegates to `gh`. Passed as
174
+ * `-c` flags so the user's global git config is never modified.
175
+ */
176
+ const GH_CREDENTIAL_ARGS = [
177
+ "-c", "credential.helper=",
178
+ "-c", "credential.helper=!gh auth git-credential",
179
+ ] as const;
180
+
167
181
  // ---------------------------------------------------------------------------
168
182
  // Internal helpers
169
183
  // ---------------------------------------------------------------------------
@@ -194,11 +208,11 @@ export function createGitService(
194
208
  runner: CommandRunner = bunRunner,
195
209
  ): GitService {
196
210
  return {
197
- async cloneOrFetch(sshUrl, refs) {
211
+ async cloneOrFetch(remoteUrl, refs) {
198
212
  const hasGit = existsSync(`${cloneDir}/.git`);
199
213
  const args: string[] = hasGit
200
- ? ["-C", cloneDir, "fetch", "origin", ...refs]
201
- : ["clone", sshUrl, cloneDir];
214
+ ? [...GH_CREDENTIAL_ARGS, "-C", cloneDir, "fetch", "origin", ...refs]
215
+ : [...GH_CREDENTIAL_ARGS, "clone", remoteUrl, cloneDir];
202
216
 
203
217
  const result = await runner.run("git", args);
204
218
  if (result.exitCode !== 0) {