Skip to content

Commit 18f0d55

Browse files
authored
Merge pull request #174 from codecov/dana/file-fix
use --file option to let users set specific files to upload
2 parents 0d15445 + e45ecb5 commit 18f0d55

File tree

5 files changed

+103
-16
lines changed

5 files changed

+103
-16
lines changed

codecov_cli/commands/upload.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,17 @@ def _turn_env_vars_into_dict(ctx, params, value):
6464
"--file",
6565
"--coverage-files-search-direct-file",
6666
"coverage_files_search_explicitly_listed_files",
67-
help="Explicit files to upload",
67+
help="Explicit files to upload. These will be added to the coverage files found for upload. If you wish to only upload the specified files, please consider using --disable-search to disable uploading other files.",
6868
type=click.Path(path_type=pathlib.Path),
6969
multiple=True,
7070
default=[],
7171
)
72+
@click.option(
73+
"--disable-search",
74+
help="Disable search for coverage files. This is helpful when specifying what files you want to uload with the --file option.",
75+
is_flag=True,
76+
default=False,
77+
)
7278
@click.option(
7379
"-b",
7480
"--build",
@@ -189,6 +195,7 @@ def do_upload(
189195
coverage_files_search_root_folder: pathlib.Path,
190196
coverage_files_search_exclude_folders: typing.List[pathlib.Path],
191197
coverage_files_search_explicitly_listed_files: typing.List[pathlib.Path],
198+
disable_search: bool,
192199
token: typing.Optional[uuid.UUID],
193200
plugin_names: typing.List[str],
194201
branch: typing.Optional[str],
@@ -227,6 +234,7 @@ def do_upload(
227234
pull_request_number=pull_request_number,
228235
git_service=git_service,
229236
enterprise_url=enterprise_url,
237+
disable_search=disable_search,
230238
)
231239
),
232240
)
@@ -260,4 +268,5 @@ def do_upload(
260268
dry_run=dry_run,
261269
git_service=git_service,
262270
enterprise_url=enterprise_url,
271+
disable_search=disable_search,
263272
)

codecov_cli/services/upload/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,14 @@ def do_upload_logic(
4747
dry_run: bool = False,
4848
git_service: typing.Optional[str],
4949
enterprise_url: typing.Optional[str],
50+
disable_search: bool = False,
5051
):
5152
preparation_plugins = select_preparation_plugins(cli_config, plugin_names)
5253
coverage_file_selector = select_coverage_file_finder(
5354
coverage_files_search_root_folder,
5455
coverage_files_search_exclude_folders,
5556
coverage_files_search_explicitly_listed_files,
57+
disable_search,
5658
)
5759
network_finder = select_network_finder(versioning_system)
5860
collector = UploadCollector(

codecov_cli/services/upload/coverage_file_finder.py

+80-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import logging
12
import os
23
import typing
34
from pathlib import Path
45

56
from codecov_cli.helpers.folder_searcher import globs_to_regex, search_files
67
from codecov_cli.types import UploadCollectionResultFile
78

9+
logger = logging.getLogger("codecovcli")
10+
811
coverage_files_patterns = [
912
"*.clover",
1013
"*.codecov.*",
@@ -163,26 +166,93 @@
163166

164167
class CoverageFileFinder(object):
165168
def __init__(
166-
self, project_root: Path = None, folders_to_ignore: typing.List[str] = None
169+
self,
170+
project_root: Path = None,
171+
folders_to_ignore: typing.List[str] = None,
172+
explicitly_listed_files: typing.List[Path] = None,
173+
disable_search: bool = False,
167174
):
168175
self.project_root = project_root or Path(os.getcwd())
169176
self.folders_to_ignore = folders_to_ignore or []
177+
self.explicitly_listed_files = explicitly_listed_files or None
178+
self.disable_search = disable_search
170179

171180
def find_coverage_files(self) -> typing.List[UploadCollectionResultFile]:
172-
regex_patterns_to_include = globs_to_regex(coverage_files_patterns)
173181
regex_patterns_to_exclude = globs_to_regex(coverage_files_excluded_patterns)
182+
coverage_files_paths = []
183+
user_coverage_files_paths = []
184+
if self.explicitly_listed_files:
185+
user_coverage_files_paths = self.get_user_specified_coverage_files(
186+
regex_patterns_to_exclude
187+
)
188+
if not self.disable_search:
189+
regex_patterns_to_include = globs_to_regex(coverage_files_patterns)
190+
coverage_files_paths = search_files(
191+
self.project_root,
192+
default_folders_to_ignore + self.folders_to_ignore,
193+
filename_include_regex=regex_patterns_to_include,
194+
filename_exclude_regex=regex_patterns_to_exclude,
195+
)
196+
result_files = [
197+
UploadCollectionResultFile(path)
198+
for path in coverage_files_paths
199+
if coverage_files_paths
200+
]
201+
user_result_files = [
202+
UploadCollectionResultFile(path)
203+
for path in user_coverage_files_paths
204+
if user_coverage_files_paths
205+
]
206+
207+
return list(set(result_files + user_result_files))
174208

175-
coverage_files_paths = search_files(
176-
self.project_root,
177-
default_folders_to_ignore + self.folders_to_ignore,
178-
filename_include_regex=regex_patterns_to_include,
179-
filename_exclude_regex=regex_patterns_to_exclude,
209+
def get_user_specified_coverage_files(self, regex_patterns_to_exclude):
210+
user_filenames_to_include = []
211+
files_excluded_but_user_includes = []
212+
for file in self.explicitly_listed_files:
213+
user_filenames_to_include.append(file.name)
214+
if regex_patterns_to_exclude.match(file.name):
215+
files_excluded_but_user_includes.append(str(file))
216+
if files_excluded_but_user_includes:
217+
logger.warning(
218+
"Some files being explicitly added are found in the list of excluded files for upload.",
219+
extra=dict(
220+
extra_log_attributes=dict(files=files_excluded_but_user_includes)
221+
),
222+
)
223+
regex_patterns_to_include = globs_to_regex(user_filenames_to_include)
224+
multipart_include_regex = globs_to_regex(
225+
[str(path.resolve()) for path in self.explicitly_listed_files]
180226
)
227+
user_coverage_files_paths = list(
228+
search_files(
229+
self.project_root,
230+
default_folders_to_ignore + self.folders_to_ignore,
231+
filename_include_regex=regex_patterns_to_include,
232+
filename_exclude_regex=regex_patterns_to_exclude,
233+
multipart_include_regex=multipart_include_regex,
234+
)
235+
)
236+
not_found_files = []
237+
for filepath in self.explicitly_listed_files:
238+
if filepath.resolve() not in user_coverage_files_paths:
239+
not_found_files.append(filepath)
240+
241+
if not_found_files:
242+
logger.warning(
243+
"Some files were not found",
244+
extra=dict(extra_log_attributes=dict(not_found_files=not_found_files)),
245+
)
181246

182-
return [UploadCollectionResultFile(path) for path in coverage_files_paths]
247+
return user_coverage_files_paths
183248

184249

185250
def select_coverage_file_finder(
186-
root_folder_to_search, folders_to_ignore, explicitly_listed_files
251+
root_folder_to_search, folders_to_ignore, explicitly_listed_files, disable_search
187252
):
188-
return CoverageFileFinder(root_folder_to_search, folders_to_ignore)
253+
return CoverageFileFinder(
254+
root_folder_to_search,
255+
folders_to_ignore,
256+
explicitly_listed_files,
257+
disable_search,
258+
)

tests/services/upload/test_coverage_file_finder.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,17 @@ def test_find_coverage_files_mocked_search_files(self, mocker):
2323
)
2424

2525
expected = [
26-
UploadCollectionResultFile(Path("a/b.txt")),
2726
UploadCollectionResultFile(Path("c.txt")),
27+
UploadCollectionResultFile(Path("a/b.txt")),
2828
]
2929

30-
assert CoverageFileFinder().find_coverage_files() == expected
30+
expected_paths = sorted([file.get_filename() for file in expected])
31+
32+
actual_paths = sorted(
33+
[file.get_filename() for file in CoverageFileFinder().find_coverage_files()]
34+
)
35+
36+
assert expected_paths == actual_paths
3137

3238
def test_find_coverage_files(self, tmp_path):
3339
(tmp_path / "sub").mkdir()

tests/services/upload/test_upload_service.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def test_do_upload_logic_happy_path_legacy_uploader(mocker):
7979
mock_select_preparation_plugins.assert_called_with(
8080
cli_config, ["first_plugin", "another", "forth"]
8181
)
82-
mock_select_coverage_file_finder.assert_called_with(None, None, None)
82+
mock_select_coverage_file_finder.assert_called_with(None, None, None, False)
8383
mock_select_network_finder.assert_called_with(versioning_system)
8484
mock_generate_upload_data.assert_called_with()
8585
mock_send_upload_data.assert_called_with(
@@ -164,7 +164,7 @@ def test_do_upload_logic_happy_path(mocker):
164164
mock_select_preparation_plugins.assert_called_with(
165165
cli_config, ["first_plugin", "another", "forth"]
166166
)
167-
mock_select_coverage_file_finder.assert_called_with(None, None, None)
167+
mock_select_coverage_file_finder.assert_called_with(None, None, None, False)
168168
mock_select_network_finder.assert_called_with(versioning_system)
169169
mock_generate_upload_data.assert_called_with()
170170
mock_send_upload_data.assert_called_with(
@@ -236,7 +236,7 @@ def test_do_upload_logic_dry_run(mocker):
236236
enterprise_url=None,
237237
)
238238
out_bytes = parse_outstreams_into_log_lines(outstreams[0].getvalue())
239-
mock_select_coverage_file_finder.assert_called_with(None, None, None)
239+
mock_select_coverage_file_finder.assert_called_with(None, None, None, False)
240240
mock_select_network_finder.assert_called_with(versioning_system)
241241
assert mock_generate_upload_data.call_count == 1
242242
assert mock_send_upload_data.call_count == 0

0 commit comments

Comments
 (0)