Metadata-Version: 2.4
Name: ansible-lint2junit
Version: 1.1.0
Summary: ansible-lint to JUnit converter.
Author: Sam McCarthy
License-Expression: MIT
Project-URL: Homepage, https://gitlab.surrey.ac.uk/sm0049/ansible-lint2junit
Project-URL: Source, https://gitlab.surrey.ac.uk/sm0049/ansible-lint2junit
Project-URL: Documentation, https://ansible-lint2junit-78e150.pages.surrey.ac.uk
Project-URL: Changelog, https://gitlab.surrey.ac.uk/sm0049/ansible-lint2junit/-/blob/main/CHANGELOG.md
Project-URL: Issues, https://gitlab.surrey.ac.uk/sm0049/ansible-lint2junit/-/issues
Project-URL: Original, https://github.com/wasilak/ansible-lint-junit
Keywords: ansible,ansible-lint,junit,gitlab,ci,lint
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: defusedxml>=0.7.1
Provides-Extra: test
Requires-Dist: pytest>=8; extra == "test"
Requires-Dist: pytest-cov>=5; extra == "test"
Dynamic: license-file

# ansible-lint2junit

Converts [ansible-lint](https://github.com/ansible/ansible-lint) output into JUnit XML,
so lint findings show up as test results in CI — in particular in
[GitLab's test report UI](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html).

This is a fork of [wasilak/ansible-lint-junit](https://github.com/wasilak/ansible-lint-junit)
(MIT licensed), renamed and modernised for GitLab (Python 3.9+):

- Testcases carry a stable identity (`classname` = ansible-lint rule ID, `name` = `file:line message`),
  so GitLab can track newly-failed/resolved findings between pipeline runs.
- Testcases carry a `file` attribute, so GitLab links each finding to the source file.
- Suite `tests`/`failures` counts reflect the actual findings (summary lines and blanks are ignored).
- No longer depends on `ansible-lint` itself — only its text output — so it installs
  cleanly alongside any ansible-lint version (the only dependency is `defusedxml`).
- ANSI colour codes are stripped from the input, so forgetting `--nocolor` doesn't
  silently produce an empty report.
- `--fail-on-findings` lets one CI step both publish the report and fail the job.

## Installation

From [PyPI](https://pypi.org/project/ansible-lint2junit/):

```shell
pip install ansible-lint2junit
```

or from this project's [GitLab package registry](https://gitlab.surrey.ac.uk/sm0049/ansible-lint2junit/-/packages):

```shell
pip install ansible-lint2junit --index-url https://gitlab.surrey.ac.uk/api/v4/projects/sm0049%2Fansible-lint2junit/packages/pypi/simple
```

## Usage

Pipe `ansible-lint -p` output in:

```shell
ansible-lint playbook.yml -p --nocolor | ansible-lint2junit -o ansible-lint.xml
```

or go via a file (multiple input files are concatenated):

```shell
ansible-lint -p --nocolor playbook.yml > ansible-lint.txt
ansible-lint2junit ansible-lint.txt -o ansible-lint.xml
```

Options:

| Option | Description |
| --- | --- |
| `-o FILE` | output file (default `ansible-lint2junit.xml`); use `-o -` to write to stdout |
| `-v` | also print the XML to stdout |
| `-d` | emit a single dummy testcase when there are no findings, for CI parsers that reject empty suites |
| `-f`, `--fail-on-findings` | exit with status 1 when there is at least one finding |
| `--version` | print version |

If the input is non-empty but no line matches the `file:line: message` format,
a warning is printed to stderr — usually a sign the input wasn't produced with `-p`.

## GitLab CI example

```yaml
ansible-lint:
  image: python:3.13
  script:
    - pip install ansible-lint
    - pip install ansible-lint2junit --index-url https://gitlab.surrey.ac.uk/api/v4/projects/sm0049%2Fansible-lint2junit/packages/pypi/simple
    - ansible-lint -p --nocolor . > ansible-lint.txt || true
    - ansible-lint2junit ansible-lint.txt -o ansible-lint.xml --fail-on-findings
  artifacts:
    when: always
    reports:
      junit: ansible-lint.xml
```

The `|| true` keeps the job running so the report is always generated;
`--fail-on-findings` then fails the job when there are findings, after the report
exists. Drop it if lint findings should not fail the pipeline.

## Output

- Findings become JUnit `<failure>` testcases, grouped by ansible-lint rule.
- Clean input still produces a valid (empty) JUnit XML file, so JUnit parsers that
  fail on a missing report (e.g. Bamboo) keep working. Use `-d` for parsers that
  also reject suites with zero tests.
- Both modern ansible-lint (`rule-id[subrule] message`) and legacy (`[E301] message`)
  output formats are recognised; unrecognised lines that still look like
  `file:line: message` are kept with a generic `ansible-lint` classname.

## Development

```shell
pip install -e '.[test]'
pytest                  # tests (with coverage in CI)
ruff check . && ruff format --check .   # lint/format (pip install ruff)
mypy                    # type check (pip install mypy)
```

## License

Distributed under the MIT license, as is the
[original project](https://github.com/wasilak/ansible-lint-junit) by Piotr Boruc.
