> ## Documentation Index
> Fetch the complete documentation index at: https://docs.codeant.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# GitLab CI/CD

> Set up GitLab CI/CD workflow for coverage reporting.

# CodeAnt AI Coverage Upload for GitLab

Upload test coverage reports to CodeAnt AI for comprehensive analysis, visualization, and tracking of your code coverage metrics.

## Features

* 📊 Upload coverage reports in XML format (Cobertura XML, JaCoCo XML)
* 🔍 Automatic coverage analysis and insights
* 📈 Track coverage trends over time
* 🎯 Integration with merge requests
* 🚀 Easy setup with minimal configuration

## Usage

### Basic Example

```yaml theme={null}
include:
  - remote: 'https://gitlab.com/codeant-pipelines/code-coverage-gitlab/-/raw/main/.gitlab-ci.yml'

stages:
  - test
  - report

test:
  stage: test
  image: python:3.9
  script:
    # Your test command that generates coverage report
    - pytest --cov --cov-report=xml
  artifacts:
    paths:
      - coverage.xml

codeant_coverage:
  extends: .codeant_coverage_upload
  stage: report
  needs: [test]
  variables:
    COVERAGE_FILE: "coverage.xml"
```

### Advanced Example

```yaml theme={null}
codeant_coverage:
  extends: .codeant_coverage_upload
  stage: report
  needs: [test]
  variables:
    COVERAGE_FILE: "coverage.xml"
    MODULE: "backend"
    MODULE_PATH: "services/backend"
    # API_BASE, PLATFORM, BASE_URL fall back to sensible defaults; only override
    # them if you're on a private CodeAnt AI deployment or self-hosted GitLab.
```

## Inputs

`ACCESS_TOKEN` must be added as a project (or group) **CI/CD variable** so it can be masked - never paste it into your `.gitlab-ci.yml`. The remaining variables go under `variables:` inside the upload job.

**Set as a CI/CD variable**

| Variable       | Description                                                                                                                                  | Required |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `ACCESS_TOKEN` | CodeAnt API token (`cdt_…`) used to authenticate with CodeAnt AI - see [API Tokens](/settings/api-tokens). The script reads this exact name. | Yes      |

**Set under `variables:` in your `.gitlab-ci.yml`**

| Variable        | Description                                                                                                                                                 | Required | Default                  |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------ |
| `COVERAGE_FILE` | Path to the coverage XML file (e.g. `coverage.xml`).                                                                                                        | Yes      | `coverage.xml`           |
| `API_BASE`      | CodeAnt AI API base URL.                                                                                                                                    | No       | `https://api.codeant.ai` |
| `PLATFORM`      | Git platform (`github`, `gitlab`, `bitbucket`).                                                                                                             | No       | `gitlab`                 |
| `BASE_URL`      | Base URL of the git platform. Leave at the default for self-hosted GitLab - `$CI_SERVER_URL` is set automatically per pipeline.                             | No       | `$CI_SERVER_URL`         |
| `MODULE`        | Module name for monorepo setups (e.g. `backend`, `frontend`). Required when uploading multiple coverage files for the same commit so reports don't collide. | No       | -                        |
| `MODULE_PATH`   | Module path used to resolve files in a monorepo (e.g. `services/backend`). Defaults to `MODULE` if omitted.                                                 | No       | `MODULE`                 |

## Supported Coverage Formats

> **Important:** Only XML format is supported for coverage reports.

* Cobertura XML (.xml)
* JaCoCo XML

## Setup

### 1. Create a CodeAnt Token

In CodeAnt AI, open the user menu (click your email at the bottom-left) and select **API Tokens**, click **Create token**, and copy the generated token (it starts with `cdt_` and is shown only once). See [API Tokens](/settings/api-tokens) for the full walkthrough. This single token authenticates the upload - you don't need a GitLab access token.

### 2. Generate Coverage Report

First, ensure your test suite generates a coverage report. Here are examples for common languages:

**Python (pytest)**

```bash theme={null}
pytest --cov --cov-report=xml
```

**JavaScript/TypeScript (Jest)**

```bash theme={null}
jest --coverage --coverageReporters=cobertura
```

**Java (Maven)**

```bash theme={null}
mvn test jacoco:report
```

**Go**

```bash theme={null}
go test -coverprofile=coverage.out ./...
gocov convert coverage.out | gocov-xml > coverage.xml
```

### 3. Add CI/CD Variables

Add your CodeAnt token to your GitLab project:

1. Go to your repository **Settings**
2. Navigate to **CI/CD > Variables**
3. Click **"Add variable"**
4. **Key:** `ACCESS_TOKEN` (this is the variable name the included template reads)
5. **Value:** Your CodeAnt token (`cdt_…`)
6. **Protected:** Yes (recommended)
7. **Masked:** Yes (recommended)

### 4. Configure Pipeline

Add the template to your `.gitlab-ci.yml` as shown in the usage examples above.

## How It Works

1. The job fetches the latest coverage upload script from CodeAnt AI
2. Decodes and prepares the script for execution
3. Uploads your coverage report along with commit and branch information
4. CodeAnt AI processes the report and provides analysis

## Examples

### Python Project

```yaml theme={null}
include:
  - remote: 'https://gitlab.com/codeant-pipelines/code-coverage-gitlab/-/raw/main/.gitlab-ci.yml'

stages:
  - test
  - report

test:
  stage: test
  image: python:3.9
  script:
    - pip install pytest pytest-cov
    - pytest --cov=. --cov-report=xml
  artifacts:
    paths:
      - coverage.xml

codeant_coverage:
  extends: .codeant_coverage_upload
  stage: report
  needs: [test]
  variables:
    COVERAGE_FILE: "coverage.xml"
```

### Node.js Project

```yaml theme={null}
include:
  - remote: 'https://gitlab.com/codeant-pipelines/code-coverage-gitlab/-/raw/main/.gitlab-ci.yml'

stages:
  - test
  - report

test:
  stage: test
  image: node:18
  script:
    - npm ci
    - npm test -- --coverage --coverageReporters=cobertura
  artifacts:
    paths:
      - coverage/cobertura-coverage.xml

codeant_coverage:
  extends: .codeant_coverage_upload
  stage: report
  needs: [test]
  variables:
    COVERAGE_FILE: "coverage/cobertura-coverage.xml"
```

### Java Project

```yaml theme={null}
include:
  - remote: 'https://gitlab.com/codeant-pipelines/code-coverage-gitlab/-/raw/main/.gitlab-ci.yml'

stages:
  - test
  - report

test:
  stage: test
  image: maven:3.8-openjdk-11
  script:
    - mvn clean test jacoco:report
  artifacts:
    paths:
      - target/site/jacoco/jacoco.xml

codeant_coverage:
  extends: .codeant_coverage_upload
  stage: report
  needs: [test]
  variables:
    COVERAGE_FILE: "target/site/jacoco/jacoco.xml"
```

### Multiple Coverage Files (Monorepo)

When a single commit produces several coverage reports - for example one per service in a monorepo - give each upload its own `MODULE` and `MODULE_PATH`. CodeAnt AI keeps the reports separate so each module is tracked, displayed, and gated independently. Without `MODULE`, every upload writes to the same key and later jobs overwrite earlier ones.

* `MODULE` is the logical name shown in the UI (e.g. `backend`, `frontend`).
* `MODULE_PATH` is the directory used to resolve source files referenced in the coverage XML (e.g. `services/backend`). If your XML's `filename` attributes are relative to the module root, set `MODULE_PATH` to that root.

#### Recommended: a single job with `parallel:matrix`

Instead of duplicating the upload block per module, define it once and fan it out with [`parallel:matrix`](https://docs.gitlab.com/ee/ci/yaml/index.html#parallelmatrix). Each matrix entry becomes its own parallel job; adding a new module is one new entry instead of an entire job stanza.

The job name `codeant_coverage` matches the one shipped by the included template, so this definition replaces it. Provide your own `test_*` jobs that emit each module's coverage XML at the path referenced by `COVERAGE_FILE`.

```yaml theme={null}
include:
  - remote: 'https://gitlab.com/codeant-pipelines/code-coverage-gitlab/-/raw/main/.gitlab-ci.yml'

stages:
  - test
  - report

# Your own test jobs that emit per-module coverage.xml as artifacts.
test_backend:
  stage: test
  image: python:3.9
  script:
    - cd services/backend
    - pip install pytest pytest-cov && pytest --cov --cov-report=xml
  artifacts:
    paths:
      - services/backend/coverage.xml

test_frontend:
  stage: test
  image: node:18
  script:
    - cd services/frontend
    - npm ci && npm test -- --coverage --coverageReporters=cobertura
  artifacts:
    paths:
      - services/frontend/coverage/cobertura-coverage.xml

# Single upload job; one variant runs per matrix entry.
codeant_coverage:
  extends: .codeant_coverage_upload
  stage: report
  parallel:
    matrix:
      - MODULE: backend
        MODULE_PATH: services/backend
        COVERAGE_FILE: services/backend/coverage.xml
      - MODULE: frontend
        MODULE_PATH: services/frontend
        COVERAGE_FILE: services/frontend/coverage/cobertura-coverage.xml
      - MODULE: api
        MODULE_PATH: services/api
        COVERAGE_FILE: services/api/coverage.xml
```

GitLab spawns one job per matrix entry - `codeant_coverage: [backend, services/backend, services/backend/coverage.xml]`, `codeant_coverage: [frontend, …]`, etc. - and each one runs the upload independently with its own `MODULE`, `MODULE_PATH`, and `COVERAGE_FILE`.

#### Alternative: one job per module

If you prefer the explicit form (e.g. you want each module gated by a different upstream `needs:`), define a job per module:

```yaml theme={null}
codeant_coverage_backend:
  extends: .codeant_coverage_upload
  stage: report
  needs: [test_backend]
  variables:
    COVERAGE_FILE: "services/backend/coverage.xml"
    MODULE: "backend"
    MODULE_PATH: "services/backend"

codeant_coverage_frontend:
  extends: .codeant_coverage_upload
  stage: report
  needs: [test_frontend]
  variables:
    COVERAGE_FILE: "services/frontend/coverage/cobertura-coverage.xml"
    MODULE: "frontend"
    MODULE_PATH: "services/frontend"
```

## Troubleshooting

**Coverage file not found**

* Ensure the `COVERAGE_FILE` path is correct and the file exists as an artifact from a previous job.

**Authentication failed / `Invalid access token`**

* Verify that your `ACCESS_TOKEN` holds a valid CodeAnt token (`cdt_…`) that hasn't been revoked. You can check and re-issue tokens under **API Tokens** (in the user menu - your email at the bottom-left) in CodeAnt AI - see [API Tokens](/settings/api-tokens).
* Make sure the token belongs to the same organization/workspace as the repository you're uploading coverage for. A token is scoped to one provider + organization.
* If you have an `ACCESS_TOKEN` defined as a project-level CI/CD variable, it overrides any `ACCESS_TOKEN` set in `.gitlab-ci.yml` (project-level CI variables take precedence over YAML variables). Update or remove the project-level variable rather than trying to override it from YAML.

**Script execution failed**

* Check that the CodeAnt AI API is accessible from your runner environment.

## Contributing

Contributions are welcome! Please feel free to submit a Merge Request.

## License

This project is licensed under the MIT License - see the LICENSE file for details.

## Support

* 📧 Email: [support@codeant.ai](mailto:support@codeant.ai)
* 📚 Documentation: [https://docs.codeant.ai](https://docs.codeant.ai)
* 🐛 Issues: [https://gitlab.com/codeant-pipelines/code-coverage-gitlab](https://gitlab.com/codeant-pipelines/code-coverage-gitlab)

## Related

* [CodeAnt AI](https://codeant.ai) - AI-powered code analysis platform
* [GitLab CI/CD Documentation](https://docs.gitlab.com/ee/ci/)## Token permission

This pipeline authenticates with a CodeAnt API token (`cdt_…`). If the token is **scoped**, give it the **Codeant CI/CD** role - it covers scans, quality gates, and test-coverage upload - scoped to the repositories this pipeline runs on (or **All repositories**). A token missing the required permission is rejected with an HTTP `403` `token_scope_forbidden` error that names the permission it needs. See [API token permissions](/settings/api-tokens#permissions-and-scopes).
