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

feat: upsert daily test rollup when we process a test instance #699

Merged
merged 4 commits into from
Sep 16, 2024
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
28 changes: 28 additions & 0 deletions database/models/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,3 +350,31 @@ class Flake(CodecovBaseModel, MixinBaseClassNoExternalID):
fail_count = Column(types.Integer)
start_date = Column(types.DateTime)
end_date = Column(types.DateTime, nullable=True)


class DailyTestRollup(CodecovBaseModel, MixinBaseClassNoExternalID):
__tablename__ = "reports_dailytestrollups"

test_id = Column(types.Text, ForeignKey("reports_test.id"))
test = relationship(Test, backref=backref("dailytestrollups"))
date = Column(types.Date)
repoid = Column(types.Integer)
branch = Column(types.Text)

fail_count = Column(types.Integer)
skip_count = Column(types.Integer)
pass_count = Column(types.Integer)
last_duration_seconds = Column(types.Float)
avg_duration_seconds = Column(types.Float)
latest_run = Column(types.DateTime)
commits_where_fail = Column(types.ARRAY(types.Text))

__table_args__ = (
UniqueConstraint(
"repoid",
"date",
"branch",
"test_id",
name="reports_dailytestrollups_repoid_date_branch_test",
),
)
2 changes: 1 addition & 1 deletion requirements.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
https://github.com/codecov/opentelem-python/archive/refs/tags/v0.0.4a1.tar.gz#egg=codecovopentelem
https://github.com/codecov/shared/archive/cdf263f5173c16585030bcab40e639045c69e199.tar.gz#egg=shared
https://github.com/codecov/shared/archive/5cc5f48e7d847d3d47ff875a682192465161155f.tar.gz#egg=shared
https://github.com/codecov/test-results-parser/archive/1507de2241601d678e514c08b38426e48bb6d47d.tar.gz#egg=test-results-parser
https://github.com/codecov/timestring/archive/d37ceacc5954dff3b5bd2f887936a98a668dda42.tar.gz#egg=timestring
asgiref>=3.7.2
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile requirements.in
# pip-compile
#
amqp==5.2.0
# via kombu
Expand Down Expand Up @@ -357,7 +357,7 @@ sentry-sdk[celery]==2.13.0
# via
# -r requirements.in
# shared
shared @ https://github.com/codecov/shared/archive/cdf263f5173c16585030bcab40e639045c69e199.tar.gz
shared @ https://github.com/codecov/shared/archive/5cc5f48e7d847d3d47ff875a682192465161155f.tar.gz
# via -r requirements.in
six==1.16.0
# via
Expand Down
98 changes: 97 additions & 1 deletion tasks/test_results_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import logging
import zlib
from datetime import date, datetime
from io import BytesIO
from sys import getsizeof
from typing import List
Expand All @@ -13,6 +14,7 @@
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.orm import Session
from test_results_parser import (
Outcome,
ParserError,
Testrun,
parse_junit_xml,
Expand All @@ -21,7 +23,7 @@
)

from app import celery_app
from database.models import Repository, Test, TestInstance, Upload
from database.models import DailyTestRollup, Repository, Test, TestInstance, Upload
from services.archive import ArchiveService
from services.test_results import generate_flags_hash, generate_test_id
from services.yaml import read_yaml_field
Expand Down Expand Up @@ -110,6 +112,7 @@
with sentry_sdk.metrics.timing(key="test_results.processor.write_to_db"):
test_data = []
test_instance_data = []
daily_totals = dict()
for testrun in parsed_testruns:
# Build up the data for bulk insert
name = testrun.name
Expand Down Expand Up @@ -143,12 +146,105 @@
)
)

def update_daily_total():
daily_totals[test_id]["last_duration_seconds"] = duration_seconds
Copy link
Contributor

@adrian-codecov adrian-codecov Sep 12, 2024

Choose a reason for hiding this comment

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

Nit: change these and (the ones below) to daily_totals.get(test_id, {}).get("last_duration_seconds") to prevent null errors.

Edit: I saw you define these below, so this isn't as applicable, but yet good practice if you want

daily_totals[test_id]["avg_duration_seconds"] = (
daily_totals[test_id]["avg_duration_seconds"]
* (
daily_totals[test_id]["pass_count"]
+ daily_totals[test_id]["fail_count"]
)
+ duration_seconds
) / (
daily_totals[test_id]["pass_count"]
+ daily_totals[test_id]["fail_count"]
+ 1
)

if outcome == str(Outcome.Pass):
daily_totals[test_id]["pass_count"] += 1
elif outcome == str(Outcome.Failure) or outcome == str(
Outcome.Error
):
daily_totals[test_id]["fail_count"] += 1
elif outcome == str(Outcome.Skip):
daily_totals[test_id]["skip_count"] += 1

Check warning on line 171 in tasks/test_results_processor.py

View check run for this annotation

Codecov Notifications / codecov/patch

tasks/test_results_processor.py#L170-L171

Added lines #L170 - L171 were not covered by tests

def create_daily_total():
daily_totals[test_id] = {
"test_id": test_id,
"repoid": repoid,
"last_duration_seconds": duration_seconds,
"avg_duration_seconds": duration_seconds,
"pass_count": 1 if outcome == str(Outcome.Pass) else 0,
"fail_count": 1
if outcome == str(Outcome.Failure)
or outcome == str(Outcome.Error)
else 0,
"skip_count": 1 if outcome == str(Outcome.Skip) else 0,
"branch": branch,
"date": date.today(),
"latest_run": datetime.now(),
"commits_where_fail": [commitid]
if (
outcome == str(Outcome.Failure)
or outcome == str(Outcome.Error)
)
else [],
}

if outcome != str(Outcome.Skip):
if test_id in daily_totals:
update_daily_total()
else:
create_daily_total()

# Save Tests
insert_on_conflict_do_nothing = (
insert(Test.__table__).values(test_data).on_conflict_do_nothing()
)
db_session.execute(insert_on_conflict_do_nothing)
db_session.flush()

# Upsert Daily Test Totals
stmt = insert(DailyTestRollup.__table__).values(list(daily_totals.values()))
stmt = stmt.on_conflict_do_update(
index_elements=[
"repoid",
"branch",
"test_id",
"date",
],
set_={
"last_duration_seconds": stmt.excluded.last_duration_seconds,
"avg_duration_seconds": (
DailyTestRollup.__table__.c.avg_duration_seconds
* (
DailyTestRollup.__table__.c.pass_count
+ DailyTestRollup.__table__.c.fail_count
)
+ stmt.excluded.avg_duration_seconds
)
/ (
DailyTestRollup.__table__.c.pass_count
+ DailyTestRollup.__table__.c.fail_count
+ 1
),
"latest_run": stmt.excluded.latest_run,
"pass_count": DailyTestRollup.__table__.c.pass_count
+ stmt.excluded.pass_count,
"skip_count": DailyTestRollup.__table__.c.skip_count
+ stmt.excluded.skip_count,
"fail_count": DailyTestRollup.__table__.c.fail_count
+ stmt.excluded.fail_count,
"commits_where_fail": DailyTestRollup.__table__.c.commits_where_fail
+ stmt.excluded.commits_where_fail,
},
)

db_session.execute(stmt)
db_session.flush()

# Save TestInstances
insert_test_instances = insert(TestInstance.__table__).values(
test_instance_data
Expand Down
11 changes: 11 additions & 0 deletions tasks/tests/samples/sample_multi_test_part_1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"test_results_files": [
{
"filename": "codecov-demo/multi-test.xml",
"format": "base64+compressed",
"data": "eJy1U01vgkAQvfsrJtvEaCywi18FBdOkNqaHnpp6bDawICkCYZe2/vsOi1aqxvTSTYDM25n3HrM788XXNoUPUcokzzzCTEpAZEEeJlnskUpFxh1Z+J25ElLJKsGP3wFcRwAyvhUeKXY1gsVlmZfSI8gT8SStSoEBIyDfk6IQod7QtRpVSV1LTWpPiOatVw1KxbeFR2xqjww6NWznhQ1daruMmZOpMxk6Bh25FLk2uVSNg9fH1fP66WG9csw0D3hK/B9G7TbgUkCQcimbfO3Cqt9vUZUFChtgFjsCx90fvGWUshav5t7/JqBpyWPMQgVRKmDQjdXMg3H3htEZDAA+NwLzGHhQ8izEJxY9eguM9okfiugXrW5E20Ov754l1AKwlzulPKifFS3h1OCFlMEVs52LRs9b6Y5duNdSGC/rezG39s1qHY11OJv/P64/a0VVmu4gyHEuRHiQgBO00Zia9hWFJtZzgkNktafoG8+FAfk=",
"labels": ""
}
],
"metadata": {}
}
11 changes: 11 additions & 0 deletions tasks/tests/samples/sample_multi_test_part_2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"test_results_files": [
{
"filename": "codecov-demo/multi-test.xml",
"format": "base64+compressed",
"data": "eJzNU8tugzAQvOcrVq4UJUoBm7wKCUSVmirqoaeqOVYWGIJKAGHTNn/fxeRBk7TnWgK0492ZweudL762KXyIUiZ55hFmUgIiC/IwyWKPVCoy7sjC78yVkEpWCX78DuA6AZDxrfBIsasRLC7LvJQeQZ6IJ2lVCgwYAfmeFIUI9Yau1ahK6lpqUntCNG+9alAqvi08YlN7ZNCpYTsvbOhS22XMnEydydAx6MilyLXJpWocvD6untdPD+uVY6Z5wFPiHxm124BLAUHKpWzytQurfr9FVRYoPACz2BE47R7xllFqt3mtA/E/0oqqNN1BkGNTRXiQgDO00Riak5aCZtw3DbAFkseYg7yiVMCgG6uZB+PuDaMzGAB8bpAKcQ9KnoX4xKJHb4HRPvFDEf2g1W1t/2Wv714k1AKwlzunPKhfFC3h3OCVlMEfZjtXjV42yx27cK+lMF7Wt3xu7Q/r9yY1sZ4THCKrPUXfoXQB+w==",
"labels": ""
}
],
"metadata": {}
}
2 changes: 1 addition & 1 deletion tasks/tests/samples/sample_test.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"test_results_files": [{"filename": "codecov-demo/temp.junit.xml", "format": "base64+compressed", "data": "eJy1VMluwjAQvfMVI1dCoBbHZiklJEFVS4V66Kkqx8okBqw6i2KHwt/XWSChnCrRXDLjefNm8Uuc2T6UsOOpEnHkIooJAh75cSCijYsyve49oJnnaK60yoR5NWyIWMhdlBzyE5OWpnGqXGQY1kzILOXGoQjUl0gSHhSBItdFQ2OJPJdgMuqXjtIsTFzUJ/1Bj9IeuX+n1KZjmwwxoZSMDWwbK13W/HhZvC1fn5eLCZaxzyQq2/KZ4uBLplQJY4nAmocJNhA/k0zHKc5xn7WPqimKYxYEjc6Iad66DrHKVjplvv4f9jCTWiTy0GQnV2MPxE4E/Lxzz6muGMzFKbbJaZXiqQajIHBdIHjUvqFkCrcA31tugEUA2lJP11nkayM3eKobKIsA00D2lAz9CV9NSHujpx16B/3uievI9mceU/sChryAr6ExZKdrtwpw+VQjXeSVPVVjtubn6HoBp8iVlnDGd9VFtFpGFFYuCqsWgfVLFDg52ANiw2Mxpyk3zz94x6qU4DnWUW2VWfwkmrbyfgBbcXMH", "labels": ""}], "metadata": {}}
{"test_results_files": [{"filename": "codecov-demo/temp.junit.xml", "format": "base64+compressed", "data": "eJy1VMluwjAQvfMVI1dCoBbHZiklJEFVS4V66Kkqx8okBqw6i2KHwt/XWSChnCrRXDLjefNm8Uuc2T6UsOOpEnHkIooJAh75cSCijYsyve49oJnnaK60yoR5NWyIWMhdlBzyE5OWpnGqXGQY1kzILOXGoQjUl0gSHhSBItdFQ2OJPJdgMuqXjtIsTFzUJ/1Bj9IeuX+n1KZjmwwxoZSMDWwbK13W/HhZvC1fn5eLCZaxzyQq2/KZ4uBLplQJY4nAmocJNhA/k0zHKc5xn7WPqimKYxYEjc6Iad66DrHKVjplvv4f9jCTWiTy0GQnV2MPxE4E/Lxzz6muGMzFKbbJaZXiqQajIHBdIHjUvqFkCrcA31tugEUA2lJP11nkayM3eKobKIsA00D2lAz9CV9NSHujpx16B/3uievI9mceU/sChryAr6ExZKdrtwpw+VQjXeSVPVVjtubn6HoBp8iVlnDGd9VFtFpGFFYuCqsWgfVLFDg52ANiw2Mxpyk3zz94x6qU4DnWUW2VWfwkmrbyfgBbcXMH", "labels": ""}], "metadata": {}}
Loading
Loading