How the no-mistakes GitLab Backend Handles glab Version Compatibility
The no-mistakes GitLab backend detects unsupported flags at runtime, avoids arguments removed in newer glab releases, and falls back to alternative CLI patterns so it works across glab v1.x through current releases.
The internal/scm/gitlab package in kunchenguid/no-mistakes implements a resilient GitLab SCM host that does not require a pinned glab CLI version. By using runtime feature detection and scoped command construction, the backend maintains broad glab version compatibility without sacrificing access to merge requests, CI checks, or pipeline data.
Avoiding Removed Flags to Maintain glab Version Compatibility
The --state Flag Omission in FindPR
In internal/scm/gitlab/gitlab.go (lines 68–71), the FindPR method intentionally builds the glab mr list command without the --state flag. A source comment explains that while older glab releases accepted --state, the flag was removed in glab v1.5x. By omitting it entirely, the backend relies on glab's default behavior of returning only open merge requests, preventing command failures on newer installations.
// Example: finding a merge request without relying on the removed `--state` flag.
host := gitlab.New(cmdFactory, cliAvailable, "gitlab.example.com", "group/project")
pr, err := host.FindPR(ctx, "feature/xyz", "main")
// Internally this runs:
// glab mr list --source-branch feature/xyz --target-branch main --output json
This approach is locked in place by TestFindPRDoesNotPassRemovedStateFlag, which verifies that mr list is never invoked with the removed flag.
Runtime Fallbacks for glab Version Compatibility
Unsupported --mr Flag Detection in GetChecks
The GetChecks method first attempts to run glab ci status --mr <id>, a pattern added in newer glab releases. If the command fails, the helper isUnsupportedMRFlagError (lines 94–115) scans stderr for phrases such as "unknown flag" or "unsupported flag". When a compatibility issue is detected, the backend automatically falls back to getChecksFallback, which reconstructs the same data using an older-compatible workflow based on glab mr view and glab api.
// Example: getting CI checks, automatically falling back if `--mr` isn’t supported.
checks, err := host.GetChecks(ctx, &scm.PR{Number: "123"})
// If `glab ci status --mr 123` fails with an unknown‑flag error, the fallback
// performs:
// glab mr view 123 --output json
// glab api --paginate projects/.../pipelines/<id>/jobs
TestGetChecksFallsBackForVariantUnsupportedMRFlagErrors codifies this by injecting an "unrecognized arguments: --mr" error and asserting that the fallback path activates correctly.
Scoped Authentication and Robust Output Parsing
Host-Aware Auth Checks
The Available function (lines 21–33) prevents stale credentials for other GitLab instances from causing false negatives. When the repository host is known, it executes glab auth status --hostname <host> to scope the authentication check only to that instance. If the host is unknown, the backend gracefully falls back to the legacy unscoped call.
// Example: scoped authentication – only the repo’s host is consulted.
if err := host.Available(ctx); err != nil {
// Authentication failed for the specific host.
}
TestAvailableScopesAuthToConfiguredHost validates that the host-scoped auth call is issued when a host is configured.
Paginated API Calls and JSON Trimming
For detached-HEAD environments, the backend cannot rely solely on local git context. Instead, pipelineJobsArgs builds a glab api --paginate command (lines 95–108) to fetch pipeline jobs directly through the GitLab REST API. The --paginate flag is always included so that jobs spread across multiple result pages are fully retrieved.
Because different glab releases may prepend banner notices before JSON output, the helper bytesTrimToJSON (lines 92–100) strips any leading non-JSON text before the decoder processes the payload. This ensures consistent parsing regardless of CLI preamble formatting.
TestGetChecksPaginatesJobsAcrossConcatenatedPages confirms that concatenated paginated JSON is parsed correctly.
Summary
- The
FindPRmethod avoids the--stateflag removed in glab v1.5x, relying on open-by-defaultmr listbehavior to preserve glab version compatibility. GetChecksprobes for the--mrflag and usesisUnsupportedMRFlagErrorto trigger a fallback toglab mr viewplusglab apiwhen the flag is unrecognized.- Authentication checks in
Availableare scoped to the repository host via--hostname, preventing false negatives from unrelated credentials. pipelineJobsArgsalways includes--paginatefor complete job retrieval, whilebytesTrimToJSONsanitizes noisy CLI output before parsing.- Tests such as
TestFindPRDoesNotPassRemovedStateFlagandTestGetChecksFallsBackForVariantUnsupportedMRFlagErrorslock these compatibility behaviors in place.
Frequently Asked Questions
How does no-mistakes avoid breaking when glab removes a flag?
The backend never passes the removed --state flag to glab mr list. In internal/scm/gitlab/gitlab.go (lines 68–71), FindPR deliberately omits the flag because it was dropped in glab v1.5x, relying instead on the CLI's default of listing open merge requests.
What happens if glab ci status --mr is unsupported?
GetChecks tries the modern command first. If isUnsupportedMRFlagError (lines 94–115) detects an unknown-flag error in stderr, the backend routes to getChecksFallback, which gathers the same data through glab mr view and paginated glab api calls compatible with older releases.
Why does the GitLab backend scope glab auth status to a specific host?
Available passes --hostname <host> (lines 21–33) so authentication validation only considers credentials for that specific GitLab instance. This avoids false negatives caused by stale or unrelated host configurations in the user's glab CLI setup.
How does the backend handle glab versions that print banners before JSON?
The bytesTrimToJSON helper (lines 92–100) discards any leading non-JSON text before decoding. This ensures consistent parsing regardless of whether the installed glab version prints notices, warnings, or other preamble content.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →