You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(scm): detect self-hosted GitLab out of the box with glab v1.5x (kunchenguid#346)
* fix(gitlab): drive self-hosted GitLab out-of-the-box with glab v1.5x
Make the GitLab backend work against self-hosted instances and the
current glab CLI without manual configuration.
Self-hosted detection:
- DetectProvider falls back to glab's configured hosts (config.yml,
honoring GLAB_CONFIG_DIR/XDG_CONFIG_HOME) when a remote's hostname
carries no "gitlab" marker, matching on the host key or its api_host.
Reads only what the user configured; no host is hardcoded; any
read/parse failure fails closed to ProviderUnknown.
- Add scm.ExtractHost to recover the host (sans port, lowercased) from
scp-style, URL, and ssh:// remotes, including IPv6 literals and
'@'-in-path edge cases.
glab v1.5x backend fixes:
- Scope `glab auth status` with --hostname <host>. Unscoped, it checks
every configured instance and fails if ANY has a stale token, falsely
reporting an authenticated repo as unauthenticated. Falls back to the
unscoped check when the host is unknown (fail-safe).
- Drop the removed `--state opened` flag from `glab mr list`; open is the
default in v1.5x and passing the unknown flag fails the whole command.
- Read pipeline jobs via the branch-independent REST endpoint
(`glab api projects/<group%2Fproject>/pipelines/<id>/jobs`) so they
work in the daemon's detached-HEAD worktree, where `glab ci get`
refuses to run. --paginate walks every page; the parser handles the
resulting concatenated JSON documents. Maps finished_at into
Check.CompletedAt for CI re-run detection. The legacy `glab ci get`
path remains as the fallback when no project path is known.
Structural polish:
- Locate the GitLab project-path parser in the gitlab backend as
exported gitlab.ProjectPath, mirroring github.RepoSlug, instead of a
private helper in the pipeline layer.
- Scope the Host via positional constructor params
New(cmd, cliAvailable, host, projectPath), matching the GitHub
backend, rather than an Options struct.
- Distinguish clean EOF from a malformed mid-stream document when
decoding paginated jobs: surface the decode error instead of silently
swallowing a corrupt page, while still returning any jobs that parsed.
- Escape each project-path segment with url.PathEscape (rejoined with
%2F) instead of a bare slash replacement.
* fix(gitlab): propagate paginated CI decode errors; tighten gitlab fallback test and ExtractHost subtests
Surface decode errors from paginated `glab api` output so a corrupt
later page can no longer hide a failed job. parseGitlabJobs previously
dropped the decode error whenever at least one job parsed, letting
GetChecks treat a partial slice as authoritative; a failed job on a
dropped page would then read green. It now returns the parsed checks
alongside any non-nil decode error.
Align the GetChecks fallback test fixture with the real invocation:
the fallback runs `glab ci get --pipeline-id <id> --output json
--with-job-details`, but the mock keyed on the command without
--with-job-details, so the case passed through the generic
unexpected-command path instead of the intended fallback-error path.
Convert TestExtractHost to t.Run subtests so each remote-URL case
reports independently, matching the table-driven convention used by the
neighboring tests in the file.
* no-mistakes(document): document out-of-the-box self-hosted GitLab detection in provider guide
* no-mistakes(document): document glab config env vars and self-hosted GitLab detection
* no-mistakes: apply CI fixes
Copy file name to clipboardExpand all lines: AGENTS.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -69,6 +69,12 @@ Safest local verification sequence after non-trivial changes:
69
69
- GitLab and Bitbucket fork MR/PR routing is intentionally out of scope until implemented end to end.
70
70
- If a legacy or manually edited row has `fork_url` for GitLab or Bitbucket, PR creation must skip instead of opening a self PR.
71
71
72
+
**GitLab Backend (`internal/scm/gitlab`)**
73
+
74
+
- The GitLab `Host` is constructed via `gitlab.New(cmd, cliAvailable, host, projectPath)`, mirroring the GitHub backend's positional constructor. `host` is the repo's GitLab hostname (from `scm.ExtractHost(UpstreamURL)`); `projectPath` is the `group/project` path (subgroups allowed, from `gitlab.ProjectPath` - which lives in the gitlab package next to the `Host` that consumes it, mirroring `github.RepoSlug`). Both are optional; passing `"", ""` reproduces the legacy unscoped behavior used by unit tests.
75
+
- glab's flag surface drifts between versions; the backend is pinned against `glab v1.5x`. Two flags bit us: `glab auth status` must be **host-scoped** with `--hostname <host>` (unscoped, it checks every configured instance and fails if ANY has a stale token, falsely reporting an authenticated repo as unauthenticated); and `glab mr list` no longer accepts `--state opened` (open is the default; v1.5x exposes `-c/--closed`, `-M/--merged`, `-A/--all`) - passing the removed flag fails the whole command. When the host is unknown, fall back to the unscoped auth check (fail-safe).
76
+
- The daemon operates in a **detached-HEAD worktree** (it checks out the commit, not a branch). `glab ci get` refuses to run there ("you're not on any Git branch (a 'detached HEAD' state)") even with an explicit `--pipeline-id`. Read pipeline jobs via the branch-independent REST endpoint instead: `glab api projects/<url-encoded group%2Fproject>/pipelines/<id>/jobs` (`Host.pipelineJobsArgs`). The legacy `glab ci get` path is kept only as the fallback when no project path is supplied. The `glab api .../jobs` payload carries `finished_at`, mapped into `Check.CompletedAt` (needed for CI re-run detection).
77
+
72
78
**Documentation**
73
79
74
80
- Keep `README.md` concise and high-level. The bar needs to be extremely high for what has to show up there.
Copy file name to clipboardExpand all lines: docs/src/content/docs/guides/provider-integration.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -140,6 +140,12 @@ These are GitHub and GitLab only right now.
140
140
141
141
Self-hosted GitHub Enterprise and self-hosted GitLab instances work through the same `gh` and `glab` CLIs. Authenticate the CLI against your instance (`gh auth login --hostname your-ghe.example.com`, `glab auth login --hostname gitlab.example.com`) and `no-mistakes` will route through the CLI as usual.
142
142
143
+
Self-hosted GitLab is detected out of the box even when the hostname carries no `gitlab` marker (for example `git.example.com`).
144
+
When the hostname is not obviously GitLab, `no-mistakes` consults glab's configured hosts (`config.yml`, honoring `GLAB_CONFIG_DIR` then `XDG_CONFIG_HOME/glab-cli`, then `~/.config/glab-cli`) and treats the upstream as GitLab if its host appears there as a configured host or `api_host`.
145
+
Running `glab auth login --hostname your-gitlab.example.com` is enough to make detection succeed; if glab is not configured for the host, detection fails closed and the upstream is treated as unsupported.
146
+
147
+
The GitLab backend is pinned against `glab v1.5x`. Self-hosted detection and the merge-request and CI steps rely on its current flag and API surface, so keep `glab` reasonably up to date.
148
+
143
149
## Unsupported hosts
144
150
145
151
If your upstream isn't GitHub, GitLab, or Bitbucket Cloud:
Copy file name to clipboardExpand all lines: docs/src/content/docs/guides/troubleshooting.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -191,6 +191,7 @@ Check the [Provider Integration](/no-mistakes/guides/provider-integration/) requ
191
191
- `gh auth status`shows not authenticated
192
192
- Bitbucket env vars not set in the daemon's environment
193
193
- Upstream is on a host that isn't supported (GitHub, GitLab, or `bitbucket.org`)
194
+
- Self-hosted GitLab on a hostname with no `gitlab` marker isn't detected because `glab` isn't configured for the host; run `glab auth login --hostname your-gitlab.example.com` so detection finds it
194
195
- A GitLab or Bitbucket repo record has a fork URL set; fork MR/PR routing is currently GitHub-only
195
196
- You pushed the default branch (PR step always skips on the default branch)
Copy file name to clipboardExpand all lines: docs/src/content/docs/reference/environment.md
+22Lines changed: 22 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -79,6 +79,28 @@ Data directory used to discover OpenCode transcripts for intent extraction.
79
79
When set, no-mistakes looks for OpenCode's intent transcript database at `$XDG_DATA_HOME/opencode/opencode.db`.
80
80
When unset, it falls back to `~/.local/share/opencode/opencode.db`.
81
81
82
+
## `GLAB_CONFIG_DIR`
83
+
84
+
Directory holding glab's `config.yml`, consulted when detecting self-hosted GitLab.
85
+
86
+
|||
87
+
|---|---|
88
+
| Type |`string`|
89
+
| Default | (none) |
90
+
91
+
When the upstream hostname carries no `gitlab` marker, no-mistakes reads glab's configured hosts from `$GLAB_CONFIG_DIR/config.yml` to decide whether the host is a GitLab instance. It takes precedence over `XDG_CONFIG_HOME`. See [Provider Integration](/no-mistakes/guides/provider-integration/#self-hosted-githubgitlab).
92
+
93
+
## `XDG_CONFIG_HOME`
94
+
95
+
Config directory used to locate glab's `config.yml` for self-hosted GitLab detection.
96
+
97
+
|||
98
+
|---|---|
99
+
| Type |`string`|
100
+
| Default |`~/.config`|
101
+
102
+
When `GLAB_CONFIG_DIR` is unset, no-mistakes looks for glab's configured hosts at `$XDG_CONFIG_HOME/glab-cli/config.yml`, falling back to `~/.config/glab-cli/config.yml` when `XDG_CONFIG_HOME` is unset.
0 commit comments