diff --git a/services/test_analytics/ta_metrics.py b/services/test_analytics/ta_metrics.py index 002d5778d..d78e51fa7 100644 --- a/services/test_analytics/ta_metrics.py +++ b/services/test_analytics/ta_metrics.py @@ -1,4 +1,4 @@ -from shared.metrics import Summary +from shared.metrics import Counter, Summary write_tests_summary = Summary( "write_tests_summary", @@ -37,3 +37,9 @@ "The time it takes to process flakes", ["impl"], ) + + +new_ta_tasks_repo_summary = Counter( + "new_ta_tasks_repo_summary", + "Number of repos that were processed using 'new' ta tasks, due to being created after 2025-04-25", +) diff --git a/tasks/tests/unit/cassetes/test_upload_task/TestUploadTaskIntegration/test_upload_task_call_test_results_new_repo.yaml b/tasks/tests/unit/cassetes/test_upload_task/TestUploadTaskIntegration/test_upload_task_call_test_results_new_repo.yaml new file mode 100644 index 000000000..2ae9862ff --- /dev/null +++ b/tasks/tests/unit/cassetes/test_upload_task/TestUploadTaskIntegration/test_upload_task_call_test_results_new_repo.yaml @@ -0,0 +1,262 @@ +interactions: +- request: + body: '' + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate, zstd + connection: + - keep-alive + host: + - api.github.com + user-agent: + - Default + method: GET + uri: https://api.github.com/repos/ThiagoCodecov/example-python/contents?ref=abf6d4df662c47e32460020ab14abf9303581429 + response: + body: + string: '{"message":"Bad credentials","documentation_url":"https://docs.github.com/rest","status":"401"}' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, + X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, + X-GitHub-Request-Id, Deprecation, Sunset + Content-Length: + - '95' + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Tue, 22 Apr 2025 20:46:29 GMT + Referrer-Policy: + - origin-when-cross-origin, strict-origin-when-cross-origin + Server: + - github.com + Strict-Transport-Security: + - max-age=31536000; includeSubdomains; preload + Vary: + - Accept-Encoding, Accept, X-Requested-With + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + X-GitHub-Media-Type: + - github.v3 + X-GitHub-Request-Id: + - 6CED:3692BE:371DFE8:6DB056D:68080025 + X-RateLimit-Limit: + - '60' + X-RateLimit-Remaining: + - '59' + X-RateLimit-Reset: + - '1745358389' + X-RateLimit-Resource: + - core + X-RateLimit-Used: + - '1' + X-XSS-Protection: + - '0' + status: + code: 401 + message: Unauthorized +- request: + body: '' + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate, zstd + connection: + - keep-alive + host: + - api.github.com + user-agent: + - Default + method: GET + uri: https://api.github.com/repos/ThiagoCodecov/example-python/commits/abf6d4df662c47e32460020ab14abf9303581429 + response: + body: + string: '{"message":"Bad credentials","documentation_url":"https://docs.github.com/rest","status":"401"}' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, + X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, + X-GitHub-Request-Id, Deprecation, Sunset + Content-Length: + - '95' + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Tue, 22 Apr 2025 20:46:29 GMT + Referrer-Policy: + - origin-when-cross-origin, strict-origin-when-cross-origin + Server: + - github.com + Strict-Transport-Security: + - max-age=31536000; includeSubdomains; preload + Vary: + - Accept-Encoding, Accept, X-Requested-With + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + X-GitHub-Media-Type: + - github.v3 + X-GitHub-Request-Id: + - D17F:29F048:35D3BF4:6B2DD7B:68080025 + X-RateLimit-Limit: + - '60' + X-RateLimit-Remaining: + - '58' + X-RateLimit-Reset: + - '1745358389' + X-RateLimit-Resource: + - core + X-RateLimit-Used: + - '2' + X-XSS-Protection: + - '0' + status: + code: 401 + message: Unauthorized +- request: + body: '' + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate, zstd + connection: + - keep-alive + host: + - api.github.com + user-agent: + - Default + method: GET + uri: https://api.github.com/repos/ThiagoCodecov/example-python/commits/abf6d4df662c47e32460020ab14abf9303581429 + response: + body: + string: '{"message":"Bad credentials","documentation_url":"https://docs.github.com/rest","status":"401"}' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, + X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, + X-GitHub-Request-Id, Deprecation, Sunset + Content-Length: + - '95' + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Tue, 22 Apr 2025 20:46:29 GMT + Referrer-Policy: + - origin-when-cross-origin, strict-origin-when-cross-origin + Server: + - github.com + Strict-Transport-Security: + - max-age=31536000; includeSubdomains; preload + Vary: + - Accept-Encoding, Accept, X-Requested-With + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + X-GitHub-Media-Type: + - github.v3 + X-GitHub-Request-Id: + - D17F:29F048:35D3C1A:6B2DDD3:68080025 + X-RateLimit-Limit: + - '60' + X-RateLimit-Remaining: + - '57' + X-RateLimit-Reset: + - '1745358389' + X-RateLimit-Resource: + - core + X-RateLimit-Used: + - '3' + X-XSS-Protection: + - '0' + status: + code: 401 + message: Unauthorized +- request: + body: '' + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate, zstd + connection: + - keep-alive + host: + - api.github.com + user-agent: + - Default + method: GET + uri: https://api.github.com/repos/ThiagoCodecov/example-python/commits/abf6d4df662c47e32460020ab14abf9303581429 + response: + body: + string: '{"message":"Bad credentials","documentation_url":"https://docs.github.com/rest","status":"401"}' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, + X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, + X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, + X-GitHub-Request-Id, Deprecation, Sunset + Content-Length: + - '95' + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Tue, 22 Apr 2025 20:46:29 GMT + Referrer-Policy: + - origin-when-cross-origin, strict-origin-when-cross-origin + Server: + - github.com + Strict-Transport-Security: + - max-age=31536000; includeSubdomains; preload + Vary: + - Accept-Encoding, Accept, X-Requested-With + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + X-GitHub-Media-Type: + - github.v3 + X-GitHub-Request-Id: + - D17F:29F048:35D3C3F:6B2DE17:68080025 + X-RateLimit-Limit: + - '60' + X-RateLimit-Remaining: + - '56' + X-RateLimit-Reset: + - '1745358389' + X-RateLimit-Resource: + - core + X-RateLimit-Used: + - '4' + X-XSS-Protection: + - '0' + status: + code: 401 + message: Unauthorized +version: 1 diff --git a/tasks/tests/unit/test_upload_task.py b/tasks/tests/unit/test_upload_task.py index 5e6ae8b0f..6f257515c 100644 --- a/tasks/tests/unit/test_upload_task.py +++ b/tasks/tests/unit/test_upload_task.py @@ -438,6 +438,83 @@ def test_upload_task_call_test_results( notify_sig = test_results_finisher_task.signature(kwargs=kwargs) chain.assert_called_with(*[processor_sig, notify_sig]) + @pytest.mark.django_db(databases={"default"}, transaction=True) + def test_upload_task_call_test_results_new_repo( + self, + mocker, + mock_configuration, + dbsession, + codecov_vcr, + mock_storage, + mock_redis, + celery_app, + ): + chain = mocker.patch("tasks.upload.chain") + storage_path = "v4/raw/2019-05-22/C3C4715CA57C910D11D5EB899FC86A7E/4c4e4654ac25037ae869caeb3619d485970b6304/a84d445c-9c1e-434f-8275-f18f1f320f81.txt" + redis_queue = [{"url": storage_path, "build_code": "some_random_build"}] + jsonified_redis_queue = [json.dumps(x) for x in redis_queue] + mocker.patch.object(UploadTask, "app", celery_app) + + commit = CommitFactory.create( + message="", + commitid="abf6d4df662c47e32460020ab14abf9303581429", + repository__owner__oauth_token="GHTZB+Mi+kbl/ubudnSKTJYb/fgN4hRJVJYSIErtidEsCLDJBb8DZzkbXqLujHAnv28aKShXddE/OffwRuwKug==", + repository__owner__username="ThiagoCodecov", + repository__owner__service="github", + repository__yaml={"codecov": {"max_report_age": "1y ago"}}, + repository__name="example-python", + pullid=1, + # Setting the time to _before_ patch centric default YAMLs start date of 2024-04-30 + repository__owner__createstamp=datetime(2023, 1, 1, tzinfo=timezone.utc), + ) + dbsession.add(commit) + dbsession.flush() + dbsession.refresh(commit) + + mock_redis.lists[f"uploads/{commit.repoid}/{commit.commitid}/test_results"] = ( + jsonified_redis_queue + ) + + UploadTask().run_impl( + dbsession, + commit.repoid, + commit.commitid, + report_type="test_results", + ) + commit_report = commit.commit_report(report_type=ReportType.TEST_RESULTS) + assert commit_report + uploads = commit_report.uploads + assert len(uploads) == 1 + upload = dbsession.query(Upload).filter_by(report_id=commit_report.id).first() + processor_sig = test_results_processor_task.s( + False, + repoid=commit.repoid, + commitid=commit.commitid, + commit_yaml={"codecov": {"max_report_age": "1y ago"}}, + arguments_list=[ + { + "url": storage_path, + "flags": [], + "build_code": "some_random_build", + "upload_id": upload.id, + "upload_pk": upload.id, + } + ], + report_code=None, + impl_type="old", + ) + kwargs = dict( + repoid=commit.repoid, + commitid=commit.commitid, + commit_yaml={"codecov": {"max_report_age": "1y ago"}}, + checkpoints_TestResultsFlow=None, + impl_type="old", + ) + + kwargs[_kwargs_key(TestResultsFlow)] = mocker.ANY + notify_sig = test_results_finisher_task.signature(kwargs=kwargs) + chain.assert_called_with(*[processor_sig, notify_sig]) + @pytest.mark.django_db(databases={"default"}, transaction=True) def test_upload_task_call_new_ta_tasks( self, diff --git a/tasks/upload.py b/tasks/upload.py index e76642130..cc23374ba 100644 --- a/tasks/upload.py +++ b/tasks/upload.py @@ -3,6 +3,7 @@ import time import uuid from copy import deepcopy +from datetime import datetime from typing import Optional, TypedDict import orjson @@ -46,6 +47,7 @@ gitlab_webhook_update, possibly_update_commit_from_provider_info, ) +from services.test_analytics.ta_metrics import new_ta_tasks_repo_summary from services.test_results import TestResultsReportService from tasks.base import BaseCodecovTask from tasks.bundle_analysis_notify import bundle_analysis_notify_task @@ -775,6 +777,22 @@ def _schedule_ta_processing_task( new_ta_tasks = NEW_TA_TASKS.check_value(commit.repoid, default="old") if not settings.TA_TIMESERIES_ENABLED: new_ta_tasks = "old" + else: + db_session: Session = commit.get_db_session() # type: ignore + earliest_commit = ( + db_session.query(Commit) + .filter( + Commit.repoid == commit.repoid, + Commit.timestamp > datetime(2025, 4, 25, tzinfo=timezone.utc), + ) + .order_by(Commit.timestamp) + .limit(1) + .first() + ) + + if earliest_commit: + new_ta_tasks = "new" + new_ta_tasks_repo_summary.inc() task_group = [ test_results_processor_task.s(