Skip to content

Commit c047c24

Browse files
feat: enable new TA tasks on new repos (#108)
* feat: enable new TA tasks on new repos * update the date * fix tests
1 parent bc9eef9 commit c047c24

File tree

3 files changed

+154
-36
lines changed

3 files changed

+154
-36
lines changed

apps/worker/services/test_analytics/ta_metrics.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from shared.metrics import Summary
1+
from shared.metrics import Counter, Summary
22

33
write_tests_summary = Summary(
44
"write_tests_summary",
@@ -37,3 +37,8 @@
3737
"The time it takes to process flakes",
3838
["impl"],
3939
)
40+
41+
new_ta_tasks_repo_summary = Counter(
42+
"new_ta_tasks_repo_summary",
43+
"Number of repos that were processed using 'new' ta tasks, due to being created after 2025-05-30",
44+
)

apps/worker/tasks/tests/unit/test_upload_task.py

Lines changed: 126 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from tasks.bundle_analysis_processor import bundle_analysis_processor_task
3030
from tasks.test_results_finisher import test_results_finisher_task
3131
from tasks.test_results_processor import test_results_processor_task
32-
from tasks.upload import UploadContext, UploadTask
32+
from tasks.upload import NEW_TA_TASKS_CUTOFF_DATE, UploadContext, UploadTask
3333
from tasks.upload_finisher import upload_finisher_task
3434
from tasks.upload_processor import upload_processor_task
3535

@@ -112,6 +112,45 @@ def mock_redis(mocker):
112112
yield redis_server
113113

114114

115+
@pytest.fixture()
116+
def mock_repo_provider_service(mocker):
117+
mocker.patch("tasks.upload.hasattr", return_value=False)
118+
119+
mock_repo_provider_service = AsyncMock()
120+
mock_repo_provider_service.get_commit.return_value = {
121+
"author": {
122+
"id": "123",
123+
"username": "456",
124+
"email": "789",
125+
"name": "101",
126+
},
127+
"message": "hello world",
128+
"parents": [],
129+
"timestamp": str(datetime.now()),
130+
}
131+
mock_repo_provider_service.get_ancestors_tree.return_value = {"parents": []}
132+
mock_repo_provider_service.get_pull_request.return_value = {
133+
"head": {"branch": "main"},
134+
"base": {},
135+
}
136+
mock_repo_provider_service.list_top_level_files.return_value = [
137+
{"name": "codecov.yml", "path": "codecov.yml"}
138+
]
139+
mock_repo_provider_service.get_source.return_value = {
140+
"content": """
141+
codecov:
142+
max_report_age: 1y ago
143+
"""
144+
}
145+
146+
mocker.patch(
147+
"tasks.base.get_repo_provider_service",
148+
return_value=mock_repo_provider_service,
149+
)
150+
151+
return mock_repo_provider_service
152+
153+
115154
@pytest.fixture(scope="function", autouse=True)
116155
def clear_log_context(mocker):
117156
set_log_context(LogContext())
@@ -442,6 +481,7 @@ def test_upload_task_call_new_ta_tasks(
442481
mock_storage,
443482
mock_redis,
444483
celery_app,
484+
mock_repo_provider_service,
445485
):
446486
chain = mocker.patch("tasks.upload.chain")
447487
_ = mocker.patch("tasks.upload.NEW_TA_TASKS.check_value", return_value="both")
@@ -450,38 +490,6 @@ def test_upload_task_call_new_ta_tasks(
450490
jsonified_redis_queue = [json.dumps(x) for x in redis_queue]
451491
mocker.patch.object(UploadTask, "app", celery_app)
452492

453-
mock_repo_provider_service = AsyncMock()
454-
mock_repo_provider_service.get_commit.return_value = {
455-
"author": {
456-
"id": "123",
457-
"username": "456",
458-
"email": "789",
459-
"name": "101",
460-
},
461-
"message": "hello world",
462-
"parents": [],
463-
"timestamp": str(datetime.now()),
464-
}
465-
mock_repo_provider_service.get_ancestors_tree.return_value = {"parents": []}
466-
mock_repo_provider_service.get_pull_request.return_value = {
467-
"head": {"branch": "main"},
468-
"base": {},
469-
}
470-
mock_repo_provider_service.list_top_level_files.return_value = [
471-
{"name": "codecov.yml", "path": "codecov.yml"}
472-
]
473-
mock_repo_provider_service.get_source.return_value = {
474-
"content": """
475-
codecov:
476-
max_report_age: 1y ago
477-
"""
478-
}
479-
480-
mocker.patch(
481-
"tasks.base.get_repo_provider_service",
482-
return_value=mock_repo_provider_service,
483-
)
484-
mocker.patch("tasks.upload.hasattr", return_value=False)
485493
commit = CommitFactory.create(
486494
message="",
487495
commitid="abf6d4df662c47e32460020ab14abf9303581429",
@@ -542,6 +550,91 @@ def test_upload_task_call_new_ta_tasks(
542550
notify_sig = test_results_finisher_task.signature(kwargs=kwargs)
543551
chain.assert_has_calls([call(processor_sig, notify_sig)], any_order=True)
544552

553+
@pytest.mark.django_db(databases={"default"}, transaction=True)
554+
def test_upload_task_call_test_results_new_repo(
555+
self,
556+
mocker,
557+
mock_configuration,
558+
dbsession,
559+
codecov_vcr,
560+
mock_storage,
561+
mock_redis,
562+
celery_app,
563+
mock_repo_provider_service,
564+
):
565+
chain = mocker.patch("tasks.upload.chain")
566+
storage_path = "v4/raw/2019-05-22/C3C4715CA57C910D11D5EB899FC86A7E/4c4e4654ac25037ae869caeb3619d485970b6304/a84d445c-9c1e-434f-8275-f18f1f320f81.txt"
567+
redis_queue = [{"url": storage_path, "build_code": "some_random_build"}]
568+
jsonified_redis_queue = [json.dumps(x) for x in redis_queue]
569+
570+
commit = CommitFactory.create(
571+
message="",
572+
commitid="abf6d4df662c47e32460020ab14abf9303581429",
573+
repository__owner__oauth_token="GHTZB+Mi+kbl/ubudnSKTJYb/fgN4hRJVJYSIErtidEsCLDJBb8DZzkbXqLujHAnv28aKShXddE/OffwRuwKug==",
574+
repository__owner__username="ThiagoCodecov",
575+
repository__owner__service="github",
576+
repository__yaml={"codecov": {"max_report_age": "1y ago"}},
577+
repository__name="example-python",
578+
pullid=1,
579+
# Setting the time to _before_ patch centric default YAMLs start date of 2024-04-30
580+
repository__owner__createstamp=datetime(2023, 1, 1, tzinfo=UTC),
581+
)
582+
dbsession.add(commit)
583+
dbsession.flush()
584+
dbsession.refresh(commit)
585+
commit.timestamp = NEW_TA_TASKS_CUTOFF_DATE.replace(
586+
day=21
587+
) # One day after cutoff
588+
dbsession.flush()
589+
590+
mock_redis.lists[f"uploads/{commit.repoid}/{commit.commitid}/test_results"] = (
591+
jsonified_redis_queue
592+
)
593+
594+
mock_repo_provider_service.get_commit.return_value["timestamp"] = (
595+
NEW_TA_TASKS_CUTOFF_DATE.replace(day=21)
596+
) # One day after cutoff
597+
598+
UploadTask().run_impl(
599+
dbsession,
600+
commit.repoid,
601+
commit.commitid,
602+
report_type="test_results",
603+
)
604+
605+
commit_report = commit.commit_report(report_type=ReportType.TEST_RESULTS)
606+
assert commit_report
607+
uploads = commit_report.uploads
608+
assert len(uploads) == 1
609+
upload = dbsession.query(Upload).filter_by(report_id=commit_report.id).first()
610+
processor_sig = test_results_processor_task.s(
611+
False,
612+
repoid=commit.repoid,
613+
commitid=commit.commitid,
614+
commit_yaml={"codecov": {"max_report_age": "1y ago"}},
615+
arguments_list=[
616+
{
617+
"url": storage_path,
618+
"flags": [],
619+
"build_code": "some_random_build",
620+
"upload_id": upload.id,
621+
"upload_pk": upload.id,
622+
}
623+
],
624+
impl_type="new",
625+
)
626+
kwargs = {
627+
"repoid": commit.repoid,
628+
"commitid": commit.commitid,
629+
"commit_yaml": {"codecov": {"max_report_age": "1y ago"}},
630+
"checkpoints_TestResultsFlow": None,
631+
"impl_type": "new",
632+
}
633+
634+
kwargs[_kwargs_key(TestResultsFlow)] = mocker.ANY
635+
notify_sig = test_results_finisher_task.signature(kwargs=kwargs)
636+
chain.assert_called_with(*[processor_sig, notify_sig])
637+
545638
def test_upload_task_call_no_jobs(
546639
self,
547640
mocker,

apps/worker/tasks/upload.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import time
44
import uuid
55
from copy import deepcopy
6+
from datetime import UTC, datetime
67
from typing import TypedDict
78

89
import orjson
910
import sentry_sdk
1011
from asgiref.sync import async_to_sync
1112
from celery import chain, chord
1213
from django.conf import settings
13-
from django.utils import timezone
1414
from redis import Redis
1515
from redis.exceptions import LockError
1616
from sqlalchemy.orm import Session
@@ -36,6 +36,7 @@
3636
gitlab_webhook_update,
3737
possibly_update_commit_from_provider_info,
3838
)
39+
from services.test_analytics.ta_metrics import new_ta_tasks_repo_summary
3940
from services.test_results import TestResultsReportService
4041
from shared.celery_config import upload_task_name
4142
from shared.config import get_config
@@ -56,6 +57,9 @@
5657

5758
log = logging.getLogger(__name__)
5859

60+
# Date after which commits are considered for new TA tasks implementation
61+
NEW_TA_TASKS_CUTOFF_DATE = datetime(2025, 6, 20, tzinfo=UTC)
62+
5963
CHUNK_SIZE = 3
6064

6165
UPLOADS_PER_TASK_SCHEDULE = Histogram(
@@ -539,7 +543,7 @@ def _possibly_create_uploads_to_insert(
539543

540544
# List to track possible measurements to insert later
541545
measurements_list: list[UserMeasurement] = []
542-
created_at = timezone.now()
546+
created_at = datetime.now(UTC)
543547

544548
# List + helper mapping to track possible upload + flags to insert later
545549
upload_flag_map: dict[Upload, list | str | None] = {}
@@ -750,6 +754,22 @@ def _schedule_ta_processing_task(
750754
new_ta_tasks = NEW_TA_TASKS.check_value(commit.repoid, default="old")
751755
if not settings.TA_TIMESERIES_ENABLED:
752756
new_ta_tasks = "old"
757+
else:
758+
db_session: Session = commit.get_db_session() # type: ignore
759+
earliest_commit = (
760+
db_session.query(Commit)
761+
.filter(
762+
Commit.repoid == commit.repoid,
763+
Commit.timestamp > NEW_TA_TASKS_CUTOFF_DATE,
764+
)
765+
.order_by(Commit.timestamp)
766+
.limit(1)
767+
.first()
768+
)
769+
770+
if earliest_commit:
771+
new_ta_tasks = "new"
772+
new_ta_tasks_repo_summary.inc()
753773

754774
task_group = [
755775
test_results_processor_task.s(

0 commit comments

Comments
 (0)