GitLab
GitLab integration actions allow workflows to trigger CI/CD pipelines, create merge requests, update merge requests, and add or remove emoji reactions on merge request comments directly using your installed GitLab integration.
Prerequisites
- A GitLab integration installed in your Port organization.
- Actions processing must be enabled on your integration:
- Hosted by Port / UI / OAuth installations: actions processing is enabled automatically.
- Self-hosted (Helm or Docker): actions processing is disabled by default and must be explicitly enabled. See Enable actions processing (self-hosted) below.
- Your GitLab token must have sufficient permissions for the operation you run. Token requirements are listed with each action below.
Enable actions processing (self-hosted)
If you installed the GitLab Ocean integration as hosted by Port (via the UI or OAuth), actions processing is enabled automatically and you can skip to Configuration.
For self-hosted deployments (Kubernetes/Helm or Docker), the actions processor is disabled by default. You need to enable it explicitly using the flags below, depending on how you deployed the integration:
- Helm
- Docker
Pass the following flags when installing or upgrading the Helm chart:
helm upgrade --install gitlab-v2-ocean port-labs/port-ocean \
--set actionsProcessor.enabled=true \
--set ocean.baseUrl=<YOUR_INTEGRATION_BASE_URL> \
# ... rest of your values
actionsProcessor.enabled=true- enables the actions processor so the integration can receive and execute GitLab pipeline trigger requests from Port.ocean.baseUrl=<YOUR_INTEGRATION_BASE_URL>- required whenreportPipelineStatusis enabled (the default). Port uses this URL to receive webhook events from GitLab and update the action run status in real time. The URL must be reachable from GitLab.
Add the following environment variables to your Docker run command or docker-compose configuration:
docker run \
-e OCEAN__FEATURE_FLAGS__ACTIONS_PROCESSOR_ENABLED=true \
-e OCEAN__INTEGRATION__CONFIG__OCEAN_BASE_URL=<YOUR_INTEGRATION_BASE_URL> \
# ... rest of your env vars
ghcr.io/port-labs/port-ocean-gitlab-v2:latest
reportPipelineStatus?By default, Port automatically updates the action/automation run status in Port when the triggered GitLab pipeline finishes. This requires GitLab to send a pipeline webhook event back to the integration. If the integration's base URL is not set, Port cannot receive this callback and the run status will not be updated automatically.
To disable this behavior, set reportPipelineStatus: false in the execution properties of your action node, or turn off the Report pipeline status toggle in the UI.
Configuration
All GitLab integration actions share the same node structure:
| Field | Type | Description |
|---|---|---|
type | string | Required. Must be "INTEGRATION_ACTION" |
installationId | string | Required. Your GitLab integration installation ID |
integrationProvider | string | Required. Must be "gitlab-v2" |
integrationInvocationType | enum | Required. One of the values listed in available actions |
integrationActionExecutionProperties | object | Required. Operation-specific configuration |
The remaining sections describe the execution properties of each action.
Available actions
Each action is selected with the integrationInvocationType field:
| Action | Invocation type | Description |
|---|---|---|
| Trigger a pipeline | trigger_pipeline | Trigger a GitLab CI/CD pipeline and optionally wait for its result |
| Create a merge request | create_merge_request | Open a merge request between two branches |
| Update a merge request | update_merge_request | Update title, description, state, target branch, assignees, or reviewers on an existing merge request |
| Set a merge request comment reaction | set_merge_request_comment_reaction | Add or remove an emoji reaction on a merge request comment |
Pipeline actions
Trigger a pipeline
Triggers a GitLab CI/CD pipeline on a branch, tag, or commit. Set integrationInvocationType to trigger_pipeline.
The target project must have a valid .gitlab-ci.yml, and your GitLab token must be able to trigger pipelines and manage webhooks:
-
Legacy PAT: the
apiscope covers everything required. -
Fine-grained PAT: configure the following resource permissions:
Fine-grained PAT permissions (click to expand)
Group and project
Resource Permission Group Read Project Read Pipeline (CI/CD) Create Webhook (Integrations) Create, Read User
Resource Permission Project Read Group Read
Execution properties
| Field | Type | Description |
|---|---|---|
project | string | Required. GitLab project path (e.g., my-group/my-project) or numeric project ID |
ref | string | Required. Branch name, tag, or commit SHA to run the pipeline on |
pipelineVariables | object | Key-value pairs passed as CI/CD variables to the pipeline |
reportPipelineStatus | boolean | Whether to report pipeline completion status back to Port (default: true) |
Basic example
Trigger a GitLab pipeline (click to expand)
Trigger a GitLab pipeline, passing environment and version from the trigger inputs:
{
"identifier": "trigger-gitlab-pipeline",
"title": "Trigger GitLab Pipeline",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "your-installation-id",
"integrationProvider": "gitlab-v2",
"integrationInvocationType": "trigger_pipeline",
"integrationActionExecutionProperties": {
"project": "my-group/my-project",
"ref": "{{ .outputs.trigger.branch }}",
"pipelineVariables": {
"ENVIRONMENT": "{{ .outputs.trigger.environment }}",
"VERSION": "{{ .outputs.trigger.version }}"
}
}
}
}
Pipeline variables
Pipeline variables (click to expand)
Pass CI/CD variables to your pipeline using the pipelineVariables field. Values can be static or dynamically resolved from workflow outputs:
{
"integrationActionExecutionProperties": {
"project": "my-group/my-project",
"ref": "main",
"pipelineVariables": {
"ENVIRONMENT": "{{ .outputs.trigger.environment }}",
"VERSION": "{{ .outputs.trigger.version }}",
"DRY_RUN": "{{ .outputs.trigger.dryRun | tostring }}"
}
}
}
Variables are passed to the pipeline as CI/CD variables and are accessible in your .gitlab-ci.yml as $VARIABLE_NAME.
Status reporting
Status reporting (click to expand)
By default, Port monitors the triggered pipeline and updates the workflow node status when it completes. To opt out:
{
"integrationActionExecutionProperties": {
"project": "my-group/my-project",
"ref": "main",
"reportPipelineStatus": false
}
}
When reportPipelineStatus is false, Port does not track the pipeline's completion at all: the node is left in progress after the pipeline is triggered, and it is up to you to report its outcome back to Port (for example, from a job in your .gitlab-ci.yml that calls the Port API).
When reportPipelineStatus is true (the default), Port monitors the triggered pipeline and updates the workflow node status when it completes.
GitLab CI/CD configuration
Example .gitlab-ci.yml (click to expand)
Your .gitlab-ci.yml can access pipeline variables passed from Port using the standard $VARIABLE_NAME syntax:
# .gitlab-ci.yml
stages:
- deploy
deploy:
stage: deploy
script:
- echo "Deploying version $VERSION to $ENVIRONMENT"
# Your deployment logic here
environment:
name: $ENVIRONMENT
rules:
- if: $CI_PIPELINE_SOURCE == "api"
- if: $CI_PIPELINE_SOURCE == "web"
Merge request actions
Create a merge request
Opens a merge request in a GitLab project, from a source branch into a target branch. Set integrationInvocationType to create_merge_request. In the workflow builder, add this node from the Create GitLab Merge Request option.
Both branches must already exist in the project, and your GitLab token must be able to create merge requests in it:
- Legacy PAT: the
apiscope covers everything required. - Fine-grained PAT: grant the Merge request resource the Create permission on the Group and project boundary, in addition to the permissions your integration already uses to sync the catalog.
This node completes immediately after GitLab creates the merge request:
- No status tracking: Does not monitor whether the merge request is later approved, merged, or closed.
- No callbacks required: Works out-of-the-box on self-hosted instances without needing an integration base URL.
Execution properties
| Field | Type | Description |
|---|---|---|
project | string | Required. GitLab project path (e.g., my-group/my-project) or numeric project ID |
sourceBranch | string | Required. The branch containing the changes to merge |
targetBranch | string | Required. The branch to merge changes into |
title | string | Required. Title of the merge request |
All four properties are required. If one of them resolves to an empty value, the node fails before any call to GitLab is made.
The workflow builder collects the project as two separate fields, Namespace and Project, and joins them into the single project property as namespace/project. Use / between nested groups, for example my-group/my-subgroup.
Basic example
Create a GitLab merge request (click to expand)
Open a merge request into main, taking the source branch and title from the trigger inputs:
{
"identifier": "create-gitlab-merge-request",
"title": "Create GitLab Merge Request",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "your-installation-id",
"integrationProvider": "gitlab-v2",
"integrationInvocationType": "create_merge_request",
"integrationActionExecutionProperties": {
"project": "my-group/my-project",
"sourceBranch": "{{ .outputs.trigger.sourceBranch }}",
"targetBranch": "main",
"title": "{{ .outputs.trigger.title }}"
}
}
}
Merge request URL
Merge request URL (click to expand)
The URL of the new merge request is written to the run logs and to the run's completion message, so you can open it from the action run in Port. It is not available as a node output, so later nodes in the workflow cannot reference it in JQ templates.
Update a merge request
Updates an existing merge request in a GitLab project. Set integrationInvocationType to update_merge_request. In the workflow builder, add this node from the Update GitLab Merge Request option.
The node completes when GitLab accepts the update. It does not wait for the merge request to be merged or closed by reviewers. Because no callback from GitLab is involved, this action works without an integration base URL, even on self-hosted installations.
Your GitLab token must be able to update merge requests in the project:
- Legacy PAT: the
apiscope covers everything required. - Fine-grained PAT: grant the Merge request resource the Update permission on the Group and project boundary, in addition to the permissions your integration already uses to sync the catalog.
Execution properties
| Field | Type | Description |
|---|---|---|
id | string | Required. GitLab project path (e.g., my-group/my-project) or numeric project ID |
mergeRequestIid | string | Required. The project-scoped merge request IID (not the global ID) |
title | string | New title for the merge request |
description | string | New description for the merge request |
stateEvent | string | New merge request state. Allowed values: close, reopen |
targetBranch | string | New target branch for the merge request |
assigneeIds | array | GitLab user IDs to assign to the merge request. An empty array unassigns all assignees. Example: [1, 2] |
reviewerIds | array | GitLab user IDs to set as reviewers. An empty array unassigns all reviewers. Example: [3, 4] |
id and mergeRequestIid are always required. You must also set at least one of title, description, stateEvent, targetBranch, assigneeIds, or reviewerIds. If none of those optional fields is present (or they all resolve to empty values), the node fails before any call to GitLab is made.
The workflow builder collects the project as two separate fields, Namespace and Project, and joins them into the single id property as namespace/project. Use / between nested groups, for example my-group/my-subgroup.
Basic example
Update a GitLab merge request (click to expand)
Close a merge request, taking the project and IID from the trigger inputs:
{
"identifier": "update-gitlab-merge-request",
"title": "Update GitLab Merge Request",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "your-installation-id",
"integrationProvider": "gitlab-v2",
"integrationInvocationType": "update_merge_request",
"integrationActionExecutionProperties": {
"id": "my-group/my-project",
"mergeRequestIid": "{{ .outputs.trigger.mergeRequestIid }}",
"stateEvent": "close"
}
}
}
Set a merge request comment reaction
Adds or removes an emoji reaction on an existing merge request note (comment). Set integrationInvocationType to set_merge_request_comment_reaction. In the workflow builder, add this node from the Set merge request comment reaction option.
The merge request and comment must already exist. Your GitLab token must be able to award emoji on merge request notes in that project:
- Legacy PAT: the
apiscope covers everything required. - Fine-grained PAT: grant Merge request at least Read on the project, and permission to interact with notes (Developer role or equivalent on the project is typically required).
This node completes immediately after GitLab adds or removes the award emoji:
- No status tracking: Does not monitor other users' reactions on the thread.
- Sync completion: Port marks the node successful as soon as the GitLab API returns.
Execution properties
| Field | Type | Description |
|---|---|---|
project | string | Required. GitLab project path (e.g., my-group/my-project) or numeric project ID |
mergeRequestIid | string | Required. Internal merge request IID (the number in the MR URL, e.g. !42 → 42) |
noteId | string | Required. ID of the merge request note (comment) to react to |
name | string | Required. GitLab emoji name without colons (for example, thumbsup) |
removeReaction | boolean | When true, removes the named reaction instead of adding it (default: false) |
The workflow builder collects the project as two separate fields, Group/subgroups and Project, and joins them into the single project property as namespace/project. Use / between nested groups, for example my-group/my-subgroup.
Node outputs
Node outputs (click to expand)
After a successful run, the node exposes:
| Output | Type | Description |
|---|---|---|
noteId | string | Merge request note ID |
mergeRequestIid | string | Merge request IID |
name | string | Emoji name that was added or removed |
removed | boolean | Whether the reaction was removed (true) or added (false) |
awardId | string | GitLab award emoji ID when a reaction was added (omitted when removing) |
Basic example
Set a merge request comment reaction (click to expand)
Add a thumbs-up reaction to note 987 on merge request 42:
{
"identifier": "react-on-gitlab-mr-comment",
"title": "React on GitLab MR comment",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "your-installation-id",
"integrationProvider": "gitlab-v2",
"integrationInvocationType": "set_merge_request_comment_reaction",
"integrationActionExecutionProperties": {
"project": "my-group/my-project",
"mergeRequestIid": "42",
"noteId": "987",
"name": "thumbsup",
"removeReaction": false
}
}
}
Complete workflow examples
Deploy a service with a pipeline (click to expand)
A self-service deployment workflow that triggers a GitLab pipeline and updates the service entity on completion:
{
"identifier": "deploy-with-gitlab",
"title": "Deploy Service with GitLab CI",
"icon": "GitLab",
"description": "Trigger a deployment pipeline using GitLab CI/CD",
"nodes": [
{
"identifier": "trigger",
"title": "Request Deployment",
"config": {
"type": "SELF_SERVE_TRIGGER",
"userInputs": {
"properties": {
"service": {
"type": "string",
"format": "entity",
"blueprint": "service",
"title": "Service"
},
"environment": {
"type": "string",
"title": "Environment",
"enum": ["staging", "production"]
},
"version": {
"type": "string",
"title": "Version",
"description": "Git tag or commit SHA"
}
},
"required": ["service", "environment", "version"]
}
}
},
{
"identifier": "trigger-pipeline",
"title": "Trigger GitLab Pipeline",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "gitlab-integration-123",
"integrationProvider": "gitlab-v2",
"integrationInvocationType": "trigger_pipeline",
"integrationActionExecutionProperties": {
"project": "my-group/{{ .outputs.trigger.service }}",
"ref": "{{ .outputs.trigger.version }}",
"pipelineVariables": {
"ENVIRONMENT": "{{ .outputs.trigger.environment }}",
"VERSION": "{{ .outputs.trigger.version }}"
},
"reportPipelineStatus": true
}
}
},
{
"identifier": "update-entity",
"title": "Update Service Status",
"config": {
"type": "UPSERT_ENTITY",
"blueprintIdentifier": "service",
"mapping": {
"identifier": "{{ .outputs.trigger.service }}",
"properties": {
"lastDeployedVersion": "{{ .outputs.trigger.version }}",
"lastDeployedEnvironment": "{{ .outputs.trigger.environment }}",
"lastDeployedAt": "{{ now | todateiso8601 }}"
}
}
}
}
],
"connections": [
{
"sourceIdentifier": "trigger",
"targetIdentifier": "trigger-pipeline"
},
{
"sourceIdentifier": "trigger-pipeline",
"targetIdentifier": "update-entity"
}
]
}
Open a merge request (click to expand)
A self-service workflow that collects the project, branches, and title, then opens the merge request:
{
"identifier": "open-gitlab-merge-request",
"title": "Open a GitLab Merge Request",
"icon": "GitLab",
"description": "Open a merge request from a source branch into a target branch",
"nodes": [
{
"identifier": "trigger",
"title": "Request Merge Request",
"config": {
"type": "SELF_SERVE_TRIGGER",
"userInputs": {
"properties": {
"project": {
"type": "string",
"title": "Project",
"description": "GitLab project path, for example my-group/my-project"
},
"sourceBranch": {
"type": "string",
"title": "Source branch"
},
"targetBranch": {
"type": "string",
"title": "Target branch",
"default": "main"
},
"title": {
"type": "string",
"title": "Merge request title"
}
},
"required": ["project", "sourceBranch", "targetBranch", "title"]
}
}
},
{
"identifier": "create-merge-request",
"title": "Create GitLab Merge Request",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "gitlab-integration-123",
"integrationProvider": "gitlab-v2",
"integrationInvocationType": "create_merge_request",
"integrationActionExecutionProperties": {
"project": "{{ .outputs.trigger.project }}",
"sourceBranch": "{{ .outputs.trigger.sourceBranch }}",
"targetBranch": "{{ .outputs.trigger.targetBranch }}",
"title": "{{ .outputs.trigger.title }}"
}
}
}
],
"connections": [
{
"sourceIdentifier": "trigger",
"targetIdentifier": "create-merge-request"
}
]
}
Update a merge request (click to expand)
A self-service workflow that collects the project, merge request IID, and a new title, then updates the merge request:
{
"identifier": "update-gitlab-merge-request-title",
"title": "Update a GitLab Merge Request",
"icon": "GitLab",
"description": "Update the title of an existing merge request",
"nodes": [
{
"identifier": "trigger",
"title": "Request Merge Request Update",
"config": {
"type": "SELF_SERVE_TRIGGER",
"userInputs": {
"properties": {
"project": {
"type": "string",
"title": "Project",
"description": "GitLab project path, for example my-group/my-project"
},
"mergeRequestIid": {
"type": "string",
"title": "Merge request IID"
},
"title": {
"type": "string",
"title": "New merge request title"
}
},
"required": ["project", "mergeRequestIid", "title"]
}
}
},
{
"identifier": "update-merge-request",
"title": "Update GitLab Merge Request",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "gitlab-integration-123",
"integrationProvider": "gitlab-v2",
"integrationInvocationType": "update_merge_request",
"integrationActionExecutionProperties": {
"id": "{{ .outputs.trigger.project }}",
"mergeRequestIid": "{{ .outputs.trigger.mergeRequestIid }}",
"title": "{{ .outputs.trigger.title }}"
}
}
}
],
"connections": [
{
"sourceIdentifier": "trigger",
"targetIdentifier": "update-merge-request"
}
]
}