Skip to content

Commit

Permalink
coverage over time return component ID and name (#546)
Browse files Browse the repository at this point in the history
* coverage over time return component ID and name

* fix tests{

* add typings

* add typings

* add typings

* add more typings
  • Loading branch information
JerrySentry committed May 9, 2024
1 parent 3c5f37a commit dbe28ab
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 70 deletions.
125 changes: 121 additions & 4 deletions graphql_api/tests/test_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,7 @@ def setUp(self):
"individual_components": [
{
"component_id": "python",
"name": "pythonName",
"paths": [".*/*.py"],
},
{
Expand Down Expand Up @@ -938,7 +939,7 @@ def test_component_measurements_with_measurements(self):
},
{
"__typename": "ComponentMeasurements",
"name": "python",
"name": "pythonName",
"percentCovered": 80.0,
"percentChange": 5.0,
"measurements": [
Expand Down Expand Up @@ -997,7 +998,7 @@ def test_component_measurements_no_measurements(self):
},
{
"__typename": "ComponentMeasurements",
"name": "python",
"name": "pythonName",
"percentCovered": None,
"percentChange": None,
"measurements": [],
Expand Down Expand Up @@ -1098,7 +1099,7 @@ def test_component_measurements_with_filter(self):
"components": [
{
"__typename": "ComponentMeasurements",
"name": "python",
"name": "pythonName",
"percentCovered": 80.0,
"percentChange": 5.0,
"measurements": [
Expand Down Expand Up @@ -1245,7 +1246,7 @@ def test_component_measurements_with_branch(self):
},
{
"__typename": "ComponentMeasurements",
"name": "python",
"name": "pythonName",
"percentCovered": None,
"percentChange": None,
"measurements": [],
Expand All @@ -1255,3 +1256,119 @@ def test_component_measurements_with_branch(self):
}
}
}

def test_component_measurements_id_fallback(self):
MeasurementFactory(
name="component_coverage",
owner_id=self.org.pk,
repo_id=self.repo.pk,
branch="main",
measurable_id="python",
commit_sha=self.commit.pk,
timestamp="2022-06-21T00:00:00",
value=75.0,
)
MeasurementFactory(
name="component_coverage",
owner_id=self.org.pk,
repo_id=self.repo.pk,
branch="main",
measurable_id="python",
commit_sha=self.commit.pk,
timestamp="2022-06-22T00:00:00",
value=75.0,
)
MeasurementFactory(
name="component_coverage",
owner_id=self.org.pk,
repo_id=self.repo.pk,
branch="main",
measurable_id="python",
commit_sha=self.commit.pk,
timestamp="2022-06-22T01:00:00",
value=85.0,
)
MeasurementFactory(
name="component_coverage",
owner_id=self.org.pk,
repo_id=self.repo.pk,
branch="dev",
measurable_id="golang",
commit_sha=self.commit.pk,
timestamp="2022-06-21T00:00:00",
value=85.0,
)
MeasurementFactory(
name="component_coverage",
owner_id=self.org.pk,
repo_id=self.repo.pk,
branch="dev",
measurable_id="golang",
commit_sha=self.commit.pk,
timestamp="2022-06-22T00:00:00",
value=95.0,
)
MeasurementFactory(
name="component_coverage",
owner_id=self.org.pk,
repo_id=self.repo.pk,
branch="dev",
measurable_id="golang",
commit_sha=self.commit.pk,
timestamp="2022-06-22T01:00:00",
value=85.0,
)

query = """
query ComponentMeasurements(
$name: String!
$repo: String!
$interval: MeasurementInterval!
$after: DateTime!
$before: DateTime!
$branch: String
$filters: ComponentMeasurementsSetFilters
$orderingDirection: OrderingDirection
) {
owner(username: $name) {
repository: repositoryDeprecated(name: $repo) {
components(filters: $filters, orderingDirection: $orderingDirection, after: $after, before: $before, branch: $branch, interval: $interval) {
__typename
... on ComponentMeasurements {
name
componentId
}
}
}
}
}
"""

variables = {
"name": self.org.username,
"repo": self.repo.name,
"interval": "INTERVAL_1_DAY",
"after": timezone.datetime(2022, 6, 20),
"before": timezone.datetime(2022, 6, 23),
"branch": "dev",
}
data = self.gql_request(query, variables=variables)

assert data == {
"owner": {
"repository": {
"components": [
{
"__typename": "ComponentMeasurements",
"name": "golang",
"componentId": "golang",
},
{
"__typename": "ComponentMeasurements",
"name": "pythonName",
"componentId": "python",
},
]
}
}
}
45 changes: 29 additions & 16 deletions graphql_api/types/comparison/comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import List, Optional

from ariadne import ObjectType, UnionType, convert_kwargs_to_snake_case
from graphql.type.definition import GraphQLResolveInfo

import services.components as components_service
from codecov.db import sync_to_async
Expand Down Expand Up @@ -30,15 +31,15 @@


@comparison_bindable.field("state")
def resolve_state(comparison: ComparisonReport, info) -> str:
def resolve_state(comparison: ComparisonReport, info: GraphQLResolveInfo) -> str:
return comparison.commit_comparison.state


@comparison_bindable.field("impactedFilesDeprecated")
@convert_kwargs_to_snake_case
@sync_to_async
def resolve_impacted_files_deprecated(
comparison_report: ComparisonReport, info, filters=None
comparison_report: ComparisonReport, info: GraphQLResolveInfo, filters=None
) -> List[ImpactedFile]:
command: CompareCommands = info.context["executor"].get_command("compare")
comparison: Comparison = info.context.get("comparison", None)
Expand All @@ -50,7 +51,7 @@ def resolve_impacted_files_deprecated(
@convert_kwargs_to_snake_case
@sync_to_async
def resolve_impacted_files(
comparison_report: ComparisonReport, info, filters=None
comparison_report: ComparisonReport, info: GraphQLResolveInfo, filters=None
) -> List[ImpactedFile]:
command: CompareCommands = info.context["executor"].get_command("compare")
comparison: Comparison = info.context.get("comparison", None)
Expand All @@ -67,32 +68,40 @@ def resolve_impacted_files(

@comparison_bindable.field("impactedFilesCount")
@sync_to_async
def resolve_impacted_files_count(comparison: ComparisonReport, info):
def resolve_impacted_files_count(
comparison: ComparisonReport, info: GraphQLResolveInfo
):
return len(comparison.impacted_files)


@comparison_bindable.field("directChangedFilesCount")
@sync_to_async
def resolve_direct_changed_files_count(comparison: ComparisonReport, info):
def resolve_direct_changed_files_count(
comparison: ComparisonReport, info: GraphQLResolveInfo
):
return len(comparison.impacted_files_with_direct_changes)


@comparison_bindable.field("indirectChangedFilesCount")
@sync_to_async
def resolve_indirect_changed_files_count(comparison: ComparisonReport, info):
def resolve_indirect_changed_files_count(
comparison: ComparisonReport, info: GraphQLResolveInfo
):
return len(comparison.impacted_files_with_unintended_changes)


@comparison_bindable.field("impactedFile")
@sync_to_async
def resolve_impacted_file(comparison: ComparisonReport, info, path) -> ImpactedFile:
def resolve_impacted_file(
comparison: ComparisonReport, info: GraphQLResolveInfo, path
) -> ImpactedFile:
return comparison.impacted_file(path)


# TODO: rename `changeCoverage`
@comparison_bindable.field("changeCoverage")
async def resolve_change_coverage(
comparison: ComparisonReport, info
comparison: ComparisonReport, info: GraphQLResolveInfo
) -> Optional[float]:
repository_id = comparison.commit_comparison.compare_commit.repository_id
loader = CommitLoader.loader(info, repository_id)
Expand Down Expand Up @@ -124,7 +133,7 @@ async def resolve_change_coverage(

@comparison_bindable.field("baseTotals")
async def resolve_base_totals(
comparison: ComparisonReport, info
comparison: ComparisonReport, info: GraphQLResolveInfo
) -> Optional[ReportLevelTotals]:
repository_id = comparison.commit_comparison.base_commit.repository_id
loader = CommitLoader.loader(info, repository_id)
Expand All @@ -141,7 +150,7 @@ async def resolve_base_totals(

@comparison_bindable.field("headTotals")
async def resolve_head_totals(
comparison: ComparisonReport, info
comparison: ComparisonReport, info: GraphQLResolveInfo
) -> Optional[ReportLevelTotals]:
repository_id = comparison.commit_comparison.compare_commit.repository_id
loader = CommitLoader.loader(info, repository_id)
Expand All @@ -159,7 +168,9 @@ async def resolve_head_totals(


@comparison_bindable.field("patchTotals")
def resolve_patch_totals(comparison: ComparisonReport, info) -> dict:
def resolve_patch_totals(
comparison: ComparisonReport, info: GraphQLResolveInfo
) -> dict:
totals = comparison.commit_comparison.patch_totals
if not totals:
return None
Expand All @@ -176,7 +187,7 @@ def resolve_patch_totals(comparison: ComparisonReport, info) -> dict:
@comparison_bindable.field("flagComparisons")
@sync_to_async
def resolve_flag_comparisons(
comparison: ComparisonReport, info, filters=None
comparison: ComparisonReport, info: GraphQLResolveInfo, filters=None
) -> List[FlagComparison]:
all_flags = get_flag_comparisons(comparison.commit_comparison)

Expand All @@ -194,7 +205,7 @@ def resolve_flag_comparisons(
@comparison_bindable.field("componentComparisons")
@sync_to_async
def resolve_component_comparisons(
comparison_report: ComparisonReport, info, filters=None
comparison_report: ComparisonReport, info: GraphQLResolveInfo, filters=None
) -> List[ComponentComparison]:
current_owner = info.context["request"].current_owner
head_commit = comparison_report.commit_comparison.compare_commit
Expand All @@ -221,14 +232,16 @@ def resolve_component_comparisons(
@comparison_bindable.field("componentComparisonsCount")
@sync_to_async
def resolve_component_comparisons_count(
comparison_report: ComparisonReport, info
comparison_report: ComparisonReport, info: GraphQLResolveInfo
) -> int:
return comparison_report.commit_comparison.component_comparisons.count()


@comparison_bindable.field("flagComparisonsCount")
@sync_to_async
def resolve_flag_comparisons_count(comparison: ComparisonReport, info):
def resolve_flag_comparisons_count(
comparison: ComparisonReport, info: GraphQLResolveInfo
):
"""
Resolver to return if the head and base of a pull request have
different number of reports on the head and base. This implementation
Expand All @@ -240,7 +253,7 @@ def resolve_flag_comparisons_count(comparison: ComparisonReport, info):
@comparison_bindable.field("hasDifferentNumberOfHeadAndBaseReports")
@sync_to_async
def resolve_has_different_number_of_head_and_base_reports(
comparison: ComparisonReport, info, **kwargs # type: ignore
comparison: ComparisonReport, info: GraphQLResolveInfo, **kwargs # type: ignore
) -> False:
# TODO: can we remove the need for `info.context["comparison"]` here?
if "comparison" not in info.context:
Expand Down
1 change: 1 addition & 0 deletions graphql_api/types/component/component.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type Component {
}

type ComponentMeasurements {
componentId: String!
name: String!
percentCovered: Float
percentChange: Float
Expand Down

0 comments on commit dbe28ab

Please sign in to comment.