Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

coverage over time return component ID and name #546

Merged
merged 10 commits into from
May 9, 2024
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!
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Real change.

name: String!
percentCovered: Float
percentChange: Float
Expand Down