Skip to main content

GitLab plugin

A worked setup for the gitlab plugin — projects, merge requests, issues, pipelines, releases, and repository file/branch/tag operations against a GitLab instance. This page walks through the exact sequence for a real self-hosted instance, using only the flux CLI. For the general plugin mechanics (capability grants, trust model, everyday commands), see Using plugins.

1. Install

flux plugin install gitlab

This resolves the newest signed plugins-v* pack release, verifies the index signature and the archive's SHA-256, and unpacks the binary into the versioned store. Confirm it landed:

flux plugin status gitlab

status reads the installed version and operation total from the live manifest. For setup, check the personal_token auth purpose, the gitlab.endpoint endpoint, the gitlab.projects, gitlab.merge_requests, and gitlab.issues datasources, and the HTTP, declared-secret, and blob capabilities. With no configuration it reports the declared token environment variables and the endpoint's https://gitlab.com default.

ok/verified only proves the binary launched and its hash matches the signed descriptor — it does not mean authentication or network access has been checked. The auth:/endpoint: lines below it are the wiring itself: which env var each declared purpose reads (never the value), and whether one is currently set. This is what's actually true right now, not a promise about what will work at call time.

2. Provide the token and (for self-hosted) the base URL

status just told you the exact env vars this plugin's manifest declares — two per purpose, tried in order:

PurposeEnv vars (first one set wins)
Personal access tokenGITLAB_PERSONAL_TOKEN, GITLAB_PERSONAL_ACCESS_TOKEN
Base URL (omit for gitlab.com)GITLAB_URL, GITLAB_BASE_URL
export GITLAB_PERSONAL_TOKEN="glpat-…" # a token with API scope
export GITLAB_URL="https://gitlab.example.com" # self-hosted only; unset = gitlab.com

Re-run flux plugin status gitlab and both lines flip to , with the endpoint line showing the resolved base URL (endpoints are not secret — flux endpoint show/resolve print them too):

auth: ✓ personal_token — env $GITLAB_PERSONAL_TOKEN
endpoint: ✓ gitlab.endpoint — https://gitlab.example.com (env $GITLAB_URL)

Note what status never shows: the token value itself. These env vars never need to be written into .flux/config.toml or read by anything Flux-side other than the host process. The plugin subprocess never sees them as OS environment variables at all — it is spawned with a cleared environment and requests the token by name over an IPC capability call, which the host resolves from its own env and hands back only because the plugin's manifest declared these exact keys as a granted secret. See Credentials & secrets for the full resolution path.

3. Self-hosted on a private network? Grant egress

A GitLab instance on an internal/private address (RFC1918, *.internal, VPN-only DNS, etc.) is refused by the SSRF guard by default — you'll see this if you skip this step:

error: plugin `gitlab` op `gitlab.test`: provider error: refusing to fetch private/loopback/link-local address …

Grant the specific host in .flux/config.toml (project) or ~/.flux/config.toml (user default):

[private_net.plugins]
gitlab = ["gitlab.example.com"]

The grant is intersected with what the plugin itself declares, so this only ever opens the one host you name. Public gitlab.com needs no grant. See Private-network egress for the full mechanism.

4. Verify

flux plugin call gitlab gitlab.test

gitlab.test fetches the current authenticated user — the cheapest possible end-to-end check that the token and endpoint are both wired correctly:

{
"status": "ok",
"text": "GitLab auth OK",
"user": { "id": 1, "username": "…", "name": "…", "web_url": "https://gitlab.example.com/…" }
}

An auth failure surfaces as a 401 from GitLab, not a Flux-side error — that tells you the token is wrong or lacks scope, not that the wiring is broken. A private-network refusal (step 3) means the wiring reached the network guard but not GitLab yet.

5. Call a real operation

Any of the plugin's declared operations works the same way — flux plugin call gitlab <op> [json], or let an agent call them once it's running with the plugin installed:

flux plugin call gitlab gitlab.project.list '{"per_page": 5}'
flux plugin call gitlab gitlab.mr.list '{"project": "group/project", "state": "opened"}'
flux plugin call gitlab gitlab.issue.create '{"project": "group/project", "title": "…"}' --dry-run

--dry-run spawns the plugin once to read its manifest and validates the input against the operation's schema, but it never invokes the operation or performs its operation-level network/write work. It is useful for checking argument shape before a write operation.

Recap

StepCommandFailure mode if skipped
Installflux plugin install gitlabno such plugin \gitlab``
Token (+ URL if self-hosted)export GITLAB_PERSONAL_TOKEN=…no credential for purpose \personal_token``
Private-net grant (self-hosted only)[private_net.plugins] in configrefusing to fetch private/loopback/link-local address …
Verifyflux plugin call gitlab gitlab.test(this is the verification step)