GitLab
What it gives you — the Learn loop on a self-hosted or gitlab.com project: verified root causes drafted as merge requests against your knowledge-catalog repo, via a scoped project or group access token. This is what lets a self-hosted GitLab team — the archetype of RunLore’s lock-in-averse, sovereignty-conscious audience — use the curation loop at all.
Minimal config
forge:
provider: gitlab # github (default) | gitlab
kb_repo: your-group/runlore-kb
base_branch: main
gitlab:
base_url: https://gitlab.example.com # omit for gitlab.com
token_env: GITLAB_TOKENCreate the token
GitLab has no GitHub-App equivalent bot identity — OAuth apps are the wrong shape for a headless
curator, so auth is a project or group access token, sent as the PRIVATE-TOKEN header on every
request.
- Project → Settings → Access Tokens (or Group → Settings → Access Tokens to scope one token across every project group-wide).
- Role: Developer at minimum — creating a branch, committing the drafted entry, and opening a
merge request all need it. Give Maintainer only if
base_branchis a protected branch your project requires a higher role to push feature branches against. - Scope:
api— the full API scope; GitLab has no finer-grained scope that still covers creating commits, merge requests, and labels. - Set an expiration date and rotate before it lapses — an expired token fails closed (every forge call 401s), it does not silently disable curation.
- Copy the token once (GitLab shows it only at creation time) and store it as a Secret:
kubectl -n runlore create secret generic runlore-secrets \
--from-literal=GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxxVerify it locally
kubectl -n runlore logs deploy/runlore | grep 'curator enabled'Fire a test incident that produces a verified root cause and confirm a merge request lands on the KB project:
kubectl -n runlore logs deploy/runlore | grep 'msg=curated url='Check the token’s effective scope directly against the API (a 404 here — rather than a permissions error — is almost always the URL-encoding gotcha below, not a scope problem):
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.example.com/api/v4/projects/your-group%2Frunlore-kb"Notes
kb_repois a project PATH, not a numeric ID (group/project, or a nestedgroup/subgroup/project) — RunLore URL-encodes it into the API path (group%2Fproject) on every call, per the GitLab v4 API’s own requirement. Getting this encoding wrong is the single most common GitLab-client bug, and it 404s in a way that reads exactly like a permissions problem, so check the encoding first if merge requests never appear.base_urlis the instance root, e.g.https://gitlab.example.com— RunLore appends/api/v4itself. Omit it entirely for gitlab.com.- Auth is a static credential (unlike GitHub’s short-lived, minted App installation tokens) —
referenced by env-var indirection only (
token_envnames the variable; the config file never holds the token itself). Never commit the token or put it invalues.yaml. Store it in aSecret, ideally synced from a vault via External Secrets, and rotate it periodically. provider: gitlabwith noforge.gitlab.token_env, or akb_repothat isn’t a valid GitLab project path, both fail config load closed —serverefuses to start rather than coming up with curation silently disabled.- The same token clones private repos:
what_changedfetching your GitOps repo,source_difffetching an allowlisted source repo, and the catalog git-sync reading the KB project all authenticate with it over HTTPS. It was GitHub-App-only before, which meant a GitLab deployment cloned a private GitOps repo anonymously andwhat_changedsilently produced nothing. Give the tokenread_repositoryreach over the projects you want diffed (theapiscope already covers it), or those clones 404. - The token is sent only to the host in
base_url(gitlab.comwhen it is omitted). A GitOpsspec.source.repoURLpointing anywhere else clones anonymously — a repoURL is cluster state, so it must never be able to choose where RunLore’s credential goes. - TLS verification is always on; there is no
insecure_skip_verifyescape hatch. A self-signed instance needs a certificate your cluster’s trust store already accepts. - Not yet verified against a live GitLab instance. The provider is built against the GitLab v4
REST API (Commits, Merge Requests, Issues, Notes), whose surface has been stable for years, and it
is covered by tests that assert the exact requests it sends — but no one has yet run it end to end
against a real self-managed instance or gitlab.com. If you are the first, please
tell us what you find. The most likely rough edges are a
reverse proxy normalising the
%2Fin an encoded project path, and the role you need to commit to a protected default branch. - RunLore’s writes are confined to the forge — it has no cluster-mutating permissions.
Not yet supported on GitLab
The Learn loop is complete on GitLab: an investigation drafts a merge request, a recurrence
coalesces onto the open one instead of duplicating it, the reinvestigate label re-runs the
investigation and posts the findings back, and index.md/log.md stay in step with every entry.
Phase-2 grooming is GitHub-only. These do not work on a GitLab-hosted knowledge base today:
| What | Behaviour on GitLab |
|---|---|
lore curate (the backlog-grooming CLI: dedup, lifecycle, queue, recurrence, contested, retirement passes) | Fails to start, with a message naming a GitHub App — it has no GitLab code path |
In-server sweeps (curate.sweeps.mode: apply) | Disabled, and it says so. No sweeper is built, and startup logs curate sweeps disabled: no usable KB forge — Phase-2 grooming is GitHub-only |
Concretely: nothing prunes the KB backlog, stale merge requests are never closed, and entries are
never promoted to ready-to-merge when the underlying incident resolves. Review and merge KB merge
requests by hand until GitLab support lands in the grooming agent.
Reference
- Configuration →
forgefor the full key reference. - Learning loop — the full curate/triage lifecycle. Note that it documents the GitHub lifecycle end to end; see Not yet supported on GitLab for the Phase-2 grooming passes a GitLab-hosted KB does not get yet.
- GitHub — the other supported forge, for a side-by-side comparison of the two auth models.