GitLab setup
Bloom's VCS layer is platform-agnostic (M23): a project's repo target can name
provider=gitlab, and merge-request/issue hooks then drive the same flows GitHub events do.
This page is the operator runbook for wiring GitLab end-to-end: the config keys, the
per-project webhook, and where access tokens live.
Two deliberate asymmetries with the GitHub App setup:
- No GitLab App / no token in env. GitLab API access is a plain access token, resolved at
runtime from the credential store's
vcs-authscope via each target'sauth.auth_ref- no platform secret ever sits in config or code. - Static webhook secret, not an HMAC. GitLab sends the configured secret verbatim in the
X-Gitlab-Tokenheader (it does not sign the body); Bloom compares it in constant time.
Configuration (env)
Set these (see .env.example):
BLOOM_GITLAB_URL=https://gitlab.com # or your self-hosted instance's base URL
BLOOM_GITLAB_WEBHOOK_SECRET=<random secret> # e.g. `openssl rand -hex 32`
BLOOM_GITLAB_URL- base URL of the GitLab instanceprovider=gitlabtargets live on. Defaults tohttps://gitlab.com; one instance per deployment.BLOOM_GITLAB_WEBHOOK_SECRET- the shared secret verified on everyPOST /webhooks/gitlabdelivery. Optional in dev (unset = verification disabled, matching the GitHub route); in production the route fails closed (503) until it is set.
Webhook intake is always mounted at /webhooks/gitlab. The outbound GitLab adapter
(creating issues, reviewing/merging MRs) additionally requires the credential store - see
Access tokens below.
In deployed environments these are set as GitHub Actions repository secrets/variables
(BLOOM_GITLAB_WEBHOOK_SECRET as a secret, BLOOM_GITLAB_URL as a variable) and rendered
into the runtime .env like every other key - see Deployment, "One-time
setup for CD".
Webhook wiring (per project)
For each GitLab project Bloom should react to, in Settings -> Webhooks add a webhook:
- URL:
https://<your-bloom-host>/webhooks/gitlab - Secret token: the value of
BLOOM_GITLAB_WEBHOOK_SECRET. - Trigger: enable Merge request events, Issues events, and Confidential issues events (Bloom ignores every other kind). Leave Enable SSL verification on.
What Bloom reacts to, mirroring the GitHub strategy's whitelist:
- Merge requests:
openandreopen(both enter review), plusupdateonly when it carries new commits (GitLab setsoldrev; the equivalent of GitHub'ssynchronize). - Issues:
close, and label additions onupdate(these drive the blocked-work and milestone-completion flows, same as on GitHub). Confidential issues are handled exactly like public ones - the hook only arrives if wired on the project, and Bloom's token already reads them over REST. An update that adds several labels at once (one GitLab hook) is fanned out to one event per added label, matching GitHub's one-delivery-per-label shape.
Deliveries are de-duplicated downstream on content-based event keys, so GitLab's webhook Resend / retry redeliveries are safe.
Access tokens (credential store)
Outbound GitLab operations authenticate with an access token resolved through the
M19 credential store (Infisical) - the store is the
prerequisite: the GitLab adapter registers only when BLOOM_INFISICAL_URL,
BLOOM_INFISICAL_CLIENT_ID, BLOOM_INFISICAL_CLIENT_SECRET, and BLOOM_INFISICAL_ORG are
configured.
- Create a GitLab access token that can act on the target namespace - a group or project
access token (or a service account's personal access token) with the
apiscope and at least the Maintainer role (Bloom creates repos, issues, labels, and milestones, pushes branches and files, and reviews/merges MRs). - Store it in Infisical under the
vcs-authproject (workspace), environmentprod, path/, with a secret name of your choosing (e.g.gitlab-acme). Bloom creates thevcs-authworkspace on first use; this is the one scope Bloom can read values from - client deploy-credential scopes stay write-only. - Set the repo target's
auth.auth_refto that secret name. The target'sauth.auth_refis how aprovider=gitlabproject names its token; a target without one fails with an actionable error. Rotating the stored token takes effect on the next API restart.
Notes
- One instance per deployment. All
provider=gitlabtargets shareBLOOM_GITLAB_URL; mixing gitlab.com and a self-hosted instance in one deployment is not supported. - Numbering. GitLab iids are per-type (issue
!1and MR!1coexist); Bloom's provider seam keeps issue and PR number spaces separate, so no cross-type mutation occurs (M23-R-1). - Commit order. GitLab lists MR commits newest first; Bloom's adapter normalizes them to oldest first, the one documented order across all platforms (M23-R-6).
- Migration tooling. To move an existing project's SDLC state between platforms (e.g. GitHub -> GitLab), use the cross-platform migration CLI.