Skip to content

GitLab

Detailed guide for integration with GitLab CI.


Tokens

Personal Access Token (PAT)

Recommended for all GitLab plans (including Free).

CI_JOB_TOKEN does not work

GitLab's automatic CI_JOB_TOKEN cannot post comments to Merge Requests (the Notes API requires api scope, which CI_JOB_TOKEN does not have). You must use a Personal Access Token or Project Access Token.

How to create:

  1. Go to User Settings โ†’ Access Tokens โ†’ Add new token
    • URL: https://gitlab.com/-/user_settings/personal_access_tokens
  2. Fill in the fields:
    • Token name: ai-code-reviewer
    • Expiration date: set as needed (e.g., 1 year)
    • Scopes: check api
  3. Click Create personal access token
  4. Copy the token immediately โ€” GitLab shows it only once!

How to use in CI:

  1. Go to Settings โ†’ CI/CD โ†’ Variables โ†’ Add variable
  2. Add variable:
    • Key: AI_REVIEWER_GITLAB_TOKEN
    • Value: paste your token
    • Flags: check Masked, uncheck Protected

The variable is automatically available to all jobs โ€” no YAML variables: mapping needed.

Uncheck ยซProtectedยป!

By default GitLab marks new variables as Protected. Protected variables are only available in protected branches (e.g. main).

MR pipelines run on unprotected source branches โ€” so the variable will be empty and you'll get 401 Unauthorized.

Always uncheck ยซProtectedยป for AI_REVIEWER_GITLAB_TOKEN and AI_REVIEWER_GOOGLE_API_KEY.

Save the token

GitLab shows the token only once. Save it in a secure location immediately.

Project Access Token ( Premium/Ultimate)

Available only on GitLab Premium and Ultimate plans. A good choice if you prefer a project-scoped token instead of a personal one.

Advantages over PAT:

  • Scoped to a single project (no access to other projects)
  • Can be revoked by project maintainers (no dependency on a specific user)
  • Better for teams โ€” not tied to a personal account

How to create:

  1. Go to Project โ†’ Settings โ†’ Access Tokens
    • URL: https://gitlab.com/<owner>/<repo>/-/settings/access_tokens
  2. Fill in the fields:
    • Token name: ai-code-reviewer
    • Role: Developer (minimum required)
    • Scopes: check api
  3. Click Create project access token
  4. Copy the token immediately

How to use in CI:

Same as PAT โ€” add as CI/CD variable with key AI_REVIEWER_GITLAB_TOKEN and check Masked, uncheck Protected.

The variable is automatically available to all jobs โ€” no YAML variables: mapping needed.

Which token to choose?

Personal Access Token Project Access Token
Plan All (including Free) Premium/Ultimate only
Setup Manual Manual
Scope All user's projects Single project
Post comments โœ… โœ…
Inline discussions โœ… โœ…
Best for Free plan, personal use Teams on Premium/Ultimate

CI/CD Variables

Adding Variables

Settings โ†’ CI/CD โ†’ Variables โ†’ Add variable

Variable Value Options
AI_REVIEWER_GOOGLE_API_KEY Gemini API key โœ… Masked, โŒ Uncheck Protected
AI_REVIEWER_GITLAB_TOKEN PAT (if needed) โœ… Masked, โŒ Uncheck Protected

Masked

Always enable Masked for secrets โ€” they won't be shown in logs.


Triggers

rules:
  - if: $CI_PIPELINE_SOURCE == "merge_request_event"

This runs the job only for Merge Request pipelines.

Alternative Trigger (only/except)

only:
  - merge_requests

rules vs only

rules โ€” newer syntax, recommended by GitLab.


Job Examples

Minimal

ai-review:
  image: ghcr.io/konstziv/ai-code-reviewer:1
  script:
    - ai-review
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

CI/CD variables

AI_REVIEWER_GOOGLE_API_KEY and AI_REVIEWER_GITLAB_TOKEN are inherited automatically from project CI/CD variables โ€” no variables: section needed.

ai-review:
  image: ghcr.io/konstziv/ai-code-reviewer:1
  stage: test
  script:
    - ai-review
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  allow_failure: true
  timeout: 10m
  variables:
    AI_REVIEWER_LANGUAGE: uk
    AI_REVIEWER_LANGUAGE_MODE: adaptive
  interruptible: true

What it does:

  • allow_failure: true โ€” MR is not blocked if review fails
  • timeout: 10m โ€” maximum 10 minutes
  • interruptible: true โ€” can be cancelled on new commit

With Custom Stage

stages:
  - test
  - review
  - deploy

ai-review:
  stage: review
  image: ghcr.io/konstziv/ai-code-reviewer:1
  script:
    - ai-review
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  needs: []  # Don't wait for previous stages

Self-hosted GitLab

Configuration

variables:
  AI_REVIEWER_GITLAB_URL: https://gitlab.mycompany.com

Docker Registry

If your GitLab doesn't have access to ghcr.io, create a mirror:

# On a machine with access
docker pull ghcr.io/konstziv/ai-code-reviewer:1
docker tag ghcr.io/konstziv/ai-code-reviewer:1 \
    gitlab.mycompany.com:5050/devops/ai-code-reviewer:latest
docker push gitlab.mycompany.com:5050/devops/ai-code-reviewer:latest
ai-review:
  image: gitlab.mycompany.com:5050/devops/ai-code-reviewer:latest

GitLab CI Variables

AI Code Reviewer automatically uses:

Variable Description
CI_PROJECT_PATH owner/repo
CI_MERGE_REQUEST_IID MR number
CI_SERVER_URL GitLab URL

You don't need to pass --repo and --pr โ€” they're taken from CI automatically.


Variable-Driven Configuration

Use CI/CD Variables to switch between LLM providers and models without changing .gitlab-ci.yml. This is useful for comparing review quality across different models on the same MR.

Setup

CI/CD Variables (Settings โ†’ CI/CD โ†’ Variables):

Variable Description Flags
AI_REVIEWER_GOOGLE_API_KEY Gemini API key โœ… Masked, โŒ Uncheck Protected
AI_REVIEWER_MISTRAL_API_KEY Mistral API key โœ… Masked, โŒ Uncheck Protected
AI_REVIEWER_GITLAB_TOKEN GitLab token โœ… Masked, โŒ Uncheck Protected
AI_REVIEWER_LLM_PROVIDER Primary provider (google, mistral) โŒ Uncheck Protected
AI_REVIEWER_LLM_FALLBACK_PROVIDER Fallback provider โŒ Uncheck Protected
AI_REVIEWER_MISTRAL_MODEL Mistral model โŒ Uncheck Protected
AI_REVIEWER_MISTRAL_API_URL Custom API URL (for Codestral free tier) โŒ Uncheck Protected

Job Configuration

ai-review:
  image: ghcr.io/konstziv/ai-code-reviewer:1
  stage: review
  script:
    - ai-review
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  allow_failure: true
  interruptible: true

No variables: section needed โ€” all AI_REVIEWER_* CI/CD variables are inherited automatically.

Switching Presets

Change CI/CD Variables in the GitLab UI, then Retry the pipeline on the same MR:

Preset AI_REVIEWER_LLM_PROVIDER AI_REVIEWER_MISTRAL_MODEL AI_REVIEWER_MISTRAL_API_URL AI_REVIEWER_LLM_FALLBACK_PROVIDER
Gemini (default) google (empty) (empty) (empty)
Mistral Large mistral mistral-large-latest (empty) google
Codestral free mistral codestral-latest https://codestral.mistral.ai google
Devstral mistral devstral-latest (empty) google

Codestral free tier key

For the "Codestral free" preset, AI_REVIEWER_MISTRAL_API_KEY must contain a key from codestral.mistral.ai, not from console.mistral.ai.

No need to hardcode in YAML

Unlike GitHub Actions (where inputs must be mapped explicitly), GitLab CI automatically passes all CI/CD variables as environment variables. Just set them in the UI โ€” the application picks them up via AI_REVIEWER_* prefix.


Review Result

Notes (comments)

AI Review posts comments to MR as notes.

Discussions (inline)

For inline comments, you need a Personal Access Token (or Project Access Token) with api scope.

Inline comments appear directly next to code lines in the diff view.

Summary

At the end of the review, a Summary note is posted with:

  • Overall statistics
  • Metrics
  • Good practices

Troubleshooting

Review Not Posting Comments

Check:

  1. AI_REVIEWER_GOOGLE_API_KEY variable is set
  2. AI_REVIEWER_GITLAB_TOKEN has sufficient permissions (scope: api)
  3. Pipeline is running for MR (not for a branch)

"401 Unauthorized"

Cause: Invalid token.

Solution:

  • Check that the token is not expired
  • Check scope (need api)

"403 Forbidden"

Cause: Insufficient permissions.

Solution:

  • Ensure you are using a Personal Access Token (or Project Access Token) with api scope
  • Check that the token has access to the project

"404 Not Found"

Cause: MR not found.

Solution:

  • Check that the pipeline is running for MR
  • Check CI_MERGE_REQUEST_IID

Rate Limit (429)

Cause: API limit exceeded.

Solution:

  • AI Code Reviewer automatically retries with backoff
  • If persistent โ€” wait or increase limits

Best Practices

1. Use a Personal Access Token

Create a CI/CD variable named AI_REVIEWER_GITLAB_TOKEN with your PAT value โ€” it will be inherited by all jobs automatically.

2. Add allow_failure

allow_failure: true

MR won't be blocked if review fails.

3. Set timeout

timeout: 10m

4. Make job interruptible

interruptible: true

Old review will be cancelled on new commit.

5. Don't wait for other stages

needs: []

Review will start immediately, without waiting for build/test.


Next Step