feat: add GitLab MR support with --glab flag#153
feat: add GitLab MR support with --glab flag#153it-baron wants to merge 1 commit intomichaelshimeles:mainfrom
Conversation
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
|
@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. |
|
Related Documentation 1 document(s) may need updating based on files changed in this PR: Goshen Labs's Space Progress Spinner Enhancements and Settings DisplayView 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.Note: You must be authenticated to accept/decline updates. |
Greptile SummaryThis PR adds GitLab Merge Request support via a new
Confidence Score: 3/5
Important Files Changed
Flowchartflowchart 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"]
Last reviewed commit: 4773277 |
| 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; |
There was a problem hiding this 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:
| 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.| /** | ||
| * 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; | ||
| } | ||
| } |
There was a problem hiding this 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.
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.| 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}`); | ||
| } | ||
| } |
There was a problem hiding this 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.
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.
Summary
--glabCLI flag to enable GitLab Merge Request creation after task execution (mirrors existing--prflag for GitHub)cli/src/git/mr.tsmodule withcreateMergeRequest()that usesglab mr createunder the hood--glabis passedChanges
cli/src/cli/args.ts--glabflag definitioncli/src/cli/commands/run.ts--glaboption through to executioncli/src/config/types.tsglabfield to config typescli/src/execution/sequential.tscreateMergeRequest()post-taskcli/src/git/mr.tsglabCLIcli/src/git/mr.test.tscli/src/git/index.tscli/src/ui/settings.ts--glabsetting in UIMotivation
Ralphy already supports automatic GitHub PR creation via
--pr. Teams using GitLab needed parity. The--glabflag mirrors the same workflow but targets GitLab'sglab mr createcommand, keeping the two code paths cleanly separated.Test plan
cli/src/git/mr.test.ts)ralphy run --glabon a GitLab-hosted repo and verify MR is created--glaband verify no MR is created--pr(GitHub) still works unchangedcc @michaelshimeles