GitLab MR auto-merge check uses invalid glab mr view --json <fields> flag #273

Closed
opened 2026-08-18 07:05:52 +00:00 by david · 0 comments
Owner

Summary

The MR stage's GitLab merge poller fails immediately when checking mergeability, aborting the run with agent-failure:

[mr] ERROR stage failed (agent-failure): glab command failed: Command failed: glab mr view 5 --json mergeWhenPipelineSucceeds,hasConflicts

   ERROR

  Unknown flag: --json.

  Try --help for usage.

This happens on the deterministic (non-LLM) auto-merge polling path in runMrStage, so any GitLab run with autoMerge.enabled: true that reaches the mr stage fails at the very first mergeability check.

Root cause

GitLabMergePoller.isMergeable() in src/mr/services/gitlabMergePoller.ts calls:

await this.execCli('glab', [
  'mr',
  'view',
  String(input.mrNumber),
  '--json',
  'mergeWhenPipelineSucceeds,hasConflicts',
]);

This models glab's JSON flag on GitHub CLI's gh pr view --json <fields> syntax (comma-separated field selection). glab mr view has never supported this. Checked the full glab (gitlab-org/cli) tag history, v1.0.0 → v1.113.0:

  • Before v1.37.0 (893f5c94, "feat: Json output", 2024-03-07): mr view had no JSON output at all (text only).
  • v1.37.0 onward: JSON output added as -F, --output stringFormat output as: text, json — a format toggle, not a field selector. It always dumps the whole MR object; there is no field1,field2 syntax.
  • v1.100.0 ("karmstrong/jq-flag", May 2026): added a global --jq <expr> flag to filter the full JSON client-side, e.g. glab mr view 5 -F json --jq '.merge_when_pipeline_succeeds'.

No released version of glab supports --json <fields>. Upgrading the CLI will not fix this — the flag needs to change.

Also note: GitLab's JSON output uses snake_case field names (merge_when_pipeline_succeeds, has_conflicts), not the camelCase (mergeWhenPipelineSucceeds, hasConflicts) the parsing code in isMergeable() currently expects (RawGitLabMergeState interface) — this needs to be fixed at the same time or the check will silently always return the "not mergeable" branch.

Fix

In src/mr/services/gitlabMergePoller.ts, isMergeable():

  1. Change the CLI invocation to use a supported flag, e.g.:
    await this.execCli('glab', ['mr', 'view', String(input.mrNumber), '-F', 'json']);
    
    (optionally combine with --jq to pre-shape the object if only on glab >= v1.100.0 — but plain -F json + client-side parsing is safer and doesn't pin a minimum CLI version.)
  2. Update RawGitLabMergeState and the parsing logic in isMergeable() to read the snake_case fields (merge_when_pipeline_succeeds, has_conflicts) from the full MR JSON object instead of the nonexistent filtered fields.
  3. Update src/mr/services/gitlabMergePoller.test.ts mocks/fixtures to match the new command args and snake_case JSON shape.

Affected files

  • src/mr/services/gitlabMergePoller.ts
  • src/mr/services/gitlabMergePoller.test.ts

Acceptance criteria

  • GitLabMergePoller.isMergeable() calls glab mr view <n> -F json (no unsupported --json <fields> flag).
  • Parsing reads the correct snake_case JSON field names from the full MR object.
  • Unit tests updated to cover: mergeable, not-mergeable (pipeline pending), conflicts, malformed JSON.
  • npm run lint and npm test pass.
  • Manually verified against a real glab install (or a fixture capturing real glab mr view -F json output) that the shape assumptions hold.
## Summary The MR stage's GitLab merge poller fails immediately when checking mergeability, aborting the run with `agent-failure`: ``` [mr] ERROR stage failed (agent-failure): glab command failed: Command failed: glab mr view 5 --json mergeWhenPipelineSucceeds,hasConflicts ERROR Unknown flag: --json. Try --help for usage. ``` This happens on the deterministic (non-LLM) auto-merge polling path in `runMrStage`, so any GitLab run with `autoMerge.enabled: true` that reaches the `mr` stage fails at the very first mergeability check. ## Root cause `GitLabMergePoller.isMergeable()` in `src/mr/services/gitlabMergePoller.ts` calls: ```ts await this.execCli('glab', [ 'mr', 'view', String(input.mrNumber), '--json', 'mergeWhenPipelineSucceeds,hasConflicts', ]); ``` This models `glab`'s JSON flag on GitHub CLI's `gh pr view --json <fields>` syntax (comma-separated field selection). **`glab mr view` has never supported this.** Checked the full `glab` (gitlab-org/cli) tag history, v1.0.0 → v1.113.0: - **Before v1.37.0** (`893f5c94`, "feat: Json output", 2024-03-07): `mr view` had no JSON output at all (text only). - **v1.37.0 onward**: JSON output added as `-F, --output string` → `Format output as: text, json` — a format *toggle*, not a field selector. It always dumps the whole MR object; there is no `field1,field2` syntax. - **v1.100.0** ("karmstrong/jq-flag", May 2026): added a global `--jq <expr>` flag to filter the full JSON client-side, e.g. `glab mr view 5 -F json --jq '.merge_when_pipeline_succeeds'`. **No released version of `glab` supports `--json <fields>`.** Upgrading the CLI will not fix this — the flag needs to change. Also note: GitLab's JSON output uses **snake_case** field names (`merge_when_pipeline_succeeds`, `has_conflicts`), not the camelCase (`mergeWhenPipelineSucceeds`, `hasConflicts`) the parsing code in `isMergeable()` currently expects (`RawGitLabMergeState` interface) — this needs to be fixed at the same time or the check will silently always return the "not mergeable" branch. ## Fix In `src/mr/services/gitlabMergePoller.ts`, `isMergeable()`: 1. Change the CLI invocation to use a supported flag, e.g.: ```ts await this.execCli('glab', ['mr', 'view', String(input.mrNumber), '-F', 'json']); ``` (optionally combine with `--jq` to pre-shape the object if only on `glab >= v1.100.0` — but plain `-F json` + client-side parsing is safer and doesn't pin a minimum CLI version.) 2. Update `RawGitLabMergeState` and the parsing logic in `isMergeable()` to read the snake_case fields (`merge_when_pipeline_succeeds`, `has_conflicts`) from the full MR JSON object instead of the nonexistent filtered fields. 3. Update `src/mr/services/gitlabMergePoller.test.ts` mocks/fixtures to match the new command args and snake_case JSON shape. ## Affected files - `src/mr/services/gitlabMergePoller.ts` - `src/mr/services/gitlabMergePoller.test.ts` ## Acceptance criteria - [ ] `GitLabMergePoller.isMergeable()` calls `glab mr view <n> -F json` (no unsupported `--json <fields>` flag). - [ ] Parsing reads the correct snake_case JSON field names from the full MR object. - [ ] Unit tests updated to cover: mergeable, not-mergeable (pipeline pending), conflicts, malformed JSON. - [ ] `npm run lint` and `npm test` pass. - [ ] Manually verified against a real `glab` install (or a fixture capturing real `glab mr view -F json` output) that the shape assumptions hold.
david 2026-08-18 07:05:52 +00:00
  • closed this issue
  • added the
    bug
    label
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
david/pi-loop#273
No description provided.