oxagenDocs
Collectors

GitLab

Read GitLab issues into a workspace by project, through the project access token already attached.

The GitLab collector is not available yet. This page describes how it works once Oxagen turns it on.

Account to connect with

The collector signs in nowhere new. It reads through the project access token you gave when you attached the project, and it stores no second credential. Attach the project first, as Connect GitLab explains. An organization Owner attaches it.

Writes show in GitLab as the bot user of that project access token.

The collector reads from gitlab.com unless its connection names another host. Attaching a project records no host yet, so every attached project reads from gitlab.com today. The collector refuses a host that is an address, carries a port or a path, or ends in .local, .internal, .localhost, .lan, .home, or .corp.

Scopes asked for

Scope or roleUsed for
apiReading issues and labels, writing notes, closing issues, and changing labels
Developer roleEverything the collector does except the webhook
Maintainer roleRegistering the collector's project webhook

Attaching with the Developer role connects the project, and the attach step reports the webhook as refused. The collector's own hook is created with the same token, so a role that GitLab refuses for hooks leaves the reconcile as the only reader.

A project access token reaches one project. A scope with more than one project needs a token that reaches them all, and Oxagen refuses a project the connection was not attached to.

Scope choices

A collector names one or more attached projects by path, an optional label filter, and a switch for confidential issues.

toml
# work/collectors/gitlab-platform.toml in the steering repo
schema = "collector/v1"
name = "gitlab-platform"
label = "GitLab platform"
type = "gitlab"
connection = "<connection id>"

[scope]
projects = ["acme/platform/api", "acme/platform/web"]
labels = ["oxagen"]
confidential = false
  • A path is group/project or group/subgroup/project.
  • A work item whose repository is one of these projects gets its issue there.
  • With labels, Oxagen reads only issues that carry at least one of them.
  • confidential is off until a person turns it on. While it is off, Oxagen reads no confidential issue. When it is on, the project webhook also sends confidential issue events.
  • The collector reads issues only. It skips tasks and incidents.
  • An issue that moves to another project keeps its old row, closed. The new issue arrives from its own project's reconcile when that project is in scope.

The scope step lists the attached project, then its labels.

Default field mapping

A workspace with no GitLab rows gets these.

OxagenReads from GitLabWrites to GitLab
Status OpenState opened, or status categories triage, to do, in progressState opened (reopen)
Status ClosedState closed, or status categories done and canceledState closed
Resolution DoneStatus category done, or state closedState closed
Resolution Won't doStatus Won't do, status category canceled, or label wontfixLabel wontfix
Resolution DuplicateStatus DuplicateNone
Priority P0, P1, P2, P3Scoped labels priority::1 to priority::4The same labels
Type Bug, New Feature, Improvement, Documentation, Test, ChoreLabels bug, feature, improvement, documentation, test, choreThe same labels

GitLab has no priority field, so a scoped label carries it.

What each switch writes

SwitchGitLab callResult
certify_noteCreate noteAn internal note in Markdown that lists the criteria
send_noteCreate noteAn internal note about the send
statusstate_event, or a GraphQL statusCloses or reopens the issue through the write rows. It sets a system status only when a write row names the field status. A reopen or a Done close removes the wontfix label
closeThe same as statusCloses the issue as Done
labelsadd_labels and remove_labelsAdds the priority and Type labels and removes the other priority::* and Type labels. The labels must already exist, or the write fails as mapping_missing
createProject upload, then create issueUploads each file to the project, then creates the issue with the mapped labels and a link to each file
textEdit issueSets the title and description a person edited in Oxagen
badgeEdit issuePuts the work item badge at the top of the description of an open issue the collector reads into a new work item

A create on a public project uploads files only when the person allowed links on save, because anyone with a file's address can read it there. A label no mapping row names is set only where the project has it.

On a project without statuses, a won't-do closes the issue and adds the wontfix label the mapping names. Oxagen creates no label.

What the tracker cannot do

FreePremium
Read an issueState opened or closed, labelsThe same, and a status in one of five categories from GitLab 18.2
WriteClose, reopen, note, labelsThe same, and a system status (To do, In progress, Done, Won't do, Duplicate) through a mapping row that names it. The default rows write only the state
Won't do and duplicateWon't do reads from a label. Duplicate has no read rowBoth read as statuses. A write sets a status only through a mapping row that names one
  • A custom status needs a mapping row that names a system status. A write that names a custom status fails as status_unreachable.
  • A project without work item statuses refuses a status write. Map the status to a state instead.
  • GitLab does not lock the body of a webhook with a shared secret, so a changed body would not show. It sends the secret Oxagen minted in X-Gitlab-Token, and Oxagen compares it in constant time.
  • A user's last label event names who changed an issue last. A bot's close or note leaves no label event, so Oxagen recognizes only the echo of its own label write.
  • Oxagen writes a title or a description only for an issue it creates, and for a person's edit in Oxagen. It never deletes an issue and never assigns anyone.

Webhook and reconcile timing

Oxagen registers one project hook for each project in scope. It sends issue events only, and confidential issue events only when the scope allows them. The hook uses the collector's own address. It never touches the hook that steering and the code graph use. The webhook arrives within seconds of a change. It names only the issue's global id and the host, and Oxagen reads the issue over REST.

GitLab hooks do not expire. The 15-minute reconcile checks the hook and registers it again if a maintainer removed it or changed its address. It also reads the issues changed since its cursor, so a change that no webhook carried arrives within about 15 minutes.

On this page