Skip to content

Add remote repository publish and discovery support#2482

Merged
juliusmarminge merged 7 commits intomainfrom
t3code/remote-git-projects
May 4, 2026
Merged

Add remote repository publish and discovery support#2482
juliusmarminge merged 7 commits intomainfrom
t3code/remote-git-projects

Conversation

@juliusmarminge
Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge commented May 4, 2026

Summary

  • Add source control repository lookup, clone, and publish flows on the server, including provider-backed repository creation.
  • Extend GitHub and GitLab CLI integrations to create repositories and return clone URLs for newly created remotes.
  • Update source control discovery to treat unsupported Bitbucket support as unavailable rather than partially implemented.
  • Expand web UI and RPC contracts to expose remote repository actions through the command palette and git controls.
  • Add coverage for the new repository service and provider/CLI behavior.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test
  • Not run: manual browser verification of the new remote repository publish/discovery UI

Note

Medium Risk
Medium risk because it adds new RPC surface area and wiring across server+web for cloning/publishing, and changes GitVcsDriver.pushCurrentBranch semantics to optionally push to a specified remote (affecting publish behavior).

Overview
Enables remote repository workflows by introducing SourceControlRepositoryService with lookupRepository, cloneRepository, and publishRepository (create remote repo, add/ensure remote, push if commits exist; otherwise return remote_added).

Extends GitHub/GitLab provider layers to support createRepository (GitHub parses gh repo create stdout to avoid eventual-consistency races; GitLab resolves namespace IDs and normalizes clone URLs), adds new WS RPC methods (sourceControl.*) and client environmentApi bindings, and updates tests/contracts accordingly.

Updates the web UI to support Add project from remote (GitHub/GitLab/URL clone flow in CommandPalette) and a Publish repository wizard in GitActionsControl; quick actions/menu behavior changes when no primary remote exists. Also adjusts source control discovery to treat Bitbucket as unimplemented (no CLI probing, clearer messaging).

Reviewed by Cursor Bugbot for commit df59af7. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add remote repository publish and clone discovery support via GitHub and GitLab

  • Adds SourceControlRepositoryService with lookupRepository, cloneRepository, and publishRepository operations, backed by GitHub CLI and GitLab CLI providers.
  • Exposes the three operations as WebSocket RPCs (sourceControl.lookupRepository, sourceControl.cloneRepository, sourceControl.publishRepository) and wires them into EnvironmentApi.
  • Adds a multi-step clone flow to the command palette: users pick GitHub, GitLab, or Git URL, enter a repo, optionally look it up for SSH URL, then choose a destination and clone.
  • Adds a multi-step publish dialog to GitActionsControl: users select provider, repo name, visibility, and remote name; if the local repo has no commits, publish returns remote_added without pushing.
  • Changes the Git quick action to show 'Publish repository' (kind open_publish) instead of a disabled push hint when no primary remote is configured.
  • GitVcsDriverCore.pushCurrentBranch now accepts an optional remoteName to push to a specific remote instead of the configured upstream.
  • Behavioral Change: Bitbucket provider discovery now reports unknown auth state with an install hint instead of probing for auth, and discovery items may omit the executable field.

Macroscope summarized df59af7.

- add source control repository service for lookup, clone, and publish
- implement GitHub/GitLab repository creation and update discovery handling
- wire UI and server flows to use remote repository actions
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 190b8775-91e2-49d3-8e90-a5c923379be3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/remote-git-projects

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels May 4, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Publish push ignores newly configured remote name
    • Changed git.pushCurrentBranch(input.cwd, null) to git.pushCurrentBranch(input.cwd, remoteName) so the push targets the remote that was just configured by ensureRemote.

Create PR

Or push these changes by commenting:

@cursor push a5bc715907
Preview (a5bc715907)
diff --git a/apps/server/src/sourceControl/SourceControlRepositoryService.ts b/apps/server/src/sourceControl/SourceControlRepositoryService.ts
--- a/apps/server/src/sourceControl/SourceControlRepositoryService.ts
+++ b/apps/server/src/sourceControl/SourceControlRepositoryService.ts
@@ -292,7 +292,7 @@
         };
       }
 
-      const pushResult = yield* git.pushCurrentBranch(input.cwd, null);
+      const pushResult = yield* git.pushCurrentBranch(input.cwd, remoteName);
 
       return {
         repository: toRepositoryInfo(providerKind, urls),

You can send follow-ups to the cloud agent here.

Comment thread apps/server/src/sourceControl/SourceControlRepositoryService.ts Outdated
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented May 4, 2026

Approvability

Verdict: Needs human review

Substantial new feature adding remote repository clone and publish capabilities across backend services, CLI integrations, and UI. Introduces new user-facing workflows and has an unresolved comment about dialog state not resetting properly.

You can customize Macroscope's approvability policy. Learn more.

- Pass the ensured remote name through publish flow
- Push directly to that remote when publishing a repository
- Add coverage for remote-specific push behavior
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: GitLab clone URL used as web URL in browser
    • Changed normalizeRepositoryCloneUrls to use raw.web_url (the browser-friendly URL without .git suffix) instead of raw.http_url_to_repo for the url field, consistent with how GitHub's url field works.

Create PR

Or push these changes by commenting:

@cursor push 153bb29c80
Preview (153bb29c80)
diff --git a/apps/server/src/sourceControl/GitLabCli.ts b/apps/server/src/sourceControl/GitLabCli.ts
--- a/apps/server/src/sourceControl/GitLabCli.ts
+++ b/apps/server/src/sourceControl/GitLabCli.ts
@@ -176,7 +176,7 @@
 ): GitLabRepositoryCloneUrls {
   return {
     nameWithOwner: raw.path_with_namespace,
-    url: raw.http_url_to_repo || raw.web_url,
+    url: raw.web_url,
     sshUrl: raw.ssh_url_to_repo,
   };
 }

You can send follow-ups to the cloud agent here.

Comment thread apps/server/src/sourceControl/GitLabCli.ts
juliusmarminge and others added 2 commits May 3, 2026 17:42
- add publishRepository query key mock
- add sourceControlPublishRepository mutation options mock

Co-authored-by: codex <codex@users.noreply.github.com>
The normalizeRepositoryCloneUrls function was using http_url_to_repo (which
has a .git suffix) as the url field. This caused the 'Open on GitLab' button
to open a .git-suffixed URL and display it in the UI. Use web_url instead,
which is the proper browser URL and also works as an HTTPS clone URL.
@juliusmarminge
Copy link
Copy Markdown
Member Author

@cursor push 153bb29

The normalizeRepositoryCloneUrls function was using http_url_to_repo (which
has a .git suffix) as the url field. This caused the 'Open on GitLab' button
to open a .git-suffixed URL and display it in the UI. Use web_url instead,
which is the proper browser URL and also works as an HTTPS clone URL.

Applied via @cursor push command
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

Create PR

Or push these changes by commenting:

@cursor push df1160c81c
Preview (df1160c81c)
diff --git a/apps/server/src/sourceControl/GitLabCli.test.ts b/apps/server/src/sourceControl/GitLabCli.test.ts
--- a/apps/server/src/sourceControl/GitLabCli.test.ts
+++ b/apps/server/src/sourceControl/GitLabCli.test.ts
@@ -175,7 +175,7 @@
 
       assert.deepStrictEqual(result, {
         nameWithOwner: "octocat/t3code",
-        url: "https://gitlab.com/octocat/t3code.git",
+        url: "https://gitlab.com/octocat/t3code",
         sshUrl: "git@gitlab.com:octocat/t3code.git",
       });
     }),
@@ -243,7 +243,7 @@
 
       assert.deepStrictEqual(result, {
         nameWithOwner: "octocat/t3code",
-        url: "https://gitlab.com/octocat/t3code.git",
+        url: "https://gitlab.com/octocat/t3code",
         sshUrl: "git@gitlab.com:octocat/t3code.git",
       });
       expect(mockedRun).toHaveBeenNthCalledWith(

You can send follow-ups to the cloud agent here.

Comment thread apps/server/src/sourceControl/GitLabCli.test.ts
@juliusmarminge
Copy link
Copy Markdown
Member Author

@cursor push df1160c

…using web_url

The normalizeRepositoryCloneUrls function was changed to return raw.web_url
instead of raw.http_url_to_repo || raw.web_url, but the test assertions still
expected the http_url_to_repo value (with .git suffix). Updated both assertions
to expect the web_url value (without .git suffix).

Applied via @cursor push command
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Publish dialog doesn't reset visibility on close
    • Added resets for publishProvider, publishVisibility, and publishProtocol in the dialog's onOpenChange handler so they return to their safe defaults ("github", "private", "ssh") when the dialog closes.

Create PR

Or push these changes by commenting:

@cursor push f485be5715

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit df59af7. Configure here.

setPublishAdvancedOpen(false);
setPublishError(null);
setPublishResult(null);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Publish dialog doesn't reset visibility on close

Medium Severity

The publish dialog's onOpenChange handler resets most state (publishRemoteName, publishRepository, publishWizardStep, etc.) when the dialog closes, but omits resetting publishProvider, publishVisibility, and publishProtocol. The publishVisibility not resetting is particularly risky — if a user once selects "public" and later re-opens the dialog, it defaults to "public" instead of the safe "private" default, potentially causing accidental public repository creation.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit df59af7. Configure here.

@juliusmarminge juliusmarminge merged commit d796926 into main May 4, 2026
13 checks passed
@juliusmarminge juliusmarminge deleted the t3code/remote-git-projects branch May 4, 2026 01:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants