A fast, Docker-based GitHub Action for validating test coverage from XML files against minimum thresholds. This action eliminates the need to install dependencies like libxml2-utils, bc, and other tools in your workflows.
- ✅ Fast execution - Pre-built Docker container with all dependencies
- ✅ Multiple formats - Supports Clover, Cobertura, and JaCoCo XML formats
- ✅ Configurable thresholds - Set minimum coverage percentages
- ✅ Clear output - Colored logs and detailed error messages
- ✅ GitHub Actions integration - Outputs for use in other steps
| Format | Description | Example Tools |
|---|---|---|
clover |
Clover XML format | PHPUnit, Jest, Vitest |
cobertura |
Cobertura XML format | pytest-cov, coverage.py |
jacoco |
JaCoCo XML format | JaCoCo (Java) |
This action follows semantic versioning with convenience tags:
@v1- Latest v1.x.x release (gets all updates, including new features)@v1.0- Latest v1.0.x release (gets patch updates only)@v1.0.4- Exact version (no automatic updates)
Recommended: Use @v1 for most use cases to get the latest improvements and security updates.
- name: Validate Coverage
uses: vln-devsecops/actions-validate-coverage@v1
with:
coverage-file: 'coverage/clover.xml'
minimum-coverage: '80'- name: Validate Coverage
uses: vln-devsecops/actions-validate-coverage@v1
with:
coverage-file: 'coverage/coverage.xml'
minimum-coverage: '85'
coverage-type: 'cobertura'
working-directory: './backend'- name: Validate Coverage
id: coverage
uses: vln-devsecops/actions-validate-coverage@v1
with:
coverage-file: 'coverage/clover.xml'
minimum-coverage: '80'
- name: Comment on PR
if: failure()
uses: actions/github-script@v6
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `❌ Coverage validation failed! Actual: ${{ steps.coverage.outputs.coverage-percentage }}%`
})| Input | Description | Required | Default |
|---|---|---|---|
coverage-file |
Path to the coverage XML file | ✅ | - |
minimum-coverage |
Minimum coverage percentage required | ❌ | 85 |
coverage-type |
XML format type (clover, cobertura, jacoco) |
❌ | cobertura |
working-directory |
Working directory for the coverage file | ❌ | . |
| Output | Description |
|---|---|
coverage-percentage |
The actual coverage percentage found |
status |
pass or fail status of validation |
name: Test Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run tests with coverage
run: npm run test:coverage
- name: Validate Coverage
uses: vln-devsecops/actions-validate-coverage@v1
with:
coverage-file: 'coverage/clover.xml'
minimum-coverage: '80'name: Test Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install dependencies
run: |
pip install pytest pytest-cov
- name: Run tests with coverage
run: pytest --cov=src --cov-report=xml
- name: Validate Coverage
uses: vln-devsecops/actions-validate-coverage@v1
with:
coverage-file: 'coverage.xml'
minimum-coverage: '85'
coverage-type: 'cobertura'name: Test Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Run tests with JaCoCo
run: ./mvnw test jacoco:report
- name: Validate Coverage
uses: vln-devsecops/actions-validate-coverage@v1
with:
coverage-file: 'target/site/jacoco/jacoco.xml'
minimum-coverage: '75'
coverage-type: 'jacoco'Before:
- name: Validate coverage
run: |
sudo apt-get update -y && sudo apt-get install -y libxml2-utils
COVERED=$(xmllint --xpath "string(/coverage/project/metrics/@coveredstatements)" coverage/clover.xml)
TOTAL=$(xmllint --xpath "string(/coverage/project/metrics/@statements)" coverage/clover.xml)
COVERAGE=$(echo "($COVERED * 100) / $TOTAL" | bc | awk '{print int($1)}')
if [ "$COVERAGE" -lt "80" ]; then
echo "Coverage $COVERAGE% is below 80%"
exit 1
fiAfter:
- name: Validate coverage
uses: vln-devsecops/actions-validate-coverage@v1
with:
coverage-file: 'coverage/clover.xml'
minimum-coverage: '80'# Run the unit test suite
bats tests/validate-coverage.bats
# Test the script directly
./validate-coverage.sh examples/clover.xml 80
# Build and test Docker image
./scripts/test-docker.sh
# Build Docker image manually
docker build -t validate-coverage .
# Test with a sample coverage file
docker run --rm -v $(pwd)/examples:/workspace validate-coverage \
/workspace/clover.xml 80 clover# Manual publish to GHCR (for initial setup)
./scripts/publish-docker.sh
# Create a release (automated pipeline)
./scripts/create-release.sh 1.0.0Important: The release script automatically updates action.yml to reference the specific version Docker image (e.g., ghcr.io/vln-devsecops/actions-validate-coverage:v1.0.0), ensuring reproducible releases.
The project includes VS Code tasks for development:
- Build Docker Image: Builds the Docker container
- Test Coverage Script: Tests the script directly
- Test Docker Action: Tests the Docker action
- Test Docker (All Formats): Comprehensive Docker testing
- Publish Docker to GHCR: Manual publish to registry
- Create Release: Streamlined release creation
- Fork the repository
- Create a feature branch
- Make your changes
- Test with different coverage file formats
- Submit a pull request (including evidence of non-regression)
MIT License - see LICENSE file for details.