Skip to content

Commit ac2d78c

Browse files
feat: upload TA even when a file is not found (#585)
* refactor: create ReportType enum we only want to ingest a string from the cli options as click doesn't support enums yet "internally" we only want to use this enum * 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 * build: fix tests
1 parent 2ebbb6c commit ac2d78c

14 files changed

+226
-72
lines changed

codecov_cli/commands/process_test_results.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
send_get_request,
2222
send_post_request,
2323
)
24+
from codecov_cli.helpers.upload_type import ReportType
2425
from codecov_cli.services.upload.file_finder import select_file_finder
2526
from codecov_cli.types import CommandContext, RequestResult, UploadCollectionResultFile
2627

@@ -103,7 +104,11 @@ def process_test_results(
103104
with sentry_sdk.start_transaction(op="task", name="Process Test Results"):
104105
with sentry_sdk.start_span(name="process_test_results"):
105106
file_finder = select_file_finder(
106-
dir, exclude_folders, files, disable_search, report_type="test_results"
107+
dir,
108+
exclude_folders,
109+
files,
110+
disable_search,
111+
report_type=ReportType.TEST_RESULTS,
107112
)
108113

109114
upload_collection_results: List[UploadCollectionResultFile] = (

codecov_cli/commands/upload.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import os
33
import pathlib
44
import typing
5-
65
import click
76
import sentry_sdk
87

@@ -11,6 +10,7 @@
1110
from codecov_cli.helpers.options import global_options
1211
from codecov_cli.services.upload import do_upload_logic
1312
from codecov_cli.types import CommandContext
13+
from codecov_cli.helpers.upload_type import report_type_from_str, ReportType
1414

1515
logger = logging.getLogger("codecovcli")
1616

@@ -167,6 +167,7 @@ def _turn_env_vars_into_dict(ctx, params, value):
167167
),
168168
click.option(
169169
"--report-type",
170+
"report_type_str",
170171
help="The type of the file to upload, coverage by default. Possible values are: testing, coverage.",
171172
default="coverage",
172173
type=click.Choice(["coverage", "test_results"]),
@@ -241,7 +242,7 @@ def do_upload(
241242
network_root_folder: pathlib.Path,
242243
plugin_names: typing.List[str],
243244
pull_request_number: typing.Optional[str],
244-
report_type: str,
245+
report_type_str: str,
245246
slug: typing.Optional[str],
246247
swift_project: typing.Optional[str],
247248
token: typing.Optional[str],
@@ -261,6 +262,8 @@ def do_upload(
261262
extra_log_attributes=args,
262263
),
263264
)
265+
266+
report_type: ReportType = report_type_from_str(report_type_str)
264267
do_upload_logic(
265268
cli_config,
266269
versioning_system,
@@ -276,7 +279,9 @@ def do_upload(
276279
env_vars=env_vars,
277280
fail_on_error=fail_on_error,
278281
files_search_exclude_folders=list(files_search_exclude_folders),
279-
files_search_explicitly_listed_files=list(files_search_explicitly_listed_files),
282+
files_search_explicitly_listed_files=list(
283+
files_search_explicitly_listed_files
284+
),
280285
files_search_root_folder=files_search_root_folder,
281286
flags=flags,
282287
gcov_args=gcov_args,
@@ -296,7 +301,7 @@ def do_upload(
296301
slug=slug,
297302
swift_project=swift_project,
298303
token=token,
299-
upload_file_type=report_type,
304+
report_type=report_type,
300305
use_legacy_uploader=use_legacy_uploader,
301306
args=args,
302307
)

codecov_cli/commands/upload_coverage.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from codecov_cli.helpers.args import get_cli_args
1212
from codecov_cli.helpers.options import global_options
1313
from codecov_cli.opentelemetry import close_telem
14+
from codecov_cli.helpers.upload_type import report_type_from_str, ReportType
1415
from codecov_cli.services.upload_coverage import upload_coverage_logic
1516
from codecov_cli.types import CommandContext
1617

@@ -56,7 +57,7 @@ def upload_coverage(
5657
plugin_names: typing.List[str],
5758
pull_request_number: typing.Optional[str],
5859
report_code: str,
59-
report_type: str,
60+
report_type_str: str,
6061
slug: typing.Optional[str],
6162
swift_project: typing.Optional[str],
6263
token: typing.Optional[str],
@@ -72,7 +73,9 @@ def upload_coverage(
7273
),
7374
)
7475

75-
if not use_legacy_uploader and report_type == "coverage":
76+
report_type = report_type_from_str(report_type_str)
77+
78+
if not use_legacy_uploader and report_type == ReportType.COVERAGE:
7679
versioning_system = ctx.obj["versioning_system"]
7780
codecov_yaml = ctx.obj["codecov_yaml"] or {}
7881
cli_config = codecov_yaml.get("cli", {})
@@ -116,7 +119,7 @@ def upload_coverage(
116119
slug=slug,
117120
swift_project=swift_project,
118121
token=token,
119-
upload_file_type=report_type,
122+
report_type=report_type,
120123
use_legacy_uploader=use_legacy_uploader,
121124
args=args,
122125
)
@@ -132,7 +135,7 @@ def upload_coverage(
132135
git_service=git_service,
133136
fail_on_error=True,
134137
)
135-
if report_type == "coverage":
138+
if report_type == ReportType.COVERAGE:
136139
ctx.invoke(
137140
create_report,
138141
token=token,
@@ -171,7 +174,7 @@ def upload_coverage(
171174
plugin_names=plugin_names,
172175
pull_request_number=pull_request_number,
173176
report_code=report_code,
174-
report_type=report_type,
177+
report_type_str=report_type_str,
175178
slug=slug,
176179
swift_project=swift_project,
177180
token=token,

codecov_cli/commands/upload_process.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from codecov_cli.commands.upload import do_upload, global_upload_options
1111
from codecov_cli.helpers.args import get_cli_args
1212
from codecov_cli.helpers.options import global_options
13+
from codecov_cli.helpers.upload_type import report_type_from_str, ReportType
1314
from codecov_cli.types import CommandContext
1415

1516
logger = logging.getLogger("codecovcli")
@@ -54,7 +55,7 @@ def upload_process(
5455
plugin_names: typing.List[str],
5556
pull_request_number: typing.Optional[str],
5657
report_code: str,
57-
report_type: str,
58+
report_type_str: str,
5859
slug: typing.Optional[str],
5960
swift_project: typing.Optional[str],
6061
token: typing.Optional[str],
@@ -81,7 +82,9 @@ def upload_process(
8182
git_service=git_service,
8283
fail_on_error=True,
8384
)
84-
if report_type == "coverage":
85+
86+
report_type = report_type_from_str(report_type_str)
87+
if report_type == ReportType.COVERAGE:
8588
ctx.invoke(
8689
create_report,
8790
token=token,
@@ -120,7 +123,7 @@ def upload_process(
120123
plugin_names=plugin_names,
121124
pull_request_number=pull_request_number,
122125
report_code=report_code,
123-
report_type=report_type,
126+
report_type_str=report_type_str,
124127
slug=slug,
125128
swift_project=swift_project,
126129
token=token,

codecov_cli/helpers/upload_type.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from enum import Enum
2+
3+
4+
class ReportType(Enum):
5+
COVERAGE = "coverage"
6+
TEST_RESULTS = "test_results"
7+
8+
9+
def report_type_from_str(report_type_str: str) -> ReportType:
10+
if report_type_str == "coverage":
11+
return ReportType.COVERAGE
12+
elif report_type_str == "test_results":
13+
return ReportType.TEST_RESULTS
14+
else:
15+
raise ValueError(f"Invalid upload type: {report_type_str}")

codecov_cli/opentelemetry.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88

99
def init_telem(ctx):
10-
if ctx['disable_telem']:
10+
if ctx["disable_telem"]:
1111
return
12-
if ctx['enterprise_url']: # dont run on dedicated cloud
12+
if ctx["enterprise_url"]: # dont run on dedicated cloud
13+
return
14+
if os.getenv("CODECOV_ENV", "production") == "test":
1315
return
1416
if os.getenv('CODECOV_ENV', 'production') == 'test':
1517
return

codecov_cli/services/upload/__init__.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from codecov_cli.helpers.ci_adapters.base import CIAdapterBase
99
from codecov_cli.helpers.request import log_warnings_and_errors_if_any
1010
from codecov_cli.helpers.versioning_systems import VersioningSystemInterface
11+
from codecov_cli.helpers.upload_type import ReportType
1112
from codecov_cli.plugins import select_preparation_plugins
1213
from codecov_cli.services.upload.file_finder import select_file_finder
1314
from codecov_cli.services.upload.legacy_upload_sender import LegacyUploadSender
@@ -59,7 +60,7 @@ def do_upload_logic(
5960
slug: typing.Optional[str],
6061
swift_project: typing.Optional[str],
6162
token: typing.Optional[str],
62-
upload_file_type: str = "coverage",
63+
report_type: ReportType = ReportType.COVERAGE,
6364
use_legacy_uploader: bool = False,
6465
):
6566
plugin_config = {
@@ -71,18 +72,18 @@ def do_upload_logic(
7172
"project_root": files_search_root_folder,
7273
"swift_project": swift_project,
7374
}
74-
if upload_file_type == "coverage":
75+
if report_type == ReportType.COVERAGE:
7576
preparation_plugins = select_preparation_plugins(
7677
cli_config, plugin_names, plugin_config
7778
)
78-
elif upload_file_type == "test_results":
79+
elif report_type == ReportType.TEST_RESULTS:
7980
preparation_plugins = []
8081
file_selector = select_file_finder(
8182
files_search_root_folder,
8283
files_search_exclude_folders,
8384
files_search_explicitly_listed_files,
8485
disable_search,
85-
upload_file_type,
86+
report_type,
8687
)
8788
network_finder = select_network_finder(
8889
versioning_system,
@@ -98,7 +99,7 @@ def do_upload_logic(
9899
plugin_config,
99100
)
100101
try:
101-
upload_data = collector.generate_upload_data(upload_file_type)
102+
upload_data = collector.generate_upload_data(report_type)
102103
except click.ClickException as exp:
103104
if handle_no_reports_found:
104105
logger.info(
@@ -138,7 +139,7 @@ def do_upload_logic(
138139
token=token,
139140
env_vars=env_vars,
140141
report_code=report_code,
141-
upload_file_type=upload_file_type,
142+
report_type=report_type,
142143
name=name,
143144
branch=branch,
144145
slug=slug,

codecov_cli/services/upload/file_finder.py

+17-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import sentry_sdk
77

88
from codecov_cli.helpers.folder_searcher import globs_to_regex, search_files
9+
from codecov_cli.helpers.upload_type import ReportType
910
from codecov_cli.types import UploadCollectionResultFile
1011

1112
logger = logging.getLogger("codecovcli")
@@ -193,46 +194,54 @@ def __init__(
193194
folders_to_ignore: Optional[List[Path]] = None,
194195
explicitly_listed_files: Optional[List[Path]] = None,
195196
disable_search: bool = False,
196-
report_type: str = "coverage",
197+
report_type: ReportType = ReportType.COVERAGE,
197198
):
198199
self.search_root = search_root or Path(os.getcwd())
199200
self.folders_to_ignore = list(folders_to_ignore) if folders_to_ignore else []
200201
self.explicitly_listed_files = explicitly_listed_files or None
201202
self.disable_search = disable_search
202-
self.report_type = report_type
203+
self.report_type: ReportType = report_type
203204

204205
def find_files(self) -> List[UploadCollectionResultFile]:
205206
with sentry_sdk.start_span(name="find_files"):
206-
if self.report_type == "coverage":
207+
if self.report_type == ReportType.COVERAGE:
207208
files_excluded_patterns = coverage_files_excluded_patterns
208209
files_patterns = coverage_files_patterns
209-
elif self.report_type == "test_results":
210+
elif self.report_type == ReportType.TEST_RESULTS:
210211
files_excluded_patterns = test_results_files_excluded_patterns
211212
files_patterns = test_results_files_patterns
212213
regex_patterns_to_exclude = globs_to_regex(files_excluded_patterns)
213214
assert regex_patterns_to_exclude # this is never `None`
214215
files_paths: Iterable[Path] = []
215216
user_files_paths = []
216217
if self.explicitly_listed_files:
217-
user_files_paths = self.get_user_specified_files(regex_patterns_to_exclude)
218+
user_files_paths = self.get_user_specified_files(
219+
regex_patterns_to_exclude
220+
)
218221
if not self.disable_search:
219222
regex_patterns_to_include = globs_to_regex(files_patterns)
220223
assert regex_patterns_to_include # this is never `None`
221224
files_paths = search_files(
222225
self.search_root,
223-
default_folders_to_ignore + [str(folder) for folder in self.folders_to_ignore],
226+
default_folders_to_ignore
227+
+ [str(folder) for folder in self.folders_to_ignore],
224228
filename_include_regex=regex_patterns_to_include,
225229
filename_exclude_regex=regex_patterns_to_exclude,
226230
)
227231
result_files = [UploadCollectionResultFile(path) for path in files_paths]
232+
user_result_files = [
233+
UploadCollectionResultFile(path)
234+
for path in user_files_paths
235+
if user_files_paths
236+
]
228237

229238
user_result_files = []
230239
for path in user_files_paths:
231240
if os.path.isfile(path):
232241
user_result_files.append(UploadCollectionResultFile(path))
233242
else:
234243
logger.warning(
235-
f"File \"{path}\" could not be found or does not exist. Please enter in the full path or from the search root \"{self.search_root}\"",
244+
f'File "{path}" could not be found or does not exist. Please enter in the full path or from the search root "{self.search_root}"',
236245
)
237246

238247
return list(set(result_files + user_result_files))
@@ -287,7 +296,7 @@ def select_file_finder(
287296
folders_to_ignore,
288297
explicitly_listed_files,
289298
disable_search,
290-
report_type="coverage",
299+
report_type: ReportType = ReportType.COVERAGE,
291300
):
292301
return FileFinder(
293302
root_folder_to_search,

codecov_cli/services/upload/upload_collector.py

+15-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import click
1010
import sentry_sdk
1111

12+
from codecov_cli.helpers.upload_type import ReportType
1213
from codecov_cli.services.upload.file_finder import FileFinder
1314
from codecov_cli.services.upload.network_finder import NetworkFinder
1415
from codecov_cli.types import (
@@ -149,7 +150,9 @@ def _get_file_fixes(
149150
path, fixed_lines_without_reason, fixed_lines_with_reason, eof
150151
)
151152

152-
def generate_upload_data(self, report_type="coverage") -> UploadCollectionResult:
153+
def generate_upload_data(
154+
self, report_type: ReportType = ReportType.COVERAGE
155+
) -> UploadCollectionResult:
153156
with sentry_sdk.start_span(name="upload_collector"):
154157
for prep in self.preparation_plugins:
155158
logger.debug(f"Running preparation plugin: {type(prep)}")
@@ -158,10 +161,18 @@ def generate_upload_data(self, report_type="coverage") -> UploadCollectionResult
158161
with sentry_sdk.start_span(name="file_collector"):
159162
network = self.network_finder.find_files()
160163
report_files = self.file_finder.find_files()
161-
logger.info(f"Found {len(report_files)} {report_type} files to report")
164+
logger.info(
165+
f"Found {len(report_files)} {report_type.value} files to report"
166+
)
162167
if not report_files:
163-
if report_type == "test_results":
168+
if report_type == ReportType.TEST_RESULTS:
164169
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+
)
165176
else:
166177
error_message = "No coverage reports found. Please make sure you're generating reports successfully."
167178
raise click.ClickException(
@@ -177,7 +188,7 @@ def generate_upload_data(self, report_type="coverage") -> UploadCollectionResult
177188
files=report_files,
178189
file_fixes=(
179190
self._produce_file_fixes(self.network_finder.find_files(True))
180-
if report_type == "coverage"
191+
if report_type == ReportType.COVERAGE
181192
else []
182193
),
183194
)

0 commit comments

Comments
 (0)