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 role | Used for |
|---|---|
api | Reading issues and labels, writing notes, closing issues, and changing labels |
| Developer role | Everything the collector does except the webhook |
| Maintainer role | Registering 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.
# 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/projectorgroup/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. confidentialis 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.
| Oxagen | Reads from GitLab | Writes to GitLab |
|---|---|---|
| Status Open | State opened, or status categories triage, to do, in progress | State opened (reopen) |
| Status Closed | State closed, or status categories done and canceled | State closed |
| Resolution Done | Status category done, or state closed | State closed |
| Resolution Won't do | Status Won't do, status category canceled, or label wontfix | Label wontfix |
| Resolution Duplicate | Status Duplicate | None |
| Priority P0, P1, P2, P3 | Scoped labels priority::1 to priority::4 | The same labels |
| Type Bug, New Feature, Improvement, Documentation, Test, Chore | Labels bug, feature, improvement, documentation, test, chore | The same labels |
GitLab has no priority field, so a scoped label carries it.
What each switch writes
| Switch | GitLab call | Result |
|---|---|---|
certify_note | Create note | An internal note in Markdown that lists the criteria |
send_note | Create note | An internal note about the send |
status | state_event, or a GraphQL status | Closes 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 |
close | The same as status | Closes the issue as Done |
labels | add_labels and remove_labels | Adds 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 |
create | Project upload, then create issue | Uploads each file to the project, then creates the issue with the mapped labels and a link to each file |
text | Edit issue | Sets the title and description a person edited in Oxagen |
badge | Edit issue | Puts 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
| Free | Premium | |
|---|---|---|
| Read an issue | State opened or closed, labels | The same, and a status in one of five categories from GitLab 18.2 |
| Write | Close, reopen, note, labels | The 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 duplicate | Won't do reads from a label. Duplicate has no read row | Both 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.