A security scan flags payments-api. Before anyone fixes anything, the service desk has to answer four questions: who owns it, is it public, is anyone still working on it, and is it archived? Today that's a Slack thread and a GitLab search.
OnLink now imports GitLab projects into Jira Service Management Assets, from GitLab.com or your own Self-Managed instance. Each repository becomes an Assets object with its owning group, visibility, default branch and last activity, so the answers sit on the ticket.
Why put GitLab in Assets
- Ownership on the ticket. Every project links to its GitLab group, so security findings and access requests go to the team that owns the code.
- Find public repositories fast. Visibility is an attribute, so one Assets search lists every public project.
- Spot stale and empty repos. Last activity, archived and empty-repository flags make cleanup a saved search, not a spreadsheet.
- Link changes and incidents to code. Requesters pick the repository from an Assets field, and the incident history builds up per project.
- Self-Managed included. Point OnLink at your own GitLab host; the setup is the same.
- One CMDB. Repositories sit next to the devices, people and cloud resources OnLink already brings in from 100+ sources.
How it fits together
OnLink calls the GitLab Projects API with a read-only token and writes each repository into a GitLab Project object. The project's group becomes a reference to a GitLab Group object, so ownership travels with every repo.
Authentication
OnLink reads GitLab with an access token that has the read_api scope. A group access token is the better choice for a team, because it isn't tied to one person's account.
- Open the top-level group that holds the projects you want in Assets.
- Settings > Access tokens > Add new token. Name it
onlink-assets-sync and set an expiry date. - Role: Reporter. Reporter is enough for project data; it also unlocks repository statistics if you want them.
- Scope:
read_api, then create the token and copy it. - In OnLink, add an Assets Data Source with authentication type Bearer Token, header
Authorization, and paste the token.
A personal access token works too, but the import will only see projects that person can access. See GitLab's REST API authentication page for the token types.
The API call
One GET call to the GitLab Projects API covers it. Pick the endpoint by how you want to scope the import:
Endpoint | Returns | Use it when |
|---|
GET /projects?membership=true
| Projects the token can see as a member | You use a personal token, or projects span several groups |
GET /groups/:id/projects?include_subgroups=true
| Every project in a group and its subgroups | Your projects live under one top-level group |
On GitLab.com, always add membership=true or use the group endpoint. Without it, /projects returns every public project on GitLab.com.
Paging is by page number: per_page=100 (the maximum) and page=1, 2, 3… until a page comes back empty. Add order_by=id&sort=asc so records don't shift between pages while the import runs.
GET https://gitlab.com/api/v4/projects?membership=true&active=true&order_by=id&sort=asc&per_page=100&page=1
Authorization: Bearer <your_access_token>
For Self-Managed, swap gitlab.com for your host. Other resources (groups, users, project members) follow the same pattern with their own endpoints.
OnLink mapping
Key on the numeric project id: names and paths change when a project is renamed or moved, the id doesn't. Nested fields such as namespace.full_path use dot paths.
GitLab Project (Projects API, no data path)
key:id=ProjectID
map:name=Name
map:path_with_namespace=Full Path
map:web_url=URL
map:visibility=Visibility
map:default_branch=Default Branch
map:archived=Archived
map:empty_repo=Empty Repository
map:last_activity_at=Last Activity
map:namespace.id=Group|GroupID=${namespace.id}
map:topics=Topics|Name=${topics}
The Group line references a GitLab Group object by its ID. Import groups first from /groups, or let OnLink create them with config:enable_object_creation=true. Set the Topics attribute to allow multiple values.
Filters go on the request URL, so you import only what your service desk supports:
Filter | Example | Use it to |
|---|
active
| active=true
| Skip archived projects and ones marked for deletion |
visibility
| visibility=private
| Import one visibility level |
last_activity_after
| last_activity_after=2026-01-01T00:00:00Z
| Leave out repos nobody has touched this year |
topic
| topic=production
| Import only projects tagged for production |
min_access_level
| min_access_level=40
| Only projects where the token is at least Maintainer |
Questions you can answer once it's in Assets
With repositories as objects, the questions people ask in Slack become saved AQL searches, dashboards and automation conditions:
Question | AQL |
|---|
Which repos are public? | objectType = "GitLab Project" AND Visibility = "public"
|
What hasn't been touched in 90 days? | objectType = "GitLab Project" AND "Last Activity" < now(-90d) AND Archived = false
|
Which repos have no code at all? | objectType = "GitLab Project" AND "Empty Repository" = true
|
What does the payments group own? | objectType = "GitLab Project" AND Group = "payments"
|
Which production repos are public? | objectType = "GitLab Project" AND Topics = "production" AND Visibility = "public"
|
Use the same conditions in Assets automation: for example, open a review request whenever a project flips to public.
Try it
FAQ
Does it work with GitLab Self-Managed and Dedicated? Yes. Use https://<your-gitlab-host>/api/v4 as the base URL; everything else is the same.
Does OnLink get write access to GitLab? No. The read_api scope is read-only, and a Reporter-role group token can't push code or change settings.
Why am I seeing thousands of projects I don't recognise? The URL is missing membership=true on GitLab.com. Add it, or switch to the group projects endpoint.
Can I import groups, users and members too? Yes. Point a second import at /groups, /users or /projects/:id/members and map their fields the same way. Import groups before projects so the Group reference finds its target.
How often does it sync? You set a schedule per import: hourly, daily, weekly or monthly. Daily suits most teams; GitLab only updates last activity about once an hour anyway.