GitLab ExecModule
Overview
GitLabModule connects ValkyrAI workflows to GitLab.com REST API v4 for project discovery, issue tracking, merge-request automation, review notes, and CI/CD pipelines. It exposes 16 bounded operations through the native map I/O ExecModule ABI and keeps the personal access token or OAuth access token inside a READY IntegrationAccount.
The connector fixes production traffic to https://gitlab.com/api/v4, disables redirects, caps request bodies at 256 KiB and responses at 5 MiB, returns one provider page per execution, retries transient failures only for safe GET operations, and never automatically retries issue, note, merge-request, or pipeline mutations.
The official n8n GitLab node informed the resource model and core issue, repository, file, release, and user patterns. ValkyrAI prioritizes agentic engineering workflows by adding merge requests and pipelines, then adds the native IntegrationAccount security boundary, strict field allowlists, fixed-host routing, response identity checks, explicit pagination, mutation non-retry, and credential-redacted errors.
Usage
- Create a GitLab personal, project, or group access token, or an OAuth access token, with only the scopes required by the workflow.
- Store that token in the encrypted
apiKeyorpasswordfield of a ValkyrAIIntegrationAccount; set the account status toREADY. - Bind the account through
ExecModuleConfig.authConfig.integrationAccount. - Choose
authMode: private_tokenfor a PAT orauthMode: oauth2for an OAuth bearer token. - Select one operation and provide its conditional project, resource, filter, or body fields.
- When a list returns
hasMore: true, passnextPageas the next execution'spage.
Version 1.0 targets GitLab.com only. GitLab Self-Managed and Dedicated hosts are deferred until they can be supported with an explicit trusted-host policy rather than caller-controlled routing.
Inputs
| Name | Type | Required | Description | Constraints |
|---|---|---|---|---|
operation | string | Yes | Operation listed below. | Exact allowlist of 16 values. |
projectId | string or integer | Conditional | Numeric project ID or namespace/project path. | 1–512 characters; path segments use letters, digits, dot, underscore, and hyphen. |
resourceIid | integer | Conditional | Project-scoped issue or merge-request IID. | Positive 32-bit integer. |
pipelineId | integer | Conditional | Global pipeline ID for retry or cancellation. | Positive integer. |
record | object or JSON string | Conditional | Allowlisted body fields for a mutation. | At most 12 fields and 256 KiB encoded. |
query | object or JSON string | No | Allowlisted list filters. | At most 10 scalar fields; values bounded to 1,024 characters. |
page | integer | No | One-based offset page. | 1–10,000; default 1. |
limit | integer | No | Items requested from one provider page. | 1–100; default 50. |
authMode | string | No | Authentication header contract. | private_token or oauth2; default private_token. |
The module percent-encodes namespaced project paths as one provider path parameter. Project paths cannot influence the scheme, host, API version, or route structure.
Mutation bodies use operation-specific allowlists:
- Issues:
title,description,assignee_ids,milestone_id,labels,due_date,confidential,state_event, anddiscussion_lockedas applicable. - Issue notes:
body,confidential, andinternal. - Merge requests: branch, title, description, assignment/reviewer, label, milestone, squash, source-branch removal, draft, state, lock, SHA, and merge-message fields as applicable.
- Pipelines:
ref,variables, andinputsfor creation.
Token-, password-, secret-, and authorization-shaped fields are rejected from workflow payloads.
Outputs
| Name | Type | When present | Description |
|---|---|---|---|
status | string | Always | success or error. |
operation | string | Always | Normalized operation. |
resource | string | After validation | projects, issues, notes, merge_requests, or pipelines. |
data | object | Single-resource success | GitLab response after identity validation. |
id or iid | integer | Identity-bearing success | Verified provider identity. |
items | array | List success | One bounded provider page. |
count | integer | List success | Items returned in that page. |
hasMore | boolean | List success | Whether GitLab supplied X-Next-Page. |
nextPage | integer | When another page exists | Validated next page number. |
httpStatus | integer | Provider response | GitLab HTTP status. |
attempts | integer | Provider call or error | HTTP attempts consumed. |
error | object | Failure | Redacted code, message, and retryable fields. |
GitLab payloads are classified restricted. Tokens, source bodies, issue descriptions, merge-request descriptions, variables, and provider response bodies are not copied into progress logs.
IntegrationAccount Requirements
| Setting | Requirement |
|---|---|
| Provider | GitLab.com REST API v4 |
| Authentication | PAT in PRIVATE-TOKEN, or OAuth 2.0 bearer token |
| Status | Exactly READY |
accountName | Human-readable GitLab identity or automation purpose |
apiKey or password | Encrypted token, 20–4,096 non-whitespace characters |
| Relationship | ExecModuleConfig.authConfig.integrationAccount |
Recommended scopes:
- Read-only project, issue, merge-request, and pipeline discovery:
read_api. - Issue, note, merge-request, and pipeline mutations:
api. - Repository content access is not exposed by this version, so
read_repositoryorwrite_repositoryis not required solely for these operations.
Prefer project or group access tokens with a narrow role and expiration over broad personal tokens. The module does not refresh OAuth tokens; the integration-account lifecycle must rotate expiring credentials.
Configuration
Illustrative persisted configuration:
{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:gitlab-platform-automation"
},
"payloadConfig": {
"parameters": "{\"operation\":\"list_merge_requests\",\"authMode\":\"private_token\",\"projectId\":\"acme/platform\",\"page\":1,\"limit\":50,\"query\":{\"state\":\"opened\",\"scope\":\"all\"}}"
}
}
The relationship is symbolic. The generated IntegrationAccount record owns the encrypted token.
Operations
| Resource | Operation | Provider route | Behavior |
|---|---|---|---|
| Projects | list_projects | GET /projects | One page with membership, ownership, visibility, archive, search, and sort filters. |
| Projects | get_project | GET /projects/{id} | Gets one numeric or namespaced project. |
| Issues | list_issues | GET /projects/{id}/issues | One filtered issue page. |
| Issues | get_issue | GET /projects/{id}/issues/{iid} | Gets one issue and verifies its IID. |
| Issues | create_issue | POST /projects/{id}/issues | Creates one bounded issue; title is required. |
| Issues | update_issue | PUT /projects/{id}/issues/{iid} | Updates allowlisted fields and verifies the response IID. |
| Notes | create_issue_note | POST /projects/{id}/issues/{iid}/notes | Adds one bounded issue note; body is required. |
| Merge requests | list_merge_requests | GET /projects/{id}/merge_requests | One filtered merge-request page. |
| Merge requests | get_merge_request | GET /projects/{id}/merge_requests/{iid} | Gets one merge request and verifies its IID. |
| Merge requests | create_merge_request | POST /projects/{id}/merge_requests | Creates one merge request with required source, target, and title. |
| Merge requests | update_merge_request | PUT /projects/{id}/merge_requests/{iid} | Updates allowlisted fields and verifies its IID. |
| Merge requests | merge_merge_request | PUT /projects/{id}/merge_requests/{iid}/merge | Requests a governed merge with optional exact SHA and provider controls. |
| Pipelines | list_pipelines | GET /projects/{id}/pipelines | One filtered pipeline page. |
| Pipelines | create_pipeline | POST /projects/{id}/pipeline | Creates one pipeline for a required ref with bounded variables or inputs. |
| Pipelines | retry_pipeline | POST /projects/{id}/pipelines/{pipelineId}/retry | Retries jobs in one pipeline and verifies its ID. |
| Pipelines | cancel_pipeline | POST /projects/{id}/pipelines/{pipelineId}/cancel | Cancels one pipeline and verifies its ID. |
Repository files, branches, commits, releases, tags, package registries, environments, deployments, jobs and traces, webhooks/triggers, approvals, discussions, protected resources, group administration, project creation/deletion, and GitLab Self-Managed routing are deferred.
Errors and Failure Modes
| Failure | Cause | Retry guidance |
|---|---|---|
VALIDATION_ERROR | Missing or malformed project/IID/pipeline ID, unsupported body/filter, invalid token mode, local bound, or invalid success identity. | Correct the request; no provider call is sent for input errors. |
INTEGRATION_ACCOUNT_REQUIRED | No bound secure account. | Bind the intended GitLab account. |
INTEGRATION_ACCOUNT_NOT_READY | Account status is not READY. | Repair or refresh the account before execution. |
GITLAB_HTTP_400/404 | Provider validation, private-resource masking, missing project/resource, or incompatible field. | Correct the request and confirm access. GitLab may return 404 for unauthorized private projects. |
GITLAB_HTTP_401/403 | Expired token, wrong auth mode, missing scope, or insufficient project role. | Refresh credentials and grant only the required scope/role. |
GITLAB_HTTP_409/412 | Resource state, stale SHA, or merge precondition conflict. | Read the resource, reconcile state, then submit a deliberate new mutation. |
GITLAB_HTTP_429 | GitLab.com rate limit. | Reads retry up to three total attempts; writes remain single-attempt. |
GITLAB_HTTP_5xx / NETWORK_ERROR | Provider or transport failure. | Reads retry safely. Reconcile issues, notes, merge requests, merges, and pipelines before manual retry. |
RESPONSE_TOO_LARGE | Provider response exceeded 5 MiB. | Narrow filters or reduce limit. |
| Invalid list or identity response | GitLab returned a wrong shape, invalid next-page header, missing identity, or mismatched IID/ID. | Treat as failure and verify API compatibility. |
Errors are bounded to 500 characters and pass through credential redaction. A timed-out write may have completed in GitLab, so the module refuses automatic mutation replay.
Example
Create a traceable deployment-regression issue:
{
"operation": "create_issue",
"authMode": "private_token",
"projectId": "acme/platform",
"record": {
"title": "Investigate production deployment regression",
"description": "The post-deploy verification route returned the prior release marker. Reconcile the active release before retrying deployment.",
"labels": "incident,automation,release",
"confidential": true,
"due_date": "2026-08-12"
}
}
Expected normalized result:
{
"status": "success",
"operation": "create_issue",
"resource": "issues",
"iid": 42,
"data": {
"id": 901,
"iid": 42,
"project_id": 17,
"title": "Investigate production deployment regression",
"state": "opened",
"confidential": true
},
"httpStatus": 201,
"attempts": 1
}
Notes
- Pagination: each list execution returns at most one offset page. Pass
nextPageinto the next execution'spage; no silent all-pages loop occurs. - Rate limits: GitLab.com applies global, endpoint, user, and abuse-prevention limits. The module handles numeric
Retry-Afterwith at most three attempts forGETonly. - API limits: provider page size is capped at 100, page at 10,000, request at 256 KiB, response at 5 MiB, record properties at 12, query properties at 10, and array-shaped mutation fields at 100 entries.
- Idempotency: reads are retry-safe. Issue, note, merge-request, merge, and pipeline mutations are single-attempt because a timeout can leave completion ambiguous.
- Destructive behavior: no project, repository, branch, release, issue, merge-request, or pipeline deletion is exposed.
cancel_pipeline, merge-request state changes, and merges still change provider state and require deliberate workflow governance. - Merge safety:
merge_merge_requestaccepts an optional exactsha; GitLab rejects the merge if the source changed. The module never overrides provider approvals, protected-branch policy, pipeline requirements, or merge checks. - Redirect safety: redirects are disabled and the production host is fixed to GitLab.com. Caller-controlled GitLab Self-Managed URLs are intentionally unsupported.
- External verification: deterministic tests cover validation, project-path encoding, PAT/OAuth headers, fixed routing, pagination, request construction, retries, mutation non-retry, redaction, identity checks, and annotation discovery. Live GitLab execution is deferred until a separately authorized account is supplied.
See the official n8n GitLab node source, GitLab REST API, Issues API, Merge requests API, and Pipelines API for upstream functional references.