Examples
Mapping groupsโ
In the following example you will ingest your GitLab groups, subgroups and projects to Port, you may use the following Port blueprint definitions and integration configuration:
Group blueprint
{
"identifier": "gitlabGroup",
"title": "Group",
"icon": "GitLab",
"schema": {
"properties": {
"visibility": {
"icon": "Lock",
"title": "Visibility",
"type": "string",
"enum": [
"public",
"internal",
"private"
],
"enumColors": {
"public": "red",
"internal": "yellow",
"private": "green"
}
},
"url": {
"title": "URL",
"format": "url",
"type": "string",
"icon": "Link"
},
"description": {
"title": "Description",
"type": "string",
"icon": "BlankPage"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {}
}
Project blueprint
{
"identifier": "service",
"title": "Service",
"icon": "Microservice",
"schema": {
"properties": {
"url": {
"title": "URL",
"type": "string",
"format": "url"
},
"readme": {
"title": "README",
"type": "string",
"format": "markdown"
},
"description": {
"title": "Description",
"type": "string"
},
"language": {
"title": "Language",
"type": "string"
},
"namespace": {
"title": "Namespace",
"type": "string"
},
"fullPath": {
"title": "Full Path",
"type": "string"
},
"defaultBranch": {
"title": "Default Branch",
"type": "string"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {
"group": {
"title": "Group",
"target": "gitlabGroup",
"required": true,
"many": false
}
}
}
Integration mapping
deleteDependentEntities: true
createMissingRelatedEntities: true
enableMergeEntity: true
resources:
- kind: group
selector:
query: "true"
port:
entity:
mappings:
identifier: .full_path
title: .name
blueprint: '"gitlabGroup"'
properties:
url: .web_url
visibility: .visibility
description: .description
- kind: project
selector:
query: "true"
port:
entity:
mappings:
identifier: .path_with_namespace | gsub(" "; "")
title: .name
blueprint: '"service"'
properties:
url: .web_url
readme: file://README.md
description: .description
language: .__languages | to_entries | max_by(.value) | .key
namespace: .namespace.name
fullPath: .namespace.full_path
defaultBranch: .default_branch
relations:
group: >-
.path_with_namespace | gsub(" "; "") | split("/") | .[:-1] |
join("/")
- Refer to the setup section to learn more about the integration configuration setup process.
- We leverage JQ JSON processor to map and transform GitLab objects to Port entities.
- Click Here for the GitLab group object structure.
Mapping projects, README.md and merge requestsโ
In the following example you will ingest your GitLab projects, their README.md file contents and merge requests to Port, you may use the following Port blueprint definitions and integration configuration:
Project blueprint
{
"identifier": "service",
"title": "Service",
"icon": "Microservice",
"schema": {
"properties": {
"url": {
"title": "URL",
"type": "string",
"format": "url"
},
"readme": {
"title": "README",
"type": "string",
"format": "markdown"
},
"description": {
"title": "Description",
"type": "string"
},
"language": {
"title": "Language",
"type": "string"
},
"namespace": {
"title": "Namespace",
"type": "string"
},
"fullPath": {
"title": "Full Path",
"type": "string"
},
"defaultBranch": {
"title": "Default Branch",
"type": "string"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Merge request blueprint
{
"identifier": "gitlabMergeRequest",
"title": "Merge Request",
"icon": "GitVersion",
"schema": {
"properties": {
"creator": {
"title": "Creator",
"type": "string"
},
"status": {
"title": "Status",
"type": "string",
"enum": [
"opened",
"closed",
"merged",
"locked"
],
"enumColors": {
"opened": "yellow",
"closed": "red",
"merged": "green",
"locked": "blue"
}
},
"createdAt": {
"title": "Created At",
"type": "string",
"format": "date-time"
},
"updatedAt": {
"title": "Updated At",
"type": "string",
"format": "date-time"
},
"mergedAt": {
"title": "Merged At",
"type": "string",
"format": "date-time"
},
"link": {
"title": "Link",
"format": "url",
"type": "string"
},
"leadTimeHours": {
"title": "Lead Time in hours",
"type": "number"
},
"reviewers": {
"title": "Reviewers",
"type": "array",
"items": {
"type": "string"
}
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {
"project": {
"title": "Service",
"target": "service",
"required": false,
"many": false
}
}
}
Integration Mapping
resources:
- kind: project
selector:
query: "true"
includeLabels: "true"
port:
entity:
mappings:
identifier: .path_with_namespace | gsub(" "; "")
title: .name
blueprint: '"gitlabRepository"'
properties:
url: .web_url
readme: file://README.md
description: .description
language: .__languages | to_entries | max_by(.value) | .key
namespace: .namespace.name
fullPath: .namespace.full_path
defaultBranch: .default_branch
- kind: merge-request
selector:
query: "true"
port:
entity:
mappings:
identifier: .id | tostring
title: .title
blueprint: '"gitlabMergeRequest"'
properties:
creator: .author.name
status: .state
createdAt: .created_at
updatedAt: .updated_at
mergedAt: .merged_at
link: .web_url
leadTimeHours: >-
(.created_at as $createdAt | .merged_at as $mergedAt |
($createdAt | sub("\\..*Z$"; "Z") | strptime("%Y-%m-%dT%H:%M:%SZ") | mktime) as $createdTimestamp |
($mergedAt | if . == null then null else sub("\\..*Z$"; "Z") |
strptime("%Y-%m-%dT%H:%M:%SZ") | mktime end) as $mergedTimestamp |
if $mergedTimestamp == null then null else
(((($mergedTimestamp - $createdTimestamp) / 3600) * 100 | floor) / 100) end)
reviewers: .reviewers | map(.name)
relations:
project: .references.full | gsub("!.+"; "")
- Refer to the setup section to learn more about the integration configuration setup process.
- We leverage JQ JSON processor to map and transform GitLab objects to Port entities.
- Click Here for the GitLab project object structure.
- Click Here for the GitLab merge request object structure.
Mapping projects and issuesโ
In the following example you will ingest your GitLab projects and their issues to Port, you may use the following Port blueprint definitions and integration configuration:
Project blueprint
{
"identifier": "service",
"title": "Service",
"icon": "Microservice",
"schema": {
"properties": {
"url": {
"title": "URL",
"type": "string",
"format": "url"
},
"readme": {
"title": "README",
"type": "string",
"format": "markdown"
},
"description": {
"title": "Description",
"type": "string"
},
"language": {
"title": "Language",
"type": "string"
},
"namespace": {
"title": "Namespace",
"type": "string"
},
"fullPath": {
"title": "Full Path",
"type": "string"
},
"defaultBranch": {
"title": "Default Branch",
"type": "string"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Issue blueprint
{
"identifier": "gitlabIssue",
"title": "Issue",
"icon": "GitLab",
"schema": {
"properties": {
"link": {
"title": "Link",
"type": "string",
"format": "url"
},
"description": {
"title": "Description",
"type": "string",
"format": "markdown"
},
"createdAt": {
"title": "Created At",
"type": "string",
"format": "date-time"
},
"closedAt": {
"title": "Closed At",
"type": "string",
"format": "date-time"
},
"updatedAt": {
"title": "Updated At",
"type": "string",
"format": "date-time"
},
"creator": {
"title": "Creator",
"type": "string"
},
"status": {
"title": "Status",
"type": "string",
"enum": ["opened", "closed"],
"enumColors": {
"opened": "green",
"closed": "purple"
}
}
}
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {
"project": {
"title": "Service",
"target": "service",
"required": false,
"many": false
}
}
}
Integration Mapping
resources:
- kind: project
selector:
query: "true"
port:
entity:
mappings:
identifier: .path_with_namespace | gsub(" "; "")
title: .name
blueprint: '"service"'
properties:
url: .web_url
description: .description
language: .__languages | to_entries | max_by(.value) | .key
namespace: .namespace.name
fullPath: .namespace.full_path
defaultBranch: .default_branch
- kind: issue
selector:
query: "true"
port:
entity:
mappings:
identifier: .id | tostring
title: .title
blueprint: '"gitlabIssue"'
properties:
creator: .author.name
status: .state
createdAt: .created_at
closedAt: .closed_at
updatedAt: .updated_at
description: .description
link: .web_url
labels: "[.labels[]]"
relations:
project: .references.full | gsub("#.+"; "")
- Refer to the setup section to learn more about the integration configuration setup process.
- We leverage JQ JSON processor to map and transform GitLab objects to Port entities.
- Click Here for the GitLab project object structure.
- Click Here for the GitLab issue object structure.
Mapping files and file contentsโ
The following example shows how to ingest dependencies from a package.json
file in your GitLab repository into Port.
You can use the following Port blueprint definitions and integration configuration:
Package blueprint
{
"identifier": "package",
"title": "Package",
"icon": "Package",
"schema": {
"properties": {
"package": {
"icon": "DefaultProperty",
"type": "string",
"title": "Package"
},
"version": {
"icon": "DefaultProperty",
"type": "string",
"title": "Version"
}
},
"required": [
"package",
"version"
]
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {}
}
Integration Mapping
resources:
- kind: file
selector:
query: 'true'
files:
path: package.json
repos:
# Replace with your repository's path_with_namespace (e.g., "group/project" or "group/subgroup/project")
- group/my-project
port:
itemsToParse: .file.content.dependencies | to_entries
entity:
mappings:
identifier: >-
.item.key + "_" + if (.item.value | startswith("^")) then
.item.value[1:] else .item.value end
title: .item.key + "@" + .item.value
blueprint: '"package"'
properties:
package: .item.key
version: .item.value
The example will parse the package.json
file in your repository and extract the dependencies into Port entities.
For more information about ingesting files and file contents, click here
Mapping projects and monoreposโ
In the following example you will ingest your GitLab projects and their monorepo folders to Port, you may use the following Port blueprint definitions and integration configuration:
Project blueprint
{
"identifier": "service",
"title": "Service",
"icon": "Microservice",
"schema": {
"properties": {
"url": {
"title": "URL",
"type": "string",
"format": "url"
},
"readme": {
"title": "README",
"type": "string",
"format": "markdown"
},
"description": {
"title": "Description",
"type": "string"
},
"language": {
"title": "Language",
"type": "string"
},
"namespace": {
"title": "Namespace",
"type": "string"
},
"fullPath": {
"title": "Full Path",
"type": "string"
},
"defaultBranch": {
"title": "Default Branch",
"type": "string"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Integration mapping
resources:
- kind: folder
selector:
query: "true" # JQ boolean query. If evaluated to false - skip syncing the object.
folders: # Specify the repositories and folders to include under this relative path.
- path: "apps/" # Relative path to the folders within the repositories.
repos: # List of repositories to include folders from.
- backend-service
- frontend-service
port:
entity:
mappings:
identifier: .folder.name
title: .folder.name
blueprint: '"service"'
properties:
url: >-
.repo.web_url + "/tree/" + .repo.default_branch + "/" +
.folder.path
description: .repo.description
namespace: .repo.namespace.name
full_path: .repo.path_with_namespace + "/" + folder.path
language: .repo.__languages | to_entries | max_by(.value) | .key
readme: file://README.md
To retrieve the root folders of your monorepo, you can use this following syntax in your port-app-config.yml
:
- kind: folder
selector:
query: "true" # JQ boolean query. If evaluated to false - skip syncing the object.
folders: # Specify the repositories and folders to include under this relative path.
- path: "/" # Relative path to the folders within the repositories
repos: # List of repositories to include folders from.
- backend-service
- frontend-service
You can also specify a different path for each monorepo repository, for example:
- kind: folder
selector:
query: "true" # JQ boolean query. If evaluated to false - skip syncing the object.
folders: # Specify the repositories and folders to include under this relative path.
- path: "apps/"
repos:
- gaming-apps
- path: "microservices/"
repos:
- backend-services
- Refer to the setup section to learn more about the integration configuration setup process.
- We leverage JQ JSON processor to map and transform GitLab objects to Port entities.
- Click Here for the GitLab project object structure.
- Click Here for the GitLab repository tree object structure.
Mapping projects and foldersโ
In the following example you will ingest your GitLab projects and their folders to Port, you may use the following Port blueprint definitions and integration configuration:
Project blueprint
{
"identifier": "service",
"title": "Service",
"icon": "Microservice",
"schema": {
"properties": {
"url": {
"title": "URL",
"type": "string",
"format": "url"
},
"readme": {
"title": "README",
"type": "string",
"format": "markdown"
},
"description": {
"title": "Description",
"type": "string"
},
"language": {
"title": "Language",
"type": "string"
},
"namespace": {
"title": "Namespace",
"type": "string"
},
"fullPath": {
"title": "Full Path",
"type": "string"
},
"defaultBranch": {
"title": "Default Branch",
"type": "string"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Folder blueprint
{
"identifier": "gitlabFolder",
"title": "Folder",
"icon": "GitLab",
"schema": {
"properties": {
"url": {
"type": "string",
"title": "URL",
"format": "url",
"description": "Link to the folder in GitLab"
},
"readme": {
"type": "string",
"title": "README",
"format": "markdown",
"description": "Content of the folder's README file"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {
"project": {
"title": "Service",
"target": "service",
"required": false,
"many": false
}
}
}
Integration Mapping
resources:
- kind: project
selector:
query: "true"
port:
entity:
mappings:
identifier: .path_with_namespace | gsub(" "; "")
title: .name
blueprint: '"service"'
properties:
url: .web_url
readme: file://README.md
description: .description
language: .__languages | to_entries | max_by(.value) | .key
namespace: .namespace.name
fullPath: .namespace.full_path
defaultBranch: .default_branch
- kind: folder
selector:
query: "true"
folders:
- path: "/" # Using "/" will ingest the folders from the root of each of repository as entities
repos:
# Replace with your repository's path_with_namespace
- group/backend-service
- group/frontend-service
port:
entity:
mappings:
identifier: .folder.name
title: .folder.name
blueprint: '"gitlabFolder"'
properties:
url: >-
.repo.web_url + "/tree/" + .repo.default_branch + "/" +
.folder.path
readme: file://README.md
relations:
project: .references.full | gsub("!.+"; "")
You can specify different paths for different repositories:
resources:
- kind: folder
selector:
query: "true"
folders:
- path: "apps/"
repos:
- group/gaming-services
- path: "packages/"
repos:
- group/shared-libraries
Mapping members and group with membersโ
Prerequisitesโ
- When using GitLab Self Hosted, an admin token is required, rather than a group access token, to retrieve the
primary email addresses
of members. - When using GitLab Enterprise, accounts can retrieve the
primary email addresses
of members within their groups, provided the members are part of user accounts administered by an organization with verified domains for groups. For more information, see limitations.
Primary email addresses are not available for GitLab "Free plan" users.
Mapping membersโ
In the following example you will ingest your GitLab members to Port, you may use the following Port blueprint definitions and integration configuration:
Member blueprint
{
"identifier": "gitlabMember",
"title": "GitLab Member",
"icon": "GitLab",
"schema": {
"properties": {
"url": {
"type": "string",
"title": "URL",
"format": "url",
"description": "Link to the member's GitLab profile"
},
"state": {
"type": "string",
"title": "State",
"description": "The state of the member's account"
},
"email": {
"type": "string",
"title": "Email",
"format": "email",
"description": "The member's email address"
},
"created_by": {
"type": "string",
"title": "Created By",
"description": "Name of the user who added this member"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {}
}
Integration configuration
resources:
- kind: member
selector:
query: 'true'
port:
entity:
mappings:
identifier: .username
title: .name
blueprint: '"gitlabMember"'
properties:
url: .web_url
state: .state
email: .email
created_by: .created_by.name
Mapping groups with membersโ
In the following example you will ingest your GitLab groups and their members to Port, you may use the following Port blueprint definitions and integration configuration:
Group with members blueprint
{
"identifier": "gitlabGroup",
"title": "Group",
"icon": "GitLab",
"schema": {
"properties": {
"visibility": {
"icon": "Lock",
"title": "Visibility",
"type": "string",
"enum": [
"public",
"internal",
"private"
],
"enumColors": {
"public": "red",
"internal": "yellow",
"private": "green"
}
},
"url": {
"title": "URL",
"format": "url",
"type": "string",
"icon": "Link"
},
"description": {
"title": "Description",
"type": "string",
"icon": "BlankPage"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {
"gitlabMembers": {
"title": "Members",
"target": "gitlabMember",
"required": false,
"many": true
}
}
}
Integration Mapping
resources:
- kind: group-with-members
selector:
query: 'true'
port:
entity:
mappings:
identifier: .full_path
title: .name
blueprint: '"gitlabGroup"'
properties:
url: .web_url
visibility: .visibility
description: .description
relations:
gitlabMembers: .__members | map(.username)
- Include Bot Members
GitLab allows the creation of tokens (bots) for automated tasks, which can be associated with groups or projects via access tokens.
The includeBotMembers
parameter is used to filter out bot members from the actual GitLab members.
By default, this selector is set to false
, which means the integration will only sync actual members.
- kind: group-with-members
selector:
query: 'true'
includeBotMembers: false
- kind: members
selector:
query: 'true'
includeBotMembers: false
- Refer to the setup section to learn more about the integration configuration setup process.
- We leverage JQ JSON processor to map and transform GitLab objects to Port entities.
- Click Here for the GitLab project or group member object structure.
Mapping projects, pipelines and jobsโ
In the following example you will ingest your GitLab projects, their pipelines and jobs runs to Port, you may use the following Port blueprint definitions and integration configuration:
Pipeline blueprint
{
"identifier": "gitlabPipeline",
"title": "GitLab Pipeline",
"icon": "GitLab",
"schema": {
"properties": {
"creator": {
"type": "string",
"title": "Creator",
"description": "Name of the user who triggered the pipeline"
},
"status": {
"type": "string",
"title": "Status",
"description": "Current status of the pipeline"
},
"createdAt": {
"type": "string",
"title": "Created At",
"format": "date-time",
"description": "When the pipeline was created"
},
"updatedAt": {
"type": "string",
"title": "Updated At",
"format": "date-time",
"description": "When the pipeline was last updated"
},
"description": {
"type": "string",
"title": "Description",
"description": "Pipeline description"
},
"link": {
"type": "string",
"title": "Link",
"format": "url",
"description": "URL to the pipeline in GitLab"
}
},
"required": []
},
"relations": {
"project": {
"title": "Service",
"target": "service",
"required": false,
"many": false
}
}
}
Job blueprint
{
"identifier": "gitlabJob",
"title": "GitLab Job",
"icon": "GitLab",
"schema": {
"properties": {
"creator": {
"type": "string",
"title": "Creator",
"description": "Name of the user who triggered the job"
},
"startedAt": {
"type": "string",
"title": "Started At",
"format": "date-time",
"description": "When the job started"
},
"updatedAt": {
"type": "string",
"title": "Updated At",
"format": "date-time",
"description": "When the job was last updated"
},
"finishedAt": {
"type": "string",
"title": "Finished At",
"format": "date-time",
"description": "When the job finished"
},
"stage": {
"type": "string",
"title": "Stage",
"description": "Pipeline stage this job belongs to"
},
"status": {
"type": "string",
"title": "Status",
"description": "Current status of the job"
},
"link": {
"type": "string",
"title": "Link",
"format": "url",
"description": "URL to the job in GitLab"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {
"pipeline": {
"title": "Pipeline",
"target": "gitlabPipeline",
"required": false,
"many": false
}
}
}
Integration Mapping
resources:
- kind: pipeline
selector:
query: "true"
port:
entity:
mappings:
identifier: .id | tostring
title: .title // (.id | tostring)
blueprint: '"gitlabPipeline"'
properties:
creator: .user.name
status: .status
createdAt: .created_at
updatedAt: .updated_at
description: .description
link: .web_url
relations:
service: .__project.path_with_namespace
- kind: job
selector:
query: "true"
port:
entity:
mappings:
identifier: .id | tostring
title: .name
blueprint: '"gitlabJob"'
properties:
creator: .user.name
startedAt: .started_at
updatedAt: .updated_at
finishedAt: .finished_at
stage: .stage
status: .status
link: .web_url
relations:
pipeline: .pipeline.id | tostring
- Refer to the setup section to learn more about the integration configuration setup process.
- We leverage JQ JSON processor to map and transform GitLab objects to Port entities.
- Click Here for the GitLab project object structure.
- Click Here for the GitLab pipeline object structure.
- Click Here for the GitLab job object structure.