Skip to content

Commit d9f6a56

Browse files
authored
Merge pull request #154 from Pennycook/coverage-action
Add coverage workflow to GitHub Actions
2 parents ceff713 + 3f28a3b commit d9f6a56

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

.github/workflows/check-coverage.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env python3
2+
import argparse
3+
import json
4+
import subprocess # nosec B404
5+
import sys
6+
7+
# Parse command-line arguments.
8+
parser = argparse.ArgumentParser()
9+
parser.add_argument("--commits", nargs="+", default=[])
10+
parser.add_argument("file", metavar="<coverage.json>", action="store")
11+
args = parser.parse_args(sys.argv[1:])
12+
13+
# Read the coverage information into an object.
14+
with open(args.file, "rb") as f:
15+
coverage = json.load(f)
16+
17+
# For each file:
18+
# - Determine which lines were not covered;
19+
# - Check when the lines were last modified;
20+
# - Print details of new, uncovered, lines.
21+
report = {}
22+
for filename, info in coverage["files"].items():
23+
if not isinstance(filename, str):
24+
raise TypeError("filename must be a string")
25+
26+
missing = info["missing_lines"]
27+
if not missing:
28+
continue
29+
30+
for lineno in missing:
31+
if not isinstance(lineno, int):
32+
raise TypeError("line numbers must be integers")
33+
cmd = [
34+
"git",
35+
"blame",
36+
filename,
37+
"-L",
38+
f"{lineno},{lineno}",
39+
"--no-abbrev",
40+
]
41+
completed = subprocess.run(cmd, capture_output=True)
42+
commit = completed.stdout.decode().split()[0].strip()
43+
44+
if commit in args.commits:
45+
if filename not in report:
46+
report[filename] = []
47+
report[filename].append(str(lineno))
48+
49+
for filename in report:
50+
n = len(report[filename])
51+
print(f'{n} uncovered lines in {filename}: {",".join(report[filename])}')
52+
53+
# Use the exit code to communicate failure to GitHub.
54+
if len(report) != 0:
55+
sys.exit(1)
56+
else:
57+
sys.exit(0)

.github/workflows/coverage.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: coverage
2+
3+
permissions: read-all
4+
5+
on:
6+
pull_request:
7+
branches: [ "main" ]
8+
paths:
9+
- 'codebasin/**'
10+
11+
jobs:
12+
check-coverage:
13+
name: Ensure modified lines are tested
14+
runs-on: ubuntu-latest
15+
strategy:
16+
matrix:
17+
python-version: ["3.12"]
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Set up Python ${{ matrix.python-version }}
23+
uses: actions/setup-python@v4
24+
with:
25+
python-version: ${{ matrix.python-version }}
26+
27+
- name: Install `code-base-investigator`
28+
run: |
29+
python -m pip install -U pip
30+
pip install .
31+
32+
- name: Install `coverage`
33+
run: |
34+
pip install coverage
35+
36+
- name: Run `coverage`
37+
run: |
38+
python -m coverage run -m unittest
39+
40+
- name: Generate coverage.json
41+
run: |
42+
python -m coverage json --include=$(git diff --name-status main codebasin/*.py | grep "^M" | awk '{ print $2 }' | paste -sd,)
43+
44+
- name: Check coverage against latest commits
45+
run: |
46+
FROM=${{ github.event.pull_request.base.sha }}
47+
TO=${{ github.event.pull_request.head.sha }}
48+
COMMITS=$(git rev-list $FROM..$TO)
49+
python .github/workflows/check-coverage.py coverage.json --commits $COMMITS

0 commit comments

Comments
 (0)