Skip to main content

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

  1. Create a GitLab personal, project, or group access token, or an OAuth access token, with only the scopes required by the workflow.
  2. Store that token in the encrypted apiKey or password field of a ValkyrAI IntegrationAccount; set the account status to READY.
  3. Bind the account through ExecModuleConfig.authConfig.integrationAccount.
  4. Choose authMode: private_token for a PAT or authMode: oauth2 for an OAuth bearer token.
  5. Select one operation and provide its conditional project, resource, filter, or body fields.
  6. When a list returns hasMore: true, pass nextPage as the next execution's page.

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

NameTypeRequiredDescriptionConstraints
operationstringYesOperation listed below.Exact allowlist of 16 values.
projectIdstring or integerConditionalNumeric project ID or namespace/project path.1–512 characters; path segments use letters, digits, dot, underscore, and hyphen.
resourceIidintegerConditionalProject-scoped issue or merge-request IID.Positive 32-bit integer.
pipelineIdintegerConditionalGlobal pipeline ID for retry or cancellation.Positive integer.
recordobject or JSON stringConditionalAllowlisted body fields for a mutation.At most 12 fields and 256 KiB encoded.
queryobject or JSON stringNoAllowlisted list filters.At most 10 scalar fields; values bounded to 1,024 characters.
pageintegerNoOne-based offset page.1–10,000; default 1.
limitintegerNoItems requested from one provider page.1–100; default 50.
authModestringNoAuthentication 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, and discussion_locked as applicable.
  • Issue notes: body, confidential, and internal.
  • 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, and inputs for creation.

Token-, password-, secret-, and authorization-shaped fields are rejected from workflow payloads.

Outputs

NameTypeWhen presentDescription
statusstringAlwayssuccess or error.
operationstringAlwaysNormalized operation.
resourcestringAfter validationprojects, issues, notes, merge_requests, or pipelines.
dataobjectSingle-resource successGitLab response after identity validation.
id or iidintegerIdentity-bearing successVerified provider identity.
itemsarrayList successOne bounded provider page.
countintegerList successItems returned in that page.
hasMorebooleanList successWhether GitLab supplied X-Next-Page.
nextPageintegerWhen another page existsValidated next page number.
httpStatusintegerProvider responseGitLab HTTP status.
attemptsintegerProvider call or errorHTTP attempts consumed.
errorobjectFailureRedacted 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

SettingRequirement
ProviderGitLab.com REST API v4
AuthenticationPAT in PRIVATE-TOKEN, or OAuth 2.0 bearer token
StatusExactly READY
accountNameHuman-readable GitLab identity or automation purpose
apiKey or passwordEncrypted token, 20–4,096 non-whitespace characters
RelationshipExecModuleConfig.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_repository or write_repository is 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

ResourceOperationProvider routeBehavior
Projectslist_projectsGET /projectsOne page with membership, ownership, visibility, archive, search, and sort filters.
Projectsget_projectGET /projects/{id}Gets one numeric or namespaced project.
Issueslist_issuesGET /projects/{id}/issuesOne filtered issue page.
Issuesget_issueGET /projects/{id}/issues/{iid}Gets one issue and verifies its IID.
Issuescreate_issuePOST /projects/{id}/issuesCreates one bounded issue; title is required.
Issuesupdate_issuePUT /projects/{id}/issues/{iid}Updates allowlisted fields and verifies the response IID.
Notescreate_issue_notePOST /projects/{id}/issues/{iid}/notesAdds one bounded issue note; body is required.
Merge requestslist_merge_requestsGET /projects/{id}/merge_requestsOne filtered merge-request page.
Merge requestsget_merge_requestGET /projects/{id}/merge_requests/{iid}Gets one merge request and verifies its IID.
Merge requestscreate_merge_requestPOST /projects/{id}/merge_requestsCreates one merge request with required source, target, and title.
Merge requestsupdate_merge_requestPUT /projects/{id}/merge_requests/{iid}Updates allowlisted fields and verifies its IID.
Merge requestsmerge_merge_requestPUT /projects/{id}/merge_requests/{iid}/mergeRequests a governed merge with optional exact SHA and provider controls.
Pipelineslist_pipelinesGET /projects/{id}/pipelinesOne filtered pipeline page.
Pipelinescreate_pipelinePOST /projects/{id}/pipelineCreates one pipeline for a required ref with bounded variables or inputs.
Pipelinesretry_pipelinePOST /projects/{id}/pipelines/{pipelineId}/retryRetries jobs in one pipeline and verifies its ID.
Pipelinescancel_pipelinePOST /projects/{id}/pipelines/{pipelineId}/cancelCancels 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

FailureCauseRetry guidance
VALIDATION_ERRORMissing 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_REQUIREDNo bound secure account.Bind the intended GitLab account.
INTEGRATION_ACCOUNT_NOT_READYAccount status is not READY.Repair or refresh the account before execution.
GITLAB_HTTP_400/404Provider 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/403Expired token, wrong auth mode, missing scope, or insufficient project role.Refresh credentials and grant only the required scope/role.
GITLAB_HTTP_409/412Resource state, stale SHA, or merge precondition conflict.Read the resource, reconcile state, then submit a deliberate new mutation.
GITLAB_HTTP_429GitLab.com rate limit.Reads retry up to three total attempts; writes remain single-attempt.
GITLAB_HTTP_5xx / NETWORK_ERRORProvider or transport failure.Reads retry safely. Reconcile issues, notes, merge requests, merges, and pipelines before manual retry.
RESPONSE_TOO_LARGEProvider response exceeded 5 MiB.Narrow filters or reduce limit.
Invalid list or identity responseGitLab 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 nextPage into the next execution's page; no silent all-pages loop occurs.
  • Rate limits: GitLab.com applies global, endpoint, user, and abuse-prevention limits. The module handles numeric Retry-After with at most three attempts for GET only.
  • 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_request accepts an optional exact sha; 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.