Skip to content

Commit

Permalink
chore: replace coverage job (#2404)
Browse files Browse the repository at this point in the history
* chore: replace coverage job

* feat: check coverage is above threshold
  • Loading branch information
joaoandre-avaiga authored Jan 23, 2025
1 parent d7d82e1 commit 4a6315f
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 6 deletions.
8 changes: 8 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[run]
omit =
tests/*

[report]
exclude_lines =
# Ignore pragma: no cover comments
pragma: no cover
24 changes: 18 additions & 6 deletions .github/workflows/overall-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ jobs:
coverage:
timeout-minutes: 50
runs-on: ubuntu-latest

if: github.event_name == 'pull_request' && github.event.pull_request.base.repo.full_name == github.event.pull_request.head.repo.full_name
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch full history to enable proper diff

- uses: actions/setup-python@v5
with:
Expand All @@ -38,13 +41,22 @@ jobs:

- name: Pytest
run: |
pipenv run pytest --cov=taipy --cov-report="xml:overall-coverage.xml" tests
python -m pip install xmltodict
pipenv run pytest --cov=taipy --cov-report=xml:${{ github.workspace }}/coverage.xml --cov-config=.coveragerc
- name: Coverage
uses: orgoro/[email protected]
with:
coverageFile: overall-coverage.xml
token: ${{ secrets.GITHUB_TOKEN }}
- name: Fetch base branch
run: |
git fetch origin ${{ github.event.pull_request.base.ref }}:refs/remotes/origin/${{ github.event.pull_request.base.ref }}
- name: Check total project coverage
run: |
python tools/coverage_check.py check-total --coverage-file ${{ github.workspace }}/coverage.xml --threshold 80
- name: Check pull request coverage
run: |
python tools/coverage_check.py check-changed --coverage-file ${{ github.workspace }}/coverage.xml --threshold 80 --base-branch ${{ github.event.pull_request.base.ref }}
overall-tests:
needs: [partial-tests]
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ exclude = [
"build",
"dist",
"releases",
"tools",
".venv",
".mypy_cache",
".pytest_cache",
Expand Down
101 changes: 101 additions & 0 deletions tools/coverage_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Copyright 2021-2025 Avaiga Private Limited
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.

import argparse
import xmltodict
import sys
import subprocess


def check_total_coverage(coverage_file, threshold=80):
"""Check the total project coverage."""
with open(coverage_file) as f:
data = xmltodict.parse(f.read())
total_coverage = float(data['coverage']['@line-rate']) * 100
print(f"Total Coverage: {total_coverage:.2f}%")
if total_coverage < threshold:
print(f"Total project coverage is below {threshold}%: {total_coverage:.2f}%")
sys.exit(1)


def check_changed_files_coverage(coverage_file, changed_files, threshold=80):
"""Check the coverage of changed files."""
with open(coverage_file) as f:
data = xmltodict.parse(f.read())

# Handle multiple packages in the coverage report
packages = data["coverage"]["packages"]["package"]
if not isinstance(packages, list):
packages = [packages]

# Extract coverage data for all files
files = {}
for package in packages:
classes = package["classes"]["class"]
if not isinstance(classes, list):
classes = [classes]
for cls in classes:
files[cls["@filename"]] = float(cls["@line-rate"]) * 100
qty = 0
sum_coverage = 0
for file in changed_files:
if file in files:
coverage = files[file]
print(f"Coverage for {file}: {coverage:.2f}%")
sum_coverage += coverage
qty += 1
else:
print(f"No coverage data found for {file}")

if sum_coverage/qty < threshold:
print(f"Coverage for changed files is below {threshold}%: {sum_coverage/qty:.2f}%")
sys.exit(1)
print(f"Coverage for changed files: {sum_coverage/qty:.2f}%")


def get_changed_files(base_branch):
"""Get the list of changed Python files in the pull request."""
try:
result = subprocess.run(
['git', 'diff', '--name-only', f"origin/{base_branch}", '--', '*.py'],
capture_output=True,
text=True,
check=True,
)
changed_files = [
file.replace("taipy/", "") for file in result.stdout.strip().splitlines() if not file.startswith(('tests/', 'tools/'))
]
return changed_files
except subprocess.CalledProcessError as e:
print(f"Error fetching changed files: {e}")
sys.exit(1)


if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Coverage check script.")
parser.add_argument('command', choices=['check-total', 'check-changed'], help="Command to execute")
parser.add_argument('--coverage-file', default='coverage.xml', help="Path to the coverage XML file")
parser.add_argument('--threshold', type=float, default=80, help="Coverage threshold percentage")
parser.add_argument('--base-branch', help="Base branch for comparing changed files")

args = parser.parse_args()

if args.command == 'check-total':
check_total_coverage(args.coverage_file, args.threshold)
elif args.command == 'check-changed':
if not args.base_branch:
print("Error: --base-branch is required for check-changed")
sys.exit(1)
changed_files = get_changed_files(args.base_branch)
if not changed_files:
print("No relevant Python files changed.")
sys.exit(0)
check_changed_files_coverage(args.coverage_file, changed_files, args.threshold)

0 comments on commit 4a6315f

Please sign in to comment.