Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ Docs:

- Codex App Server docs: https://developers.openai.com/codex/sdk/#app-server

## Git Host Provider Abstraction (GitHub + GitLab)

MarCode supports both GitHub and GitLab (including self-hosted instances) for PR/MR operations. The integration is provider-agnostic:

- `GitHostCli` (service contract in `apps/server/src/git/Services/GitHostCli.ts`) defines the abstract interface.
- `GitHubCli` layer wraps `gh` CLI, `GitLabCli` layer wraps `glab` CLI.
- `RoutingGitHostCli` auto-detects the provider from `remote.origin.url` hostname, with fallback to `git config marcode.gitHostProvider github|gitlab` and CLI auth probing.
- `GitManager` depends only on `GitHostCli` — never on a specific provider.
- The web UI dynamically shows "PR" or "MR" labels based on `gitHostProvider` from `GitStatusResult`.
- Fork-based MR workflows for GitLab are deferred (graceful error).

When adding new git-host-specific functionality, implement it in both `GitHubCli.ts` and `GitLabCli.ts` layers behind the `GitHostCliShape` interface.

## Tailwind v4 Pitfall: `px-*` vs `pl-*`/`pr-*`

This project uses Tailwind CSS v4. In v4, `px-*` generates `padding-inline` (a logical CSS property) while `pl-*`/`pr-*` generate `padding-left`/`padding-right` (physical properties). Responsive variants (e.g. `sm:px-5`) are placed later in the generated stylesheet than non-responsive physical utilities (e.g. `pl-[90px]`), so the responsive `padding-inline` silently wins the cascade and overrides the physical `padding-left`.
Expand Down
16 changes: 12 additions & 4 deletions apps/server/src/git/Errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,26 @@ export class GitCommandError extends Schema.TaggedErrorClass<GitCommandError>()(
}

/**
* GitHubCliError - GitHub CLI execution or authentication failed.
* GitHostCliError - Git host CLI execution or authentication failed.
*
* Covers both GitHub (`gh`) and GitLab (`glab`) CLI errors.
*/
export class GitHubCliError extends Schema.TaggedErrorClass<GitHubCliError>()("GitHubCliError", {
export class GitHostCliError extends Schema.TaggedErrorClass<GitHostCliError>()("GitHostCliError", {
operation: Schema.String,
detail: Schema.String,
provider: Schema.optional(Schema.String),
cause: Schema.optional(Schema.Defect),
}) {
override get message(): string {
return `GitHub CLI failed in ${this.operation}: ${this.detail}`;
return `Git host CLI failed in ${this.operation}: ${this.detail}`;
}
}

/** @deprecated Use `GitHostCliError` instead. */
export type GitHubCliError = GitHostCliError;
/** @deprecated Use `GitHostCliError` instead. */
export const GitHubCliError = GitHostCliError;

/**
* TextGenerationError - Commit or PR text generation failed.
*/
Expand Down Expand Up @@ -63,5 +71,5 @@ export class GitManagerError extends Schema.TaggedErrorClass<GitManagerError>()(
export type GitManagerServiceError =
| GitManagerError
| GitCommandError
| GitHubCliError
| GitHostCliError
| TextGenerationError;
3 changes: 2 additions & 1 deletion apps/server/src/git/Layers/GitCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1600,6 +1600,7 @@ export const makeGitCore = (options?: { executeOverride?: GitCoreShape["execute"
const fetchPullRequestBranch: GitCoreShape["fetchPullRequestBranch"] = (input) =>
Effect.gen(function* () {
const remoteName = yield* resolvePrimaryRemoteName(input.cwd);
const prefix = input.refspecPrefix ?? "refs/pull";
yield* executeGit(
"GitCore.fetchPullRequestBranch",
input.cwd,
Expand All @@ -1608,7 +1609,7 @@ export const makeGitCore = (options?: { executeOverride?: GitCoreShape["execute"
"--quiet",
"--no-tags",
remoteName,
`+refs/pull/${input.prNumber}/head:refs/heads/${input.branch}`,
`+${prefix}/${input.prNumber}/head:refs/heads/${input.branch}`,
],
{
fallbackErrorMessage: "git fetch pull request branch failed",
Expand Down
3 changes: 2 additions & 1 deletion apps/server/src/git/Layers/GitHubCli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ layer("GitHubCliLive", (it) => {
baseRefName: "main",
headRefName: "feature/pr-threads",
state: "open",
updatedAt: null,
isCrossRepository: true,
headRepositoryNameWithOwner: "octocat/codething-mvp",
headRepositoryOwnerLogin: "octocat",
Expand All @@ -69,7 +70,7 @@ layer("GitHubCliLive", (it) => {
"view",
"#42",
"--json",
"number,title,url,baseRefName,headRefName,state,mergedAt,isCrossRepository,headRepository,headRepositoryOwner",
"number,title,url,baseRefName,headRefName,state,mergedAt,updatedAt,isCrossRepository,headRepository,headRepositoryOwner",
],
expect.objectContaining({ cwd: "/repo" }),
);
Expand Down
Loading