Skip to content

Comments

feat: add GitLab MR support with --glab flag#153

Open
it-baron wants to merge 1 commit intomichaelshimeles:mainfrom
it-baron:feat-glab-mr-support
Open

feat: add GitLab MR support with --glab flag#153
it-baron wants to merge 1 commit intomichaelshimeles:mainfrom
it-baron:feat-glab-mr-support

Conversation

@it-baron
Copy link

Summary

  • Adds --glab CLI flag to enable GitLab Merge Request creation after task execution (mirrors existing --pr flag for GitHub)
  • Introduces cli/src/git/mr.ts module with createMergeRequest() that uses glab mr create under the hood
  • Updates sequential execution pipeline to conditionally create MRs when --glab is passed
  • Includes unit tests for MR creation logic

Changes

File What changed
cli/src/cli/args.ts Added --glab flag definition
cli/src/cli/commands/run.ts Wires --glab option through to execution
cli/src/config/types.ts Added glab field to config types
cli/src/execution/sequential.ts Conditionally calls createMergeRequest() post-task
cli/src/git/mr.ts New module - GitLab MR creation via glab CLI
cli/src/git/mr.test.ts Tests for MR creation
cli/src/git/index.ts Re-exports MR module
cli/src/ui/settings.ts Displays --glab setting in UI

Motivation

Ralphy already supports automatic GitHub PR creation via --pr. Teams using GitLab needed parity. The --glab flag mirrors the same workflow but targets GitLab's glab mr create command, keeping the two code paths cleanly separated.

Test plan

  • Unit tests added (cli/src/git/mr.test.ts)
  • Manual: run ralphy run --glab on a GitLab-hosted repo and verify MR is created
  • Manual: run without --glab and verify no MR is created
  • Manual: verify --pr (GitHub) still works unchanged

cc @michaelshimeles

Add --glab CLI flag to create GitLab merge requests instead of GitHub
pull requests. When --glab is passed, it implies --create-pr and uses
glab CLI to create MRs with --target-branch/--source-branch syntax.

- Add mr.ts with createMergeRequest() and isGlabAvailable()
- Add createMr field to RuntimeOptions and ExecutionOptions
- Wire --glab flag through args, run command, and sequential execution
- Display [mr] instead of [pr] in settings when --glab is active
- Add tests for flag parsing and settings display
@vercel
Copy link

vercel bot commented Feb 16, 2026

@it-baron is attempting to deploy a commit to the Goshen Labs Team on Vercel.

A member of the Team first needs to authorize it.

@dosubot
Copy link

dosubot bot commented Feb 16, 2026

Related Documentation

1 document(s) may need updating based on files changed in this PR:

Goshen Labs's Space

Progress Spinner Enhancements and Settings Display
View Suggested Changes
@@ -8,8 +8,17 @@
 [See implementation](https://github.com/michaelshimeles/ralphy/blob/fc2df589969b5fe16d31eccb4e7ff91314e31776/cli/src/ui/spinner.ts#L9-L83)
 
 ### Display of Active Settings
-Active settings, such as `[fast]`, `[dry-run]`, `[parallel]`, `[sandbox]`, and others, are now shown in yellow next to the spinner's step label. These settings are determined at runtime based on the current execution options. For example, `[fast]` appears when both tests and linting are skipped, `[dry-run]` is shown when the dry-run mode is enabled, `[parallel]` when parallel execution is used, and `[sandbox]` when lightweight sandbox mode is enabled for parallel agents. The list of active settings is constructed by the `buildActiveSettings` function, which inspects the runtime options and returns an array of relevant flags. This array is passed to the spinner and rendered as a comma-separated list in the spinner output.  
+Active settings, such as `[fast]`, `[dry-run]`, `[parallel]`, `[sandbox]`, `[pr]`, and `[mr]`, are now shown in yellow next to the spinner's step label. These settings are determined at runtime based on the current execution options. For example, `[fast]` appears when both tests and linting are skipped, `[dry-run]` is shown when the dry-run mode is enabled, `[parallel]` when parallel execution is used, and `[sandbox]` when lightweight sandbox mode is enabled for parallel agents.
+
+#### Pull Request and Merge Request Settings
+- `[pr]` appears when the CLI is configured to create a GitHub Pull Request after each task (using `--create-pr` without `--glab`).
+- `[mr]` appears when the CLI is configured to create a GitLab Merge Request after each task (using the `--glab` flag, which implies `--create-pr`).
+- Only one of `[pr]` or `[mr]` will be shown at a time, depending on which workflow is active.
+
+The list of active settings is constructed by the `buildActiveSettings` function, which inspects the runtime options and returns an array of relevant flags. This array is passed to the spinner and rendered as a comma-separated list in the spinner output.  
 [See settings logic](https://github.com/michaelshimeles/ralphy/blob/fc2df589969b5fe16d31eccb4e7ff91314e31776/cli/src/ui/settings.ts#L7-L25)
+
+**Note:** The `[mr]` setting indicates that GitLab Merge Requests will be created using the `glab` CLI, while `[pr]` indicates GitHub Pull Requests using the standard workflow.
 
 ### Integration with Task Run Commands
 The spinner is tightly integrated with the task execution flow. When a task run command is invoked, the main run loop builds the list of active settings and passes them, along with the task description, to the spinner. The spinner starts immediately and updates its step label as the task progresses (for example, switching to "Working" when the AI engine begins processing, or to "Retry X" on retry attempts). If the task is a dry run, the spinner instantly marks the task as skipped. Upon completion, the spinner displays either a success or error message, including the final elapsed time and active settings.

[Accept] [Decline]

Note: You must be authenticated to accept/decline updates.

How did I do? Any feedback?  Join Discord

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 16, 2026

Greptile Summary

This PR adds GitLab Merge Request support via a new --glab CLI flag, mirroring the existing --create-pr GitHub workflow. It introduces cli/src/git/mr.ts which shells out to glab mr create, threads the createMr option through the config types, arg parser, run command, and sequential executor, and updates the settings display.

  • The --glab flag correctly implies createPr and branchPerTask detection, keeping the two code paths cleanly separated in sequential.ts
  • glab mr create stdout parsing may not extract the URL correctly — unlike gh pr create which outputs only the URL, glab outputs multi-line text. The current stdout.trim() approach will return the full output rather than just the MR URL
  • isGlabAvailable() is defined but never called — if glab CLI is missing or unauthenticated, MR creation silently fails with no user feedback. Consider adding an early availability check similar to the engine availability check
  • Tests cover flag parsing and settings display but not the createMergeRequest function itself

Confidence Score: 3/5

  • Low risk to existing functionality, but the new GitLab MR path has issues that will affect user experience
  • The existing --create-pr GitHub path is untouched and safe. The new --glab code path has a likely output parsing issue with glab mr create that would return multi-line text instead of a clean URL, and the unused isGlabAvailable() means users get no feedback when glab is not installed. These are not breaking issues but will degrade the GitLab MR experience.
  • cli/src/git/mr.ts needs attention for stdout URL extraction and the unused availability check

Important Files Changed

Filename Overview
cli/src/git/mr.ts New GitLab MR creation module. glab mr create stdout parsing may not correctly extract the URL, and isGlabAvailable() is defined but never used anywhere, leading to silent failures when glab CLI is missing.
cli/src/execution/sequential.ts Correctly wires MR creation into sequential execution pipeline with proper branching between PR/MR paths. Failures are silent (no logging on null return).
cli/src/cli/args.ts Correctly adds --glab flag and properly implies createPr when --glab is set. Clean integration with existing option parsing.
cli/src/cli/commands/run.ts Properly passes createMr through to both sequential and parallel execution options and adds it to base branch detection condition.
cli/src/config/types.ts Adds createMr boolean field to RuntimeOptions and DEFAULT_OPTIONS. Clean type extension.
cli/src/git/index.ts Adds re-export for new mr.ts module. Straightforward barrel export addition.
cli/src/git/mr.test.ts Good coverage for flag parsing and settings display. Missing unit tests for the actual createMergeRequest function itself (only tests args/settings).
cli/src/ui/settings.ts Correctly shows "mr" when both createPr and createMr are set, and "pr" when only createPr is set.

Flowchart

flowchart TD
    A["CLI: parseArgs()"] -->|"--glab flag"| B["createMr=true, createPr=true"]
    A -->|"--create-pr flag"| C["createPr=true, createMr=false"]
    B --> D["runLoop()"]
    C --> D
    D --> E{"parallel mode?"}
    E -->|yes| F["runParallel()"]
    E -->|no| G["runSequential()"]
    G --> H{"task success & createPr & branch?"}
    H -->|yes| I{"createMr?"}
    I -->|yes| J["pushBranchGlab()"]
    J --> K["glab mr create"]
    K --> L["logSuccess MR URL"]
    I -->|no| M["pushBranch()"]
    M --> N["gh pr create"]
    N --> O["logSuccess PR URL"]
    H -->|no| P["continue to next task"]
Loading

Last reviewed commit: 4773277

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +55 to +62
const { stdout, exitCode } = await execCommand("glab", args, workDir);

if (exitCode !== 0) {
return null;
}

// Return the MR URL (glab outputs the URL on success)
return stdout.trim() || null;
Copy link
Contributor

Choose a reason for hiding this comment

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

glab output includes more than a URL

glab mr create outputs multi-line text (e.g. "Creating merge request for branch into main in group/project\n\nhttps://gitlab.com/...") whereas gh pr create outputs only the URL. Using stdout.trim() here will return the entire multi-line output, not just the MR URL. This will result in messy log output and an incorrect return value if it's ever consumed as a URL.

Consider extracting the URL from the output:

Suggested change
const { stdout, exitCode } = await execCommand("glab", args, workDir);
if (exitCode !== 0) {
return null;
}
// Return the MR URL (glab outputs the URL on success)
return stdout.trim() || null;
const { stdout, exitCode } = await execCommand("glab", args, workDir);
if (exitCode !== 0) {
return null;
}
// glab outputs multi-line text; extract the URL (last line or first https:// match)
const urlMatch = stdout.match(/https?:\/\/\S+/);
return urlMatch ? urlMatch[0].trim() : stdout.trim() || null;
Prompt To Fix With AI
This is a comment left during a code review.
Path: cli/src/git/mr.ts
Line: 55:62

Comment:
**`glab` output includes more than a URL**

`glab mr create` outputs multi-line text (e.g. `"Creating merge request for branch into main in group/project\n\nhttps://gitlab.com/..."`) whereas `gh pr create` outputs only the URL. Using `stdout.trim()` here will return the entire multi-line output, not just the MR URL. This will result in messy log output and an incorrect return value if it's ever consumed as a URL.

Consider extracting the URL from the output:

```suggestion
	const { stdout, exitCode } = await execCommand("glab", args, workDir);

	if (exitCode !== 0) {
		return null;
	}

	// glab outputs multi-line text; extract the URL (last line or first https:// match)
	const urlMatch = stdout.match(/https?:\/\/\S+/);
	return urlMatch ? urlMatch[0].trim() : stdout.trim() || null;
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +65 to +75
/**
* Check if glab CLI is available and authenticated
*/
export async function isGlabAvailable(): Promise<boolean> {
try {
const { exitCode } = await execCommand("glab", ["auth", "status"], process.cwd());
return exitCode === 0;
} catch {
return false;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

isGlabAvailable() is never called

This function is defined but never used. The --glab flag will silently fail if the glab CLI is not installed or not authenticated — createMergeRequest returns null and the user gets no feedback. Consider calling isGlabAvailable() early in the execution pipeline (similar to isEngineAvailable) to provide a clear error message before task execution begins.

Prompt To Fix With AI
This is a comment left during a code review.
Path: cli/src/git/mr.ts
Line: 65:75

Comment:
**`isGlabAvailable()` is never called**

This function is defined but never used. The `--glab` flag will silently fail if the `glab` CLI is not installed or not authenticated — `createMergeRequest` returns `null` and the user gets no feedback. Consider calling `isGlabAvailable()` early in the execution pipeline (similar to `isEngineAvailable`) to provide a clear error message before task execution begins.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 195 to 224
if (createPr && branch && baseBranch) {
const prUrl = await createPullRequest(
branch,
baseBranch,
task.title,
`Automated PR created by Ralphy\n\n${aiResult.response}`,
draftPr,
workDir,
);
const description = `Automated ${createMr ? "MR" : "PR"} created by Ralphy\n\n${aiResult.response}`;

if (prUrl) {
logSuccess(`PR created: ${prUrl}`);
if (createMr) {
const mrUrl = await createMergeRequest(
branch,
baseBranch,
task.title,
description,
draftPr,
workDir,
);

if (mrUrl) {
logSuccess(`MR created: ${mrUrl}`);
}
} else {
const prUrl = await createPullRequest(
branch,
baseBranch,
task.title,
description,
draftPr,
workDir,
);

if (prUrl) {
logSuccess(`PR created: ${prUrl}`);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Silent failure when MR creation fails

When createMergeRequest returns null (e.g. push failure, glab not installed, auth failure), there is no error or warning logged — the code just silently continues. This makes debugging difficult for users. Consider adding an else branch to log a warning:

if (mrUrl) {
    logSuccess(`MR created: ${mrUrl}`);
} else {
    logWarn("Failed to create GitLab MR. Ensure 'glab' CLI is installed and authenticated.");
}

The same issue exists in the existing PR path (prUrl null case), but given this is new code, it's worth addressing here.

Prompt To Fix With AI
This is a comment left during a code review.
Path: cli/src/execution/sequential.ts
Line: 195:224

Comment:
**Silent failure when MR creation fails**

When `createMergeRequest` returns `null` (e.g. push failure, `glab` not installed, auth failure), there is no error or warning logged — the code just silently continues. This makes debugging difficult for users. Consider adding an else branch to log a warning:

```
if (mrUrl) {
    logSuccess(`MR created: ${mrUrl}`);
} else {
    logWarn("Failed to create GitLab MR. Ensure 'glab' CLI is installed and authenticated.");
}
```

The same issue exists in the existing PR path (`prUrl` null case), but given this is new code, it's worth addressing here.

How can I resolve this? If you propose a fix, please make it concise.

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.

1 participant