Skip to content

fix(repos): parse and preserve custom-user SSH remotes - #337

Merged
chriswritescode-dev merged 2 commits into
mainfrom
fix/ssh-remote-url-parsing
Aug 11, 2026
Merged

fix(repos): parse and preserve custom-user SSH remotes#337
chriswritescode-dev merged 2 commits into
mainfrom
fix/ssh-remote-url-parsing

Conversation

@chriswritescode-dev

@chriswritescode-dev chriswritescode-dev commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Custom-user SSH remotes (e.g. company@company.ghe.com:orga/repo.git) were misparsed: the scp-style matcher hardcoded the git@ user, so the URL fell through to the owner/repo shorthand and was stored as https://github.com/company@company.ghe.com:orga/repo. SSH URL syntax handling is now unified in shared/utils/repo.ts and applied across backend and frontend, so any user@host:path remote is detected, preserved, and deduplicated correctly. The compare key also converges the scp-with-port and ssh:// spellings, strips embedded credentials, and fails closed on malformed host segments. Fixes #336.

Summary

Type of Change

  • Bug fix
  • New feature
  • Refactor
  • Documentation

Checklist

  • Code follows project style (no comments, named imports)
  • TypeScript types are properly defined
  • Tests added/updated (80% coverage target)
  • pnpm lint passes locally
  • pnpm typecheck passes locally

Summary by CodeRabbit

  • New Features

    • Improved support for SSH and SCP-style repository URLs, including custom usernames and ports.
    • Added more consistent repository URL normalization and host detection across the application.
    • Preserved explicit HTTP and HTTPS protocol handling during URL comparisons.
  • Bug Fixes

    • Improved handling of shorthand SSH repository URLs and local or file-based repository paths.
    • Added comprehensive coverage for repository URL parsing, normalization, comparison, and credential handling.

SSH remotes with a non-git user (e.g. company@company.ghe.com:orga/repo.git)
were misparsed as GitHub shorthand and stored as
https://github.com/company@company.ghe.com:orga/repo. The scp-style matcher
hardcoded the git@ user, so custom-user remotes fell through to the
owner/repo shorthand branch.

SSH URL parsing is now unified in shared/utils/repo.ts and applied across
backend and frontend: any user@host:path remote is detected, preserved, and
deduplicated correctly. The compare key also converges the scp-with-port and
ssh:// spellings, strips embedded credentials, and fails closed on malformed
host segments.
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

SSH and SCP URL handling moved to shared utilities. The shared implementation supports custom SSH users, ports, host extraction, and comparison normalization. Backend and frontend consumers now use these helpers, with expanded repository URL tests.

Changes

SSH URL utility migration

Layer / File(s) Summary
Shared SSH and repository URL utilities
shared/src/utils/repo.ts, backend/test/utils/repo-url.test.ts
Added SSH and SCP detection, normalization, host extraction, generalized repository parsing, and comparison normalization. Added coverage for custom users, ports, credentials, shorthand URLs, and local paths.
Backend and frontend consumer migration
backend/src/utils/git-auth.ts, backend/src/services/..., frontend/src/components/repo/AddRepoDialog.tsx
Moved SSH helper imports to the shared package, removed the local SSH helpers, and updated repository normalization to accept arbitrary SCP-style usernames.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the primary fix for parsing custom-user SSH remotes.
Description check ✅ Passed The description explains the bug, fix, scope, linked issue, change type, and all required checklist items.
Linked Issues check ✅ Passed The changes address issue #336 by detecting arbitrary SSH users and preserving valid custom-user SSH remotes.
Out of Scope Changes check ✅ Passed The shared utility migration, cross-layer import updates, and focused tests support the linked SSH parsing fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ssh-remote-url-parsing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/services/repo.ts`:
- Around line 960-962: Update the SSH URL matching in the repository URL parsing
logic around sshMatch to reuse the shared SCP_STYLE_URL_PATTERN from
shared/src/utils/repo.ts instead of the local regex. Preserve the existing host
and path extraction behavior while ensuring malformed host segments containing
“/” are rejected consistently.
🪄 Autofix

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: eeb52925-081d-4430-8f57-96d9d3dd9d58

📥 Commits

Reviewing files that changed from the base of the PR and between cfe2031 and 78e48fb.

📒 Files selected for processing (8)
  • backend/src/services/git-auth.ts
  • backend/src/services/git/GitService.ts
  • backend/src/services/repo.ts
  • backend/src/services/schedule-worktree.ts
  • backend/src/utils/git-auth.ts
  • backend/test/utils/repo-url.test.ts
  • frontend/src/components/repo/AddRepoDialog.tsx
  • shared/src/utils/repo.ts
💤 Files with no reviewable changes (1)
  • backend/src/utils/git-auth.ts

Comment thread backend/src/services/repo.ts Outdated
Comment on lines +960 to +962
const sshMatch = url.match(/^([^@/:]+)@([^:]+):(.+?)(?:\.git)?$/)
if (sshMatch) {
const [, host, pathPart] = sshMatch
const [, , host, pathPart] = sshMatch

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject malformed SCP-style host segments.

Line 960 permits / in the host segment. For example, git@github.com/owner:repo becomes https://github.com/owner/repo instead of remaining invalid. This differs from SCP_STYLE_URL_PATTERN in shared/src/utils/repo.ts.

Use the shared pattern here so all consumers apply the same SSH URL contract.

Proposed fix
-import { normalizeRepoDirectoryName, sanitizeRepoDirectoryName, sanitizeBranchForDirectory, normalizeRepoUrlForCompare, isSSHUrl, normalizeSSHUrl } from '`@opencode-manager/shared/utils`'
+import { normalizeRepoDirectoryName, sanitizeRepoDirectoryName, sanitizeBranchForDirectory, normalizeRepoUrlForCompare, isSSHUrl, normalizeSSHUrl, SCP_STYLE_URL_PATTERN } from '`@opencode-manager/shared/utils`'
...
-  const sshMatch = url.match(/^([^`@/`:]+)@([^:]+):(.+?)(?:\.git)?$/)
+  const sshMatch = url.match(SCP_STYLE_URL_PATTERN)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const sshMatch = url.match(/^([^@/:]+)@([^:]+):(.+?)(?:\.git)?$/)
if (sshMatch) {
const [, host, pathPart] = sshMatch
const [, , host, pathPart] = sshMatch
const sshMatch = url.match(SCP_STYLE_URL_PATTERN)
if (sshMatch) {
const [, , host, pathPart] = sshMatch
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/services/repo.ts` around lines 960 - 962, Update the SSH URL
matching in the repository URL parsing logic around sshMatch to reuse the shared
SCP_STYLE_URL_PATTERN from shared/src/utils/repo.ts instead of the local regex.
Preserve the existing host and path extraction behavior while ensuring malformed
host segments containing “/” are rejected consistently.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • backend/src/services/repo.ts

Commit: ab69bcc00ed1f6677950bc5b3f9d5405fb63c42f

The changes have been pushed to the fix/ssh-remote-url-parsing branch.

Time taken: 5m 44s

Fixed 1 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
@chriswritescode-dev
chriswritescode-dev merged commit f7b47e6 into main Aug 11, 2026
2 checks passed
@chriswritescode-dev
chriswritescode-dev deleted the fix/ssh-remote-url-parsing branch August 11, 2026 00:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom-user SSH remotes parsed as GitHub URLs

1 participant