Skip to content

feat: add Forgejo as a source control provider#3028

Open
pat-s wants to merge 24 commits into
pingdotgg:mainfrom
pat-s:forgejo-source-control-provider
Open

feat: add Forgejo as a source control provider#3028
pat-s wants to merge 24 commits into
pingdotgg:mainfrom
pat-s:forgejo-source-control-provider

Conversation

@pat-s

@pat-s pat-s commented Jun 10, 2026

Copy link
Copy Markdown

Closes #2536.

Summary

Adds Forgejo (Gitea-compatible) as a first-class source control provider alongside GitHub, GitLab, Bitbucket, and Azure DevOps.

Forgejo has no canonical hostname — every instance is self-hosted — so the provider:

  • Calls Forgejo's REST API (https://<host>/api/v1/...), mirroring the existing Bitbucket provider.
  • Reuses the fj CLI's login store: fj auth list (a CLI discovery spec) detects which self-hosted hosts are Forgejo, and keys.json supplies the per-host token. fj stays the tool you log in with; t3code never parses its human-readable output.
  • Supports multiple instances out of the box, since keys.json holds every logged-in instance and the API base URL is resolved per-repository from the git remote.

What's included

  • New forgejo provider kind, presentation ("pull request" terminology), and the official Forgejo logo (web + mobile).
  • ForgejoKeyStore (reads fj's keys.json), ForgejoApi (per-host REST client), forgejoPullRequests (schemas + normalization), and ForgejoSourceControlProvider (wrapper + fj CLI discovery), with unit tests.
  • All seven provider operations: list/get/create change requests, repository clone URLs, create repository, default branch, and checkout (Git-driver fetch like Bitbucket).
  • Wired into the provider registry, server/ws layers, the add-project clone flow (host/owner/repo), and the Source Control settings list.
  • Git-status terminology refines self-hosted Forgejo remotes via fj auth list so the UI shows "pull request" and the Forgejo icon (scoped to Forgejo only).

Notes

  • Requires the fj CLI for detection/auth (fj auth login <host>); the API calls themselves are over HTTP.
  • The "publish new repository" picker is intentionally left out of scope for now (its UI model assumes one fixed host per provider, which Forgejo lacks).

Note

Medium Risk
Touches git hosting resolution and a new authenticated HTTP provider path; behavior is scoped so only Forgejo refinement changes unknown remotes, with broad test coverage.

Overview
Adds Forgejo as a first-class source control provider (alongside GitHub, GitLab, Bitbucket, and Azure DevOps), aimed at self-hosted instances with no single canonical hostname.

The server introduces a Forgejo stack: REST client (ForgejoApi), credentials from the fj CLI keys.json (ForgejoKeyStore), PR schemas/normalization, and a provider wired into the registry and server/ws layers. CLI discovery via fj auth list marks logged-in hosts; refineRemoteProvider on the registry (used from GitManager.resolveHostingProvider) upgrades remotes that static URL detection leaves as unknown to Forgejo when the host matches an authenticated fj session.

Contracts and shared add the forgejo kind, PR terminology/icons, and heuristics for Codeberg/forgejo in hostnames while arbitrary self-hosted hosts stay unknown until refinement.

Web, mobile, and client-runtime expose Forgejo in add-project clone (host/owner/repo), command palette, source control settings, and shared readiness checks, with a Forgejo logo in UI components.

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

Note

Add Forgejo as a source control provider

  • Adds a full Forgejo provider integration across web, mobile, and server, covering PR listing/retrieval/creation, repository metadata, and PR checkout via the fj CLI.
  • Introduces ForgejoApi for authenticated HTTP to Forgejo instances and ForgejoKeyStore for reading fj credentials from the platform-specific keys.json file.
  • Adds ForgejoSourceControlProvider wired into the SourceControlProviderRegistry, including CLI-based discovery via fj auth list and refinement of unknown remotes to Forgejo when the host matches a logged-in account.
  • Detects Codeberg and self-hosted Forgejo instances by remote URL in sourceControl.ts; Codeberg is labeled separately from generic Forgejo hosts.
  • Adds ForgejoIcon to web and mobile UIs and registers forgejo as a valid SourceControlProviderKind in contracts, client runtime, and command palette.

Macroscope summarized f58be49.

pat-s added 17 commits June 10, 2026 09:37
Git status reported `unknown` for self-hosted hosts with no canonical
hostname (Forgejo, self-hosted GitLab), so the UI showed generic
"change request" wording instead of "pull request"/"merge request".
Fall back to the registry's refined resolution (fj auth list / glab auth
status) when static hostname detection can't classify the remote, so
status terminology and icons match what PR operations actually target.
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

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: f81d3937-2bc8-4008-858b-805d23d495df

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

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 and usage tips.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Jun 10, 2026
Comment thread apps/server/src/sourceControl/ForgejoApi.ts
Comment thread apps/server/src/sourceControl/ForgejoApi.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds a complete new source control provider (Forgejo) with API client, authentication, credential management, and UI integration. New integrations of this scope warrant human review. Additionally, an open review comment identifies a potential bug where status provider detection and PR lookup may use inconsistent provider resolution.

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

pat-s added 2 commits June 10, 2026 09:48
- resolveRepository now applies the sole-logged-in-host fallback (like
  createRepository) so a bare `owner/repo` spec works in the add-project
  clone flow, which runs in a directory with no git remotes.
- Match Forgejo host identities port-insensitively for credential lookup,
  host-list matching, and unknown-remote refinement, since `fj` keys its
  login store and `fj auth list` by bare hostname while remote URLs can
  carry a `:port`. API base URLs still keep the port.
Comment thread apps/server/src/sourceControl/ForgejoApi.ts Outdated
Forgejo's pulls list cannot filter by head branch, so listPullRequests
fetched the caller's `limit` rows and filtered in memory — with status
passing limit=1, the branch's PR was almost always hidden behind
unrelated recently-updated PRs. Fetch a full page (API max) and apply the
caller's limit to the branch-filtered matches instead.
Comment thread apps/server/src/sourceControl/ForgejoApi.ts Outdated
listPullRequests filtered only on head branch name, so an `owner:branch`
selector could match a same-named branch from a different fork. Also
match the head repository owner (falling back to the base repo owner for
same-repo PRs) so cross-repository PR lookups resolve the intended fork.
Comment thread apps/server/src/sourceControl/ForgejoApi.ts
parseForgejoRepositorySpec split on `/` only, so a pasted
`https://host/owner/repo` (or `git@host:owner/repo`) clone URL produced a
bogus host like `https:/host`. Detect scheme/`git@` specs and parse them
via parseForgejoRemoteUrl instead.
Comment thread apps/server/src/git/GitManager.ts
resolveHostingProvider fell back to resolveHandle (origin-based) to refine
self-hosted "unknown" remotes, so a logged-in Forgejo host on a non-origin
upstream stayed unknown in git status. Add a registry refineRemoteProvider
that refines a specific remote URL, and use it with the branch's resolved
remote so status reflects that remote (still Forgejo-only).

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1dfd06b. Configure here.

const refined = yield* sourceControlProviders
.refineRemoteProvider({ cwd, remoteName, remoteUrl })
.pipe(Effect.orElseSucceed(() => null));
return refined?.kind === "forgejo" ? refined : detected;

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.

Status provider mismatches PR lookup

Medium Severity

resolveHostingProvider can refine the branch’s tracking remote to forgejo and attach that as sourceControlProvider on local status, but findLatestPr still calls sourceControlProviders.resolve({ cwd }), which picks a provider from remotes (preferring origin) without the same branch-aware Forgejo refinement. Repos with a non-Forgejo origin and a Forgejo upstream can show Forgejo in the UI while open-PR lookup hits the wrong provider and misses the PR.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1dfd06b. Configure here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Leaving this as-is intentionally.

Git status resolves the hosting provider from the current branch's tracking remote (branch-aware, with Forgejo refinement), while PR lookup (findOpenPrresolve({ cwd })) resolves origin-first. These can only diverge in a multi-remote setup where origin points at a non-Forgejo host and the branch's upstream is a separate Forgejo remote.

In the common case — a Forgejo repo whose origin is the Forgejo instance — both paths resolve to Forgejo and agree. Fully reconciling the multi-remote case would require making the provider registry (and every PR operation) branch-aware, which changes remote selection for all providers; that's out of scope for this PR and noted as a potential follow-up.

Comment thread apps/server/src/sourceControl/ForgejoApi.ts Outdated
apiUrl hardcoded https://, so plain-http (local/LAN) Forgejo instances
had every REST call target the wrong scheme. Thread the scheme through
the repository locator (from the remote/clone URL; https default for SSH
and bare specs) and build API URLs from it.
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:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add Forgejo as Source Control Provider

1 participant