Browse the docs

GitLab CI

Scan merge request previews on GitLab.com with the released QualityGate template, and post the result as a merge request note.

QualityGate supports merge request pipelines, pushes to the default branch, and scheduled pipelines on GitLab.com. Self-managed GitLab instances are not supported yet.

The scan runs in a container image published by QualityGate that already contains the browser, so there is nothing to install.

1. Create the project

In the app, go to Projects → Create project → GitLab and enter:

  • the project path exactly as GitLab shows it in CI_PROJECT_PATH, for example acme/web or acme/marketing/site;
  • the default branch, for example main;
  • the allowed preview domains, for example *.preview.example.com.

Create an API key named GitLab CI on the project card and copy it. It is shown only once.

2. Add CI/CD variables

In GitLab, open Settings → CI/CD → Variables and add:

VariableValueSettings
QUALITYGATE_API_KEYThe project API key.Masked, expansion off
QUALITYGATE_GITLAB_TOKENA project access token for a bot user, role Reporter or higher, scope api. Only needed for merge request notes.Masked, expansion off

Mark them Protected if your merge request pipelines run on protected branches only. Never expose either value to pipelines from forks.

3. Include the template

Pick a release from the QualityGate releases page and add this to .gitlab-ci.yml, replacing v1.0.0 with that version:

include:
  - remote: 'https://github.com/qualitygate/scan-action/releases/download/v1.0.0/qualitygate.gitlab-ci.yml'

qualitygate:
  extends: .qualitygate
  variables:
    QUALITYGATE_URL: https://mr-$CI_MERGE_REQUEST_IID.preview.example.com
    QUALITYGATE_BUNDLE: a11y
    QUALITYGATE_FAIL_ON: critical=0,serious=0

The template runs the job for merge request pipelines, pushes to the default branch, and scheduled pipelines, in the test stage. If you define your own stages, include test or set stage: on the job.

The release pins the scanner image by its SHA-256 digest. To upgrade, change the version in the include URL; do not override image.

Using a Review App URL

If a job deploys a Review App, pass its URL to QualityGate with a dotenv artifact so the scan always targets the environment that job created:

deploy_review:
  stage: deploy
  script:
    - ./deploy-review.sh "$CI_COMMIT_REF_SLUG"
    - echo "QUALITYGATE_URL=https://$CI_COMMIT_REF_SLUG.preview.example.com" >> review.env
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    url: https://$CI_COMMIT_REF_SLUG.preview.example.com
  artifacts:
    reports:
      dotenv: review.env
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

qualitygate:
  extends: .qualitygate
  stage: review
  needs: [deploy_review]
  variables:
    QUALITYGATE_BUNDLE: full
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

Add a review stage after deploy in your stages list. Variables from a dotenv report are available to jobs that need the job that produced them. The rules override keeps this job to merge requests, where the Review App exists; add a second job extending .qualitygate for default-branch baselines.

Variables

VariableRequiredDefaultPurpose
QUALITYGATE_API_KEYYesnoneProject API key.
QUALITYGATE_URLYesnonePreview URL on an allowed domain.
QUALITYGATE_GITLAB_TOKENFor notesnoneGitLab token with api scope, used only for merge request notes.
QUALITYGATE_BUNDLENoa11ySee Bundles and checks.
QUALITYGATE_FAIL_ONNocritical=0,serious=0Limits or regression. See Gates and regression mode.
QUALITYGATE_WAIT_FOR_URLNotrueWait for the preview to answer before scanning.
QUALITYGATE_WAIT_TIMEOUTNo120Seconds to wait for the preview.
QUALITYGATE_COMMENTNotruePost or update the merge request note. Set 'false' to skip it and the GitLab token.
QUALITYGATE_ID_TOKENAutomaticset by the templateGitLab-signed job identity. Do not create it yourself.

Identity and security

The template asks GitLab for an ID token with the audience https://api.qualitygate.dev. GitLab signs it for this job only, and QualityGate checks that it was issued by GitLab.com for the project path you registered. Keep both secrets masked and never echo them in scripts.

Results

  • The job fails when authorization is refused, the upload fails, or the gate fails. It also fails if a requested merge request note cannot be published.
  • QualityGate keeps one note per merge request and updates it on each run.
  • Runs on the default branch record the baseline for regression mode and post no note.
  • Scheduled pipelines count as scheduled scans. Set QUALITYGATE_URL on the schedule itself under Build → Pipeline schedules.