Skip to content

GitLab: import and origin labels

You'll learn how an issue in a connected GitLab becomes a GAIA ticket, and how the ticket's progress is mirrored back onto that issue as a label your customer can see.

GAIA keeps its own canonical tickets — it never works in GitLab. The integration is two one-way bridges: import brings an issue in and remembers where it came from as the ticket's origin; origin labels write the ticket's state back onto that issue.

The connector

An administrator configures a connector on the control plane, one per GitLab instance: its base URL and an API token with access to the projects you want to import from. Nothing else about GitLab lives on the control plane — no labels, no webhooks. With import_interval at 0 the connector imports on demand only.

Import an issue

The import is one JSON:API action on the control plane; it needs the import gaia tickets permission:

sh
curl -X POST "$BASE_URL/jsonapi/gaia_ticket/import" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{"data":{"attributes":{"url":"https://git.example.com/group/repo/-/issues/42"}}}'

The response is the ticket as a JSON:API document: 201 when the issue was new to GAIA, 200 when it had been imported before and the ticket was updated instead. Source identity is deterministic, so re-importing the same issue never creates a second ticket.

What the ticket gets: the issue's title and description (as Markdown), the raw GitLab assignee username, origin set to the issue URL — and a starting state from the issue's type label:

Issue labelWorkflowEnters at
buggaia_bugdiagnose
choregaia_chorecoding
featuregaia_featurespec
any of those, issue already closedas abovedone
no type labelnone yetno state — unclassified

An imported issue therefore skips qualification: the label already said what it is. An unclassified import has no workflow and no state, and any conductor of the project may claim it to qualify it. From there on the origin plays no part in dispatch.

Origin labels — the state, mirrored back

Whenever an agent step transitions a ticket that has an origin, it writes one label onto the origin issue and removes the others of the same family. The default chain needs no configuration:

Ticket stateLabel on the issue
qualification, spec, coding, reviewdoing
donereview

Read it from the customer's side: doing while GAIA works, review when the result is ready for them to look at.

Your customer's vocabulary

If the labels your customer expects differ, add one bullet to the repository's WORKFLOW.md, under ## Loaded skills, with an origin_labels.data map:

md
## Loaded skills

- @gaia/publish-origin-status
    origin_labels.data: |
      qualification: in progress
      spec: in progress
      coding: in progress
      review: in progress
      done: ready for review

Keys are GAIA states; a <workflow>:<state> key such as gaia_feature:done wins over the bare done, because done means "the project manager tests it now" on a feature and "the customer can have it" on a PM-test ticket. The values are the label family GAIA owns on the issue: exactly one of them is present at a time, the others are removed, and a label outside the map is never touched. An empty value, an empty map or a state with no key writes nothing.

How the write happens

The label is written by the agent, in its own session, with that machine's credentials — one glab issue update call. So glab must be installed and authenticated on every machine that runs a conductor for the project, and the control plane holds no GitLab credentials beyond the importer's token.

Two consequences to accept up front:

  • Only a transition made by an agent step is mirrored. A state changed by hand in the cockpit, by the importer, or by a bare dropsh update is not mirrored until the next agent step transitions the ticket.
  • Pre-create the labels in the GitLab project with a colour and description, so GitLab does not auto-create them in random colours on first use.

Next