Providers

GitLab

Use gitlab.com and self-managed GitLab: issues, merge requests, to-dos, pipelines, releases and webhooks.

The GitLab provider covers gitlab.com and self-managed GitLab. It reads and writes issues, merge requests and commit comments. It also covers to-dos, pipelines and jobs, commit statuses, releases, vulnerabilities and project and group webhooks. Merge requests have kind: 'pull_request'.

DetailValue
Importforges/gitlab
Factoriesgitlab(), gitlabLite()
Authtoken, anonymous

Authentication

The provider accepts a personal, project, group or OAuth access token:

import { gitlab } from 'forges/gitlab'

const forge = gitlab({
  auth: { type: 'token', token: process.env.GITLAB_TOKEN! },
}).create()

Project and group access tokens act as bot users. Use one when you need a credential that isn't tied to a person.

Without auth, the provider makes anonymous public reads.

Self-managed instances

Set baseUrl to the root of the instance. The provider appends /api/v4:

gitlab({ baseUrl: 'https://gitlab.example.com', auth })

Webhook delivery logs and redelivery require GitLab 17.0 or later. Pass instanceVersion if you know the version. Otherwise, refreshCapabilities() reads it from /version.

Nested groups

RepoRef.owner is the full namespace path. A project in a subgroup has owner: 'acme/platform' and name: 'widgets'.

Notifications are to-dos

notifications.list() reads the user's to-dos. A to-do is either pending or done, with no separate read state:

  • markRead() rejects with UnsupportedOperationError.
  • markDone() marks the to-do done.
  • unsubscribe() requires { thread }, because GitLab can't look up a to-do by ID.

Event kinds from system notes

GitLab reports label, state and assignment changes as English text in system notes. The provider parses this text, so capabilities.eventKinds is 'heuristic'. Text that the provider doesn't recognise becomes an event with kind: 'other'. The event's kindRaw and payload keep the original note.

Approvals as reviews

threads.reviews() returns one review for each approver, with the ID approval:<username>. createReview({ event: 'approve' }) approves the merge request. A body, inline comments or any other event reject with UnsupportedOperationError.

GitLab responds with 401 when the user isn't allowed to approve. The provider raises this response as InsufficientScopeError.

Release assets

GitLab release assets are links to arbitrary URLs, so releases.downloadAsset() is unavailable. To download an asset, fetch asset.url.

search.commits() uses Advanced Search. GitLab doesn't report whether an instance has Advanced Search, so the capability is 'experimental'. On an instance without it, the search returns an empty page.

Commit search accepts free text only. If you pass author, committer, since, until or sort, the result has a filter_unsupported warning. search.threads() has no involves filter and adds the same warning when you pass one.

Webhooks

GitLab doesn't sign the body of a delivery. It sends the hook's secret token unchanged in X-Gitlab-Token, and the provider compares that header with webhookSecret:

const forge = gitlab({
  webhookSecret: process.env.GITLAB_WEBHOOK_SECRET,
}).create()

const events = await forge.webhooks.ingest({
  headers: request.headers,
  body: await request.text(),
})

The event name is in X-Gitlab-Event, and the delivery ID is in X-Gitlab-Event-UUID.

An issue or merge request update that changes labels, assignees or reviewers becomes one event per label or person added or removed. When there's more than one, each event ID is the delivery ID followed by : and the event's index.

When you create a hook with webhooks.create(), nativeEvents takes GitLab's event flag names, such as issues_events.

Recording fixtures

GITLAB_TOKEN=glpat-... FIXTURE_GITLAB_PROJECT=group/project \
FIXTURE_GITLAB_MR=1 pnpm record-fixtures gitlab

To add an issue, set FIXTURE_GITLAB_ISSUE. To record a self-managed instance, set GITLAB_BASE_URL.

Capabilities

Generated by pnpm capability-matrix; do not edit by hand.

CapabilitySupport
experimental❌
sources.poll✅
sources.webhook✅
sources.subscribe❌
repos.get✅
users.get✅
repos.list✅
repos.labels✅
repos.createLabelexperimental
repos.milestones✅
repos.collaborators✅
repos.permissionFor✅
repos.addCollaboratorexperimental
repos.assignableUsers✅
repos.reviewerCandidatesemulated
threads.getissue, PR, commit (experimental)
threads.listissue, PR
threads.getMany✅
comments.listissue, PR, commit (experimental)
comments.editissue (experimental), PR (experimental)
comments.deleteissue (experimental), PR (experimental)
reactions.listissue, PR
notifications.list✅
notifications.markRead❌
notifications.markDone✅
notifications.unsubscribe✅
notifications.markAllRead❌
notifications.markAllDoneexperimental
notifications.unreadCount✅
writes.commentissue (experimental), PR, commit (experimental)
writes.upsertCommentissue (emulated), PR (emulated)
writes.closeissue (experimental), PR
writes.reopenissue (experimental), PR
writes.createissue (experimental), PR (experimental)
writes.updateissue (experimental), PR (experimental)
writes.setLabelsissue (experimental), PR (experimental)
writes.addLabelsissue (experimental), PR (experimental)
writes.removeLabelsissue (experimental), PR (experimental)
writes.setMilestoneissue (experimental), PR (experimental)
writes.reactissue (experimental), PR (experimental)
writes.setAssigneesissue (experimental), PR (experimental)
writes.requestReviewPR (experimental)
writes.merge✅
writes.approveAndMerge✅
writes.transferexperimental
writes.markDuplicateemulated
subscriptions.getissue, PR
subscriptions.setissue, PR
installations❌
checks.threadPR
checks.list✅
checks.reportexperimental
checks.rerunexperimental
ci.runs✅
ci.run✅
ci.jobs✅
ci.logexperimental
contents.file✅
contents.tree✅
contents.branches✅
contents.tags✅
contents.resolveRef✅
contents.commits✅
contents.commit✅
contents.compare✅
contents.threadFiles✅
contents.threadCommits✅
reviews.listemulated
reviews.createemulated
reviews.submit❌
reviews.approve✅
reviews.resolveThreadexperimental
releases.list✅
releases.get✅
releases.latest✅
releases.getByTag✅
releases.downloadAsset❌
webhooks.listexperimental
webhooks.createexperimental
webhooks.updateexperimental
webhooks.deleteexperimental
webhooks.rotateSecretexperimental
webhooks.deliveries❌
webhooks.redeliver❌
search.threads✅
search.repos✅
search.commitsexperimental
securityAlertsdependency (experimental), code scanning (experimental), secret (experimental)
eventKindsheuristic
authtoken, anonymous
limitsbody 1048576, comment 1000000, label 255
Copyright © 2026