# GitLab CI/CD

Source: https://docs.qualflare.com/docs/cli/ci-cd/gitlab-ci · Last updated: 2026-10-27

Upload test results from GitLab CI/CD to Qualflare with the qf CLI: a .gitlab-ci.yml job that runs when tests fail, with a masked QF_TOKEN variable.

To upload test results from GitLab CI/CD to Qualflare, add a job that runs `qf <identifier> collect <report>` after your tests, with the access token stored as a masked CI/CD variable named `QF_TOKEN`; qf reads `CI_COMMIT_REF_NAME` and `CI_COMMIT_SHA` itself.

## Before you begin

* A project access token with **Allow writes** off, which you create in **Project Settings** > **Access Tokens** (requires the Editor role or higher in the project). See [Access Tokens](https://docs.qualflare.com/docs/api/access-tokens).
* A report file your test job writes, such as JUnit XML. The examples use `ci` as the identifier.

## Store the token as a CI/CD variable

1. Go to your project **Settings** > **CI/CD** > **Variables**
2. Click **Add variable**
3. Key: `QF_TOKEN`
4. Value: Your Qualflare access token
5. Mask variable: **Checked**
6. Protect variable: Optional
7. Click **Add variable**

A protected variable reaches only pipelines that run on protected branches and tags.

## Add the upload job

Add to your `.gitlab-ci.yml`:

```yaml
stages:
  - test
  - report

# Run your tests
test:
  stage: test
  script:
    - pytest --junitxml=results.xml
  artifacts:
    when: always
    paths:
      - results.xml
    expire_in: 1 week

# Upload to Qualflare
upload-results:
  stage: report
  needs:
    - test
  when: always  # upload even when the test job fails
  script:
    # Install qf CLI
    - VERSION=0.4.0
    - curl -L "https://github.com/qualflare/qualflare-cli/releases/download/v${VERSION}/qf_${VERSION}_linux_amd64.tar.gz" -o qf.tar.gz
    - tar -xzf qf.tar.gz && mv qf /usr/local/bin/

    # Upload to Qualflare (qf login reads the QF_TOKEN variable)
    - qf login ci --force
    - qf ci collect results.xml
  variables:
    QF_ENVIRONMENT: staging  # must be an environment that exists in the project
    # Branch and commit auto-detected from CI_COMMIT_REF_NAME and CI_COMMIT_SHA
```

The job image needs `curl` and `tar`, and must be able to write `/usr/local/bin`. See the official [GitLab CI/CD documentation](https://docs.gitlab.com/ee/ci/) for `.gitlab-ci.yml` syntax and pipeline concepts beyond what's shown here.

## Branch and commit

qf reads the branch from `CI_COMMIT_REF_NAME` and the commit from `CI_COMMIT_SHA`, which GitLab sets in every job, so there is nothing to set.

## Run the upload when tests fail

`when: always` on the upload job runs it after a failed test job, and `artifacts: when: always` on the test job keeps the report for it.

*Figure: With when: always, the upload job runs after a failed test job, and artifacts when: always passes it the report.*

## Parallel jobs

One `qf <identifier> collect` call is one launch, and several files in one call merge into it. With GitLab `parallel:`, save each job's report as an artifact and upload them all from one later job with `--shard`: see [Sharded runs](https://docs.qualflare.com/docs/cli/sharding).

## Pin the qf version

The example installs qf 0.4.0 through `VERSION=0.4.0`. To pin another release, set `VERSION` to a version from the [qf releases page](https://github.com/qualflare/qualflare-cli/releases).

## Troubleshooting

The job fails at `qf login` with `Error: token cannot be empty`, or the [guard line](https://docs.qualflare.com/docs/cli/ci-cd#login-fails-in-ci) prints `QF_TOKEN is not set`, when `QF_TOKEN` is a protected variable and the pipeline runs on a branch that isn't protected. More fixes: [Troubleshooting](https://docs.qualflare.com/docs/cli/ci-cd#troubleshooting) on CI/CD integration.

## Related

* **Guides:** [CI/CD integration](https://docs.qualflare.com/docs/cli/ci-cd) · [GitLab Integration](https://docs.qualflare.com/docs/integrations/gitlab), a different feature that files GitLab issues from Qualflare
* **Reference:** [Upload results with qf collect](https://docs.qualflare.com/docs/cli/collect)
* **CLI/API:** [Access Tokens](https://docs.qualflare.com/docs/api/access-tokens)
