> ## 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` | GitLab access token used to authenticate with CodeAnt AI. 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. Get Your GitLab Access Token

1. Log in to your GitLab account
2. Go to **Edit profile (User Settings) > Access Tokens**
3. Create a new token with the `api` scope (This grants full read/write access to the API and repositories)
4. Copy the 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 GitLab Access 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 GitLab Access Token
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` is valid and that its owner has access to the project — the validator calls `GET /api/v4/projects/{repo}` with the token and rejects anything other than `200`. A token can be alive (200 on `/api/v4/user`) but still 404 on the project if its owner was removed from the project.
* 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/)
