Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

Commit 7a58082

Browse files
committed
feat: send file_not_found
if the report_type is "test_results" and we don't find any files to upload we want to send a request to the regular test results endpoint with "file_not_found" set to True and not expect a raw_upload_location in the response
1 parent acabe1c commit 7a58082

File tree

3 files changed

+89
-4
lines changed

3 files changed

+89
-4
lines changed

codecov_cli/services/upload/upload_collector.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ def generate_upload_data(
167167
if not report_files:
168168
if report_type == ReportType.TEST_RESULTS:
169169
error_message = "No JUnit XML reports found. Please review our documentation (https://docs.codecov.com/docs/test-result-ingestion-beta) to generate and upload the file."
170+
logger.error(error_message)
171+
return UploadCollectionResult(
172+
network=network,
173+
files=[],
174+
file_fixes=[],
175+
)
170176
else:
171177
error_message = "No coverage reports found. Please make sure you're generating reports successfully."
172178
raise click.ClickException(
@@ -182,7 +188,7 @@ def generate_upload_data(
182188
files=report_files,
183189
file_fixes=(
184190
self._produce_file_fixes(self.network_finder.find_files(True))
185-
if report_type == "coverage"
191+
if report_type == ReportType.COVERAGE
186192
else []
187193
),
188194
)

codecov_cli/services/upload/upload_sender.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ def send_upload_data(
5656

5757
with sentry_sdk.start_span(name="upload_sender"):
5858
with sentry_sdk.start_span(name="upload_sender_preparation"):
59+
file_not_found = False
60+
if report_type == ReportType.TEST_RESULTS and not upload_data.files:
61+
file_not_found = True
62+
5963
data = {
6064
"ci_service": ci_service,
6165
"ci_url": build_url,
@@ -65,7 +69,9 @@ def send_upload_data(
6569
"job_code": job_code,
6670
"name": name,
6771
"version": codecov_cli_version,
72+
"file_not_found": file_not_found,
6873
}
74+
6975
if upload_coverage:
7076
data["branch"] = branch
7177
data["code"] = report_code
@@ -98,6 +104,13 @@ def send_upload_data(
98104
data=data,
99105
headers=headers,
100106
)
107+
108+
if file_not_found:
109+
logger.info(
110+
"No test results reports found. Triggering notifications without uploading."
111+
)
112+
return resp_from_codecov
113+
101114
if resp_from_codecov.status_code >= 400:
102115
return resp_from_codecov
103116
resp_json_obj = json.loads(resp_from_codecov.text)
@@ -200,6 +213,7 @@ def get_url_and_possibly_update_data(
200213
commit_sha,
201214
report_code,
202215
upload_coverage=False,
216+
file_not_found=False,
203217
):
204218
if report_type == ReportType.COVERAGE:
205219
base_url = f"{upload_url}/upload/{git_service}/{encoded_slug}"
@@ -212,6 +226,7 @@ def get_url_and_possibly_update_data(
212226
data["branch"] = branch
213227
data["commit"] = commit_sha
214228
data["service"] = git_service
229+
data["file_not_found"] = file_not_found
215230
url = f"{upload_url}/upload/test_results/v1"
216231

217232
return url, data

tests/helpers/test_upload_sender.py

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@
22
import re
33
from pathlib import Path
44

5+
from copy import deepcopy
56
import pytest
67
import responses
78
from responses import matchers
89

910
from codecov_cli import __version__ as codecov_cli_version
1011
from codecov_cli.helpers.encoder import encode_slug
1112
from codecov_cli.services.upload.upload_sender import UploadSender
12-
from codecov_cli.types import UploadCollectionResult, UploadCollectionResultFileFixer
13+
from codecov_cli.types import (
14+
UploadCollectionResult,
15+
UploadCollectionResultFileFixer,
16+
UploadCollectionResultFile,
17+
)
1318
from tests.data import reports_examples
1419
from codecov_cli.helpers.upload_type import ReportType
1520

@@ -56,6 +61,7 @@
5661
"job_code": "job_code",
5762
"name": "name",
5863
"version": codecov_cli_version,
64+
"file_not_found": False,
5965
}
6066

6167

@@ -111,6 +117,18 @@ def mocked_test_results_endpoint(mocked_responses):
111117
yield resp
112118

113119

120+
@pytest.fixture
121+
def mocked_test_results_endpoint_file_not_found(mocked_responses):
122+
resp = responses.Response(
123+
responses.POST,
124+
"https://ingest.codecov.io/upload/test_results/v1",
125+
status=200,
126+
json={},
127+
)
128+
mocked_responses.add(resp)
129+
yield resp
130+
131+
114132
@pytest.fixture
115133
def mocked_storage_server(mocked_responses):
116134
resp = responses.Response(responses.PUT, "https://puturl.com", status=200)
@@ -240,7 +258,11 @@ def test_upload_sender_post_called_with_right_parameters_and_upload_coverage(
240258
) # test dict is a subset of the other
241259

242260
def test_upload_sender_post_called_with_right_parameters_test_results(
243-
self, mocked_responses, mocked_test_results_endpoint, mocked_storage_server
261+
self,
262+
mocked_responses,
263+
mocked_test_results_endpoint,
264+
mocked_storage_server,
265+
tmp_path,
244266
):
245267
headers = {"Authorization": f"token {random_token}"}
246268

@@ -249,8 +271,15 @@ def test_upload_sender_post_called_with_right_parameters_test_results(
249271
matchers.header_matcher(headers),
250272
]
251273

274+
ta_upload_collection = deepcopy(upload_collection)
275+
276+
test_path = tmp_path / "test_results.xml"
277+
test_path.write_bytes(b"test_data")
278+
279+
ta_upload_collection.files = [UploadCollectionResultFile(test_path)]
280+
252281
sending_result = UploadSender().send_upload_data(
253-
upload_collection,
282+
ta_upload_collection,
254283
random_sha,
255284
random_token,
256285
**test_results_named_upload_data,
@@ -272,6 +301,41 @@ def test_upload_sender_post_called_with_right_parameters_test_results(
272301
assert put_req_made.url == "https://puturl.com/"
273302
assert "test_results_files" in put_req_made.body.decode("utf-8")
274303

304+
def test_upload_sender_post_called_with_right_parameters_test_results_file_not_found(
305+
self,
306+
mocked_responses,
307+
mocked_test_results_endpoint_file_not_found,
308+
tmp_path,
309+
):
310+
headers = {"Authorization": f"token {random_token}"}
311+
312+
req_data = deepcopy(request_data)
313+
req_data["file_not_found"] = True
314+
315+
mocked_legacy_upload_endpoint.match = [
316+
matchers.json_params_matcher(req_data),
317+
matchers.header_matcher(headers),
318+
]
319+
320+
sending_result = UploadSender().send_upload_data(
321+
upload_collection,
322+
random_sha,
323+
random_token,
324+
**test_results_named_upload_data,
325+
)
326+
assert sending_result.error is None
327+
assert sending_result.warnings == []
328+
329+
assert len(mocked_responses.calls) == 1
330+
331+
post_req_made = mocked_responses.calls[0].request
332+
response = json.loads(mocked_responses.calls[0].response.text)
333+
assert response.get("raw_upload_location") is None
334+
assert post_req_made.url == "https://ingest.codecov.io/upload/test_results/v1"
335+
assert (
336+
post_req_made.headers.items() >= headers.items()
337+
) # test dict is a subset of the other
338+
275339
def test_upload_sender_post_called_with_right_parameters_tokenless(
276340
self,
277341
mocked_responses,

0 commit comments

Comments
 (0)