Delta-aware cyclomatic complexity reporting for GitLab Code Quality.
Wraps lizard to produce GitLab-compatible Code Quality reports that surface complexity regressions and improvements on MR diffs, not just static threshold violations.
The naive approach — flag every function above a CCN threshold — produces a report full of pre-existing issues that look identical in every pipeline. GitLab sees no change between the MR and target branch reports, so nothing appears in the Code Quality widget.
lizard-delta solves this by comparing against the merge-base version of each
changed file and emitting fingerprints that tell GitLab exactly what got worse,
what got better, and what is being carried over unchanged.
| Before | After | Result |
|---|---|---|
| 15 | 31 | New issue (minor) |
| 15 | 65 | New issue (major) |
| 31 | 32 | New issue — worsened (+ stable carry-over) |
| 32 | 31 | Resolved issue |
| 31 | 15 | Resolved issue |
| 31 | 31 | No change |
| 15 | 10 | No change |
Unchanged files fall back to threshold-only reporting.
pip install lizard-deltaRuns lizard on the merge-base versions of files changed in the current branch, producing a baseline CSV for delta comparison.
usage: lizard-base [--out FILE] [--base-ref COMMIT] [--target-branch BRANCH]
--out FILE Output CSV path (default: lizard_base_report.csv)
--base-ref COMMIT Use this commit as the base instead of computing merge-base
--target-branch BRANCH Branch to find merge base against (default: main)
Converts a lizard CSV report to GitLab Code Quality JSON. When --base-csv is
provided, applies delta rules for changed files.
usage: lizard-to-code-quality [--csv FILE] [--base-csv FILE] [--out FILE]
[--ccn-minor N] [--ccn-major N]
--csv FILE lizard CSV input (default: lizard_report.csv)
--base-csv FILE lizard CSV for merge base from lizard-base (enables delta reporting)
--out FILE Code Quality JSON output (default: gl-code-quality-report.json)
--ccn-minor N CCN threshold for flagging a function (default: 30)
--ccn-major N CCN threshold for major severity (default: 60)
variables:
CCN_MINOR: "30"
CCN_MAJOR: "60"
check-complexity:
stage: check
before_script:
- pip install lizard-delta
script:
- lizard --modified --csv --output_file lizard_report.csv src
- |
if [ -n "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-}" ]; then
lizard-base --target-branch "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}"
lizard-to-code-quality \
--base-csv lizard_base_report.csv \
--ccn-minor "${CCN_MINOR}" \
--ccn-major "${CCN_MAJOR}"
else
lizard-to-code-quality \
--ccn-minor "${CCN_MINOR}" \
--ccn-major "${CCN_MAJOR}"
fi
artifacts:
reports:
codequality: gl-code-quality-report.json
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCHMIT