Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ Note: Either `GITHUB_PR_NUMBER` or `GITHUB_REF` is required. `GITHUB_PR_NUMBER`
- `MINIMUM_GREEN`: The minimum coverage percentage for green status. Default is 100.
- `MINIMUM_ORANGE`: The minimum coverage percentage for orange status. Default is 70.
- `BRANCH_COVERAGE`: Show branch coverage in the report. Default is False.
- `ANNOTATE_MISSING_LINES`: Whether to annotate missing lines in the coverage report. Default is False.
- `ANNOTATION_TYPE`: The type of annotation to use for missing lines. 'notice' or 'warning' or 'error'. Default is 'warning'.
- `MAX_FILES_IN_COMMENT`: The maximum number of files to include in the coverage report comment. Default is 25.
- `SKIP_COVERED_FILES_IN_REPORT`: Skip the files with coverage 100% from the report. Default is True.
- `COMPLETE_PROJECT_REPORT`: Whether to include the complete project coverage report in the comment. Default is False.
Expand Down
16 changes: 0 additions & 16 deletions codecov/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ def str_to_bool(value: str) -> bool:
return value.lower() in ('1', 'true', 'yes')


class AnnotationType(Enum):
NOTICE = 'notice'
WARNING = 'warning'
ERROR = 'error'


class TestFramework(Enum):
PYTEST = 'pytest'
JEST = 'jest'
Expand All @@ -53,8 +47,6 @@ class Config:
TEST_FRAMEWORK: TestFramework = TestFramework.PYTEST
# TODO: Remove branch coverage and just use the report
BRANCH_COVERAGE: bool = False
ANNOTATE_MISSING_LINES: bool = False
ANNOTATION_TYPE: AnnotationType = AnnotationType.WARNING
MAX_FILES_IN_COMMENT: int = 25
SKIP_COVERED_FILES_IN_REPORT: bool = True
COMPLETE_PROJECT_REPORT: bool = False
Expand All @@ -74,10 +66,6 @@ def clean_minimum_green(cls, value: str) -> decimal.Decimal:
def clean_minimum_orange(cls, value: str) -> decimal.Decimal:
return decimal.Decimal(value)

@classmethod
def clean_annotate_missing_lines(cls, value: str) -> bool:
return str_to_bool(value)

@classmethod
def clean_branch_coverage(cls, value: str) -> bool:
return str_to_bool(value)
Expand All @@ -94,10 +82,6 @@ def clean_skip_covered_files_in_report(cls, value: str) -> bool:
def clean_debug(cls, value: str) -> bool:
return str_to_bool(value)

@classmethod
def clean_annotation_type(cls, value: str) -> AnnotationType:
return AnnotationType(value)

@classmethod
def clean_github_pr_number(cls, value: str) -> int:
return int(value)
Expand Down
22 changes: 4 additions & 18 deletions codecov/diff_grouper.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from codecov.coverage.jest import JestCoverage
from codecov.coverage.pytest import PytestCoverage

MAX_ANNOTATION_GAP = 3
MAX_GROUP_GAP = 3


def _flatten_branches(branches: list[list[int]] | None) -> list[int]:
Expand Down Expand Up @@ -45,7 +45,7 @@ def get_missing_groups(
values=coverage_file.missing_lines,
separators=separators,
joiners=joiners,
max_gap=MAX_ANNOTATION_GAP,
max_gap=MAX_GROUP_GAP,
):
yield groups.Group(
file=path,
Expand All @@ -70,7 +70,7 @@ def get_diff_missing_groups(
values=diff_file.missing_statements,
separators=separators,
joiners=joiners,
max_gap=MAX_ANNOTATION_GAP,
max_gap=MAX_GROUP_GAP,
):
yield groups.Group(
file=path,
Expand All @@ -93,21 +93,7 @@ def fill_branch_missing_groups(coverage: 'PytestCoverage') -> 'PytestCoverage':
values=_flatten_branches(branches=file_coverage.missing_branches),
separators=separators,
joiners=joiners,
max_gap=MAX_ANNOTATION_GAP,
max_gap=MAX_GROUP_GAP,
)
]
return coverage


def get_diff_branch_missing_groups(
coverage: 'PytestCoverage',
diff_coverage: 'DiffCoverage',
) -> Iterable[groups.Group]:
for path, _ in diff_coverage.files.items():
coverage_file = coverage.files[path]
for start, end in coverage_file.missing_branches or []:
yield groups.Group(
file=path,
line_start=start,
line_end=end,
)
59 changes: 0 additions & 59 deletions codecov/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import functools
import itertools
import pathlib
from collections.abc import Iterable


@dataclasses.dataclass(frozen=True)
Expand All @@ -12,64 +11,6 @@ class Group:
line_end: int


@dataclasses.dataclass
class Annotation:
file: pathlib.Path
line_start: int
line_end: int
title: str
message_type: str
message: str

def __str__(self) -> str:
return f'{self.message_type.upper()} {self.message} in {self.file}:{self.line_start}-{self.line_end}'

def __repr__(self) -> str:
return f'{self.message_type.upper()} {self.message} in {self.file}:{self.line_start}-{self.line_end}'

def to_dict(self):
return {
'file': str(self.file),
'line_start': self.line_start,
'line_end': self.line_end,
'title': self.title,
'message_type': self.message_type,
'message': self.message,
}


def create_missing_coverage_annotations(
annotation_type: str,
annotations: Iterable[Group],
branch: bool = False,
) -> list[Annotation]:
"""
Create annotations for lines with missing coverage.

annotation_type: The type of annotation to create. Can be either "error" or "warning" or "notice".
annotations: A list of tuples of the form (file, line_start, line_end)
branch: Whether to create branch coverage annotations or not
"""
formatted_annotations: list[Annotation] = []
for group in annotations:
if group.line_start == group.line_end:
message = f'Missing {"branch " if branch else ""}coverage on line {group.line_start}'
else:
message = f'Missing {"branch " if branch else ""}coverage on lines {group.line_start}-{group.line_end}'

formatted_annotations.append(
Annotation(
file=group.file,
line_start=group.line_start,
line_end=group.line_end,
title=f'Missing {"branch " if branch else ""}coverage',
message_type=annotation_type,
message=message,
)
)
return formatted_annotations


def compute_contiguous_groups(
values: list[int],
separators: set[int],
Expand Down
41 changes: 1 addition & 40 deletions codecov/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import os
from typing import cast

from codecov import diff_grouper, groups, template
from codecov import template
from codecov.config import Config
from codecov.coverage.base import BaseCoverageHandler, DiffCoverage
from codecov.coverage.jest import JestCoverage
Expand Down Expand Up @@ -49,7 +48,6 @@ def _init_coverage_module(self):
def run(self):
self._process_coverage()
self._create_comment()
self._generate_annotations()

def _process_coverage(self):
log.info('Processing coverage data')
Expand Down Expand Up @@ -123,40 +121,3 @@ def _create_comment(self) -> None:

self.github.post_comment(contents=comment, marker=self.marker)
log.info('Comment created on PR.')

def _generate_annotations(self):
if not self.config.ANNOTATE_MISSING_LINES:
log.info('Skipping annotations generation.')
return

log.info('Generating annotations for missing lines.')
annotations = diff_grouper.get_diff_missing_groups(coverage=self.coverage, diff_coverage=self.diff_coverage)
formatted_annotations = groups.create_missing_coverage_annotations(
annotation_type=self.config.ANNOTATION_TYPE.value,
annotations=annotations,
)

if self.config.BRANCH_COVERAGE:
branch_annotations = diff_grouper.get_diff_branch_missing_groups(
coverage=cast(PytestCoverage, self.coverage),
diff_coverage=self.diff_coverage,
)
formatted_annotations.extend(
groups.create_missing_coverage_annotations(
annotation_type=self.config.ANNOTATION_TYPE.value,
annotations=branch_annotations,
branch=True,
)
)

if not formatted_annotations:
log.info('No annotations to generate. Exiting.')
return

# Print to console
log.info('Annotations:')
yellow = '\033[93m'
reset = '\033[0m'
print(yellow, end='')
print(*formatted_annotations, sep='\n')
print(reset, end='')
2 changes: 1 addition & 1 deletion codecov/template_files/comment.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<img title="{{ text }}" src="{{ 'Coverage' | generate_badge(message=coverage.info.percent_covered_display ~ '%', color=color) }}">
{%- endif -%}
{%- endblock coverage_evolution_badge -%}

&nbsp;&nbsp;
{#- PR coverage badge -#}
{%- block diff_coverage_badge -%}
{%- set text = (diff_coverage.total_percent_covered | pct) ~ " of the statements added in this PR are covered." -%}
Expand Down
4 changes: 3 additions & 1 deletion run.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import sys

from codecov.exceptions import CoreBaseException
from codecov.log import log
from codecov.main import Main


def main_call(name):
if name == '__main__':
try:
Main().run()
except CoreBaseException:
except CoreBaseException as e:
log.error(f'Error: {str(e)}')
sys.exit(1)


Expand Down
1 change: 0 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,5 +425,4 @@ def gh(gh_client, test_config: Config):
github_mock.user.email = 'baz@foobar.com'
github_mock.user.login = 'foo'
github_mock.post_comment = MagicMock(return_value=None)
github_mock.write_annotations_to_branch = MagicMock(return_value=None)
return github_mock
24 changes: 0 additions & 24 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ def test_config_from_environ_sample():
'GITHUB_REF': 'main',
'MINIMUM_GREEN': '90',
'MINIMUM_ORANGE': '70',
'ANNOTATE_MISSING_LINES': 'True',
'ANNOTATION_TYPE': 'notice',
'MAX_FILES_IN_COMMENT': 25,
'COMPLETE_PROJECT_REPORT': 'True',
'COVERAGE_REPORT_URL': 'https://your_coverage_report_url',
Expand All @@ -66,8 +64,6 @@ def test_config_from_environ_sample():
GITHUB_REF='main',
MINIMUM_GREEN=decimal.Decimal('90'),
MINIMUM_ORANGE=decimal.Decimal('70'),
ANNOTATE_MISSING_LINES=True,
ANNOTATION_TYPE=config.AnnotationType.NOTICE,
MAX_FILES_IN_COMMENT=25,
COMPLETE_PROJECT_REPORT=True,
COVERAGE_REPORT_URL='https://your_coverage_report_url',
Expand All @@ -87,11 +83,6 @@ def test_config_required_pr_or_ref():
)


def test_config_invalid_annotation_type():
with pytest.raises(ValueError):
config.Config.from_environ({'ANNOTATION_TYPE': 'foo'})


@pytest.mark.parametrize(
'input_data, output_data',
[
Expand Down Expand Up @@ -120,11 +111,6 @@ def test_config_clean_minimum_orange():
assert value == decimal.Decimal('70')


def test_config_clean_annotate_missing_lines():
value = config.Config.clean_annotate_missing_lines('True')
assert value is True


def test_config_clean_branch_coverage():
value = config.Config.clean_branch_coverage('False')
assert value is False
Expand All @@ -145,16 +131,6 @@ def test_config_clean_debug():
assert value is False


def test_config_clean_annotation_type():
value = config.Config.clean_annotation_type('warning')
assert value == config.AnnotationType.WARNING


def test_config_clean_annotation_type_invalid():
with pytest.raises(ValueError):
config.Config.clean_annotation_type('foo')


def test_config_clean_github_pr_number():
value = config.Config.clean_github_pr_number('123')
assert value == 123
Expand Down
24 changes: 0 additions & 24 deletions tests/test_diff_grouper.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,30 +58,6 @@ def test_flatten_branches():
assert flattened_branches == [1, 2, 3, 4, 5]


def test_get_branch_missing_groups(coverage_obj, diff_coverage_obj):
result = diff_grouper.get_diff_branch_missing_groups(coverage=coverage_obj, diff_coverage=diff_coverage_obj)

assert list(result) == [
groups.Group(file=pathlib.Path('codebase/code.py'), line_start=5, line_end=6),
groups.Group(file=pathlib.Path('codebase/code.py'), line_start=10, line_end=11),
]


def test_get_branch_missing_groups_more_files(coverage_obj_more_files, diff_coverage_obj_more_files):
result = diff_grouper.get_diff_branch_missing_groups(
coverage=coverage_obj_more_files,
diff_coverage=diff_coverage_obj_more_files,
)

assert list(result) == [
groups.Group(file=pathlib.Path('codebase/code.py'), line_start=5, line_end=6),
groups.Group(file=pathlib.Path('codebase/code.py'), line_start=10, line_end=11),
groups.Group(file=pathlib.Path('codebase/other.py'), line_start=3, line_end=4),
groups.Group(file=pathlib.Path('codebase/other.py'), line_start=5, line_end=6),
groups.Group(file=pathlib.Path('codebase/other.py'), line_start=10, line_end=11),
]


def test_fill_branch_missing_groups(coverage_obj):
result = diff_grouper.fill_branch_missing_groups(coverage=coverage_obj)

Expand Down
Loading
Loading