Skip to content

Commit 750e957

Browse files
feat: add network prefix and filter options (#406)
* feat: add network prefix and filter options * fix: update network tests * fix: add tests * fix: pull all files for file fixes * fix: added description to network-filter
1 parent 3ce68bd commit 750e957

9 files changed

Lines changed: 202 additions & 100 deletions

File tree

codecov_cli/commands/upload.py

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,14 @@ def _turn_env_vars_into_dict(ctx, params, value):
164164
default="coverage",
165165
type=click.Choice(["coverage", "test_results"]),
166166
),
167+
click.option(
168+
"--network-filter",
169+
help="Specify a filter on the files listed in the network section of the Codecov report. This will only add files whose path begin with the specified filter. Useful for upload-specific path fixing",
170+
),
171+
click.option(
172+
"--network-prefix",
173+
help="Specify a prefix on files listed in the network section of the Codecov report. Useful to help resolve path fixing",
174+
),
167175
]
168176

169177

@@ -181,29 +189,31 @@ def do_upload(
181189
ctx: click.Context,
182190
commit_sha: str,
183191
report_code: str,
192+
branch: typing.Optional[str],
184193
build_code: typing.Optional[str],
185194
build_url: typing.Optional[str],
186-
job_code: typing.Optional[str],
195+
disable_file_fixes: bool,
196+
disable_search: bool,
197+
dry_run: bool,
187198
env_vars: typing.Dict[str, str],
199+
fail_on_error: bool,
200+
files_search_exclude_folders: typing.List[pathlib.Path],
201+
files_search_explicitly_listed_files: typing.List[pathlib.Path],
202+
files_search_root_folder: pathlib.Path,
188203
flags: typing.List[str],
204+
git_service: typing.Optional[str],
205+
handle_no_reports_found: bool,
206+
job_code: typing.Optional[str],
189207
name: typing.Optional[str],
208+
network_filter: typing.Optional[str],
209+
network_prefix: typing.Optional[str],
190210
network_root_folder: pathlib.Path,
191-
files_search_root_folder: pathlib.Path,
192-
files_search_exclude_folders: typing.List[pathlib.Path],
193-
files_search_explicitly_listed_files: typing.List[pathlib.Path],
194-
disable_search: bool,
195-
disable_file_fixes: bool,
196-
token: typing.Optional[str],
197211
plugin_names: typing.List[str],
198-
branch: typing.Optional[str],
199-
slug: typing.Optional[str],
200212
pull_request_number: typing.Optional[str],
201-
use_legacy_uploader: bool,
202-
fail_on_error: bool,
203-
dry_run: bool,
204-
git_service: typing.Optional[str],
205-
handle_no_reports_found: bool,
206213
report_type: str,
214+
slug: typing.Optional[str],
215+
token: typing.Optional[str],
216+
use_legacy_uploader: bool,
207217
):
208218
versioning_system = ctx.obj["versioning_system"]
209219
codecov_yaml = ctx.obj["codecov_yaml"] or {}
@@ -214,60 +224,64 @@ def do_upload(
214224
"Starting upload processing",
215225
extra=dict(
216226
extra_log_attributes=dict(
217-
upload_file_type=report_type,
218-
commit_sha=commit_sha,
219-
report_code=report_code,
227+
branch=branch,
220228
build_code=build_code,
221229
build_url=build_url,
222-
job_code=job_code,
230+
commit_sha=commit_sha,
231+
disable_file_fixes=disable_file_fixes,
232+
disable_search=disable_search,
233+
enterprise_url=enterprise_url,
223234
env_vars=env_vars,
235+
files_search_exclude_folders=files_search_exclude_folders,
236+
files_search_explicitly_listed_files=files_search_explicitly_listed_files,
237+
files_search_root_folder=files_search_root_folder,
224238
flags=flags,
239+
git_service=git_service,
240+
handle_no_reports_found=handle_no_reports_found,
241+
job_code=job_code,
225242
name=name,
243+
network_filter=network_filter,
244+
network_prefix=network_prefix,
226245
network_root_folder=network_root_folder,
227-
files_search_root_folder=files_search_root_folder,
228-
files_search_exclude_folders=files_search_exclude_folders,
229-
files_search_explicitly_listed_files=files_search_explicitly_listed_files,
230246
plugin_names=plugin_names,
231-
token=token,
232-
branch=branch,
233-
slug=slug,
234247
pull_request_number=pull_request_number,
235-
git_service=git_service,
236-
enterprise_url=enterprise_url,
237-
disable_search=disable_search,
238-
disable_file_fixes=disable_file_fixes,
239-
handle_no_reports_found=handle_no_reports_found,
248+
report_code=report_code,
249+
slug=slug,
250+
token=token,
251+
upload_file_type=report_type,
240252
)
241253
),
242254
)
243255
do_upload_logic(
244256
cli_config,
245257
versioning_system,
246258
ci_adapter,
247-
upload_file_type=report_type,
248-
commit_sha=commit_sha,
249-
report_code=report_code,
259+
branch=branch,
250260
build_code=build_code,
251261
build_url=build_url,
252-
job_code=job_code,
262+
commit_sha=commit_sha,
263+
disable_file_fixes=disable_file_fixes,
264+
disable_search=disable_search,
265+
dry_run=dry_run,
266+
enterprise_url=enterprise_url,
253267
env_vars=env_vars,
268+
fail_on_error=fail_on_error,
269+
files_search_exclude_folders=list(files_search_exclude_folders),
270+
files_search_explicitly_listed_files=list(files_search_explicitly_listed_files),
271+
files_search_root_folder=files_search_root_folder,
254272
flags=flags,
273+
git_service=git_service,
274+
handle_no_reports_found=handle_no_reports_found,
275+
job_code=job_code,
255276
name=name,
277+
network_filter=network_filter,
278+
network_prefix=network_prefix,
256279
network_root_folder=network_root_folder,
257-
files_search_root_folder=files_search_root_folder,
258-
files_search_exclude_folders=list(files_search_exclude_folders),
259-
files_search_explicitly_listed_files=list(files_search_explicitly_listed_files),
260280
plugin_names=plugin_names,
261-
token=token,
262-
branch=branch,
263-
slug=slug,
264281
pull_request_number=pull_request_number,
282+
report_code=report_code,
283+
slug=slug,
284+
token=token,
285+
upload_file_type=report_type,
265286
use_legacy_uploader=use_legacy_uploader,
266-
fail_on_error=fail_on_error,
267-
dry_run=dry_run,
268-
git_service=git_service,
269-
enterprise_url=enterprise_url,
270-
disable_search=disable_search,
271-
handle_no_reports_found=handle_no_reports_found,
272-
disable_file_fixes=disable_file_fixes,
273287
)

codecov_cli/commands/upload_process.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ def upload_process(
3131
env_vars: typing.Dict[str, str],
3232
flags: typing.List[str],
3333
name: typing.Optional[str],
34+
network_filter: typing.Optional[str],
35+
network_prefix: typing.Optional[str],
3436
network_root_folder: pathlib.Path,
3537
files_search_root_folder: pathlib.Path,
3638
files_search_exclude_folders: typing.List[pathlib.Path],

codecov_cli/services/upload/__init__.py

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,32 +25,34 @@ def do_upload_logic(
2525
versioning_system: VersioningSystemInterface,
2626
ci_adapter: CIAdapterBase,
2727
*,
28-
commit_sha: str,
29-
report_code: str,
28+
branch: typing.Optional[str],
3029
build_code: typing.Optional[str],
3130
build_url: typing.Optional[str],
32-
job_code: typing.Optional[str],
31+
commit_sha: str,
32+
disable_file_fixes: bool = False,
33+
disable_search: bool = False,
34+
dry_run: bool = False,
35+
enterprise_url: typing.Optional[str],
3336
env_vars: typing.Dict[str, str],
37+
fail_on_error: bool = False,
38+
files_search_exclude_folders: typing.List[Path],
39+
files_search_explicitly_listed_files: typing.List[Path],
40+
files_search_root_folder: Path,
3441
flags: typing.List[str],
42+
git_service: typing.Optional[str],
43+
handle_no_reports_found: bool = False,
44+
job_code: typing.Optional[str],
3545
name: typing.Optional[str],
46+
network_filter: typing.Optional[str],
47+
network_prefix: typing.Optional[str],
3648
network_root_folder: Path,
37-
files_search_root_folder: Path,
38-
files_search_exclude_folders: typing.List[Path],
39-
files_search_explicitly_listed_files: typing.List[Path],
4049
plugin_names: typing.List[str],
41-
token: str,
42-
branch: typing.Optional[str],
43-
slug: typing.Optional[str],
4450
pull_request_number: typing.Optional[str],
51+
report_code: str,
52+
slug: typing.Optional[str],
53+
token: str,
4554
upload_file_type: str = "coverage",
4655
use_legacy_uploader: bool = False,
47-
fail_on_error: bool = False,
48-
dry_run: bool = False,
49-
git_service: typing.Optional[str],
50-
enterprise_url: typing.Optional[str],
51-
disable_search: bool = False,
52-
handle_no_reports_found: bool = False,
53-
disable_file_fixes: bool = False,
5456
):
5557
if upload_file_type == "coverage":
5658
preparation_plugins = select_preparation_plugins(cli_config, plugin_names)
@@ -63,7 +65,12 @@ def do_upload_logic(
6365
disable_search,
6466
upload_file_type,
6567
)
66-
network_finder = select_network_finder(versioning_system)
68+
network_finder = select_network_finder(
69+
versioning_system,
70+
network_filter=network_filter,
71+
network_prefix=network_prefix,
72+
network_root_folder=network_root_folder,
73+
)
6774
collector = UploadCollector(
6875
preparation_plugins, network_finder, file_selector, disable_file_fixes
6976
)

codecov_cli/services/upload/network_finder.py

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,39 @@
55

66

77
class NetworkFinder(object):
8-
def __init__(self, versioning_system: VersioningSystemInterface):
8+
def __init__(
9+
self,
10+
versioning_system: VersioningSystemInterface,
11+
network_filter: typing.Optional[str],
12+
network_prefix: typing.Optional[str],
13+
network_root_folder: pathlib.Path,
14+
):
915
self.versioning_system = versioning_system
16+
self.network_filter = network_filter
17+
self.network_prefix = network_prefix
18+
self.network_root_folder = network_root_folder
1019

11-
def find_files(
12-
self,
13-
network_root: typing.Optional[pathlib.Path] = None,
14-
network_filter=None,
15-
network_adjuster=None,
16-
) -> typing.List[str]:
17-
return self.versioning_system.list_relevant_files(network_root)
20+
def find_files(self, ignore_filters=False) -> typing.List[str]:
21+
files = self.versioning_system.list_relevant_files(self.network_root_folder)
22+
23+
if not ignore_filters:
24+
if self.network_filter:
25+
files = [file for file in files if file.startswith(self.network_filter)]
26+
if self.network_prefix:
27+
files = [self.network_prefix + file for file in files]
28+
29+
return files
1830

1931

20-
def select_network_finder(versioning_system: VersioningSystemInterface):
21-
return NetworkFinder(versioning_system)
32+
def select_network_finder(
33+
versioning_system: VersioningSystemInterface,
34+
network_filter: typing.Optional[str],
35+
network_prefix: typing.Optional[str],
36+
network_root_folder: pathlib.Path,
37+
):
38+
return NetworkFinder(
39+
versioning_system,
40+
network_filter,
41+
network_prefix,
42+
network_root_folder,
43+
)

codecov_cli/services/upload/upload_collector.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ def __init__(
3636
self.file_finder = file_finder
3737
self.disable_file_fixes = disable_file_fixes
3838

39-
def _produce_file_fixes_for_network(
40-
self, network: typing.List[str]
39+
def _produce_file_fixes(
40+
self, files: typing.List[str]
4141
) -> typing.List[UploadCollectionResultFileFixer]:
42-
if not network or self.disable_file_fixes:
42+
if not files or self.disable_file_fixes:
4343
return []
4444
# patterns that we don't need to specify a reason for
4545
empty_line_regex = re.compile(r"^\s*$")
@@ -94,7 +94,7 @@ def _produce_file_fixes_for_network(
9494
}
9595

9696
result = []
97-
for filename in network:
97+
for filename in files:
9898
for glob, fix_patterns in file_regex_patterns.items():
9999
if fnmatch(filename, glob):
100100
result.append(self._get_file_fixes(filename, fix_patterns))
@@ -150,9 +150,9 @@ def generate_upload_data(self, report_type="coverage") -> UploadCollectionResult
150150
prep.run_preparation(self)
151151
logger.debug("Collecting relevant files")
152152
network = self.network_finder.find_files()
153-
files = self.file_finder.find_files()
154-
logger.info(f"Found {len(files)} {report_type} files to upload")
155-
if not files:
153+
report_files = self.file_finder.find_files()
154+
logger.info(f"Found {len(report_files)} {report_type} files to report")
155+
if not report_files:
156156
if report_type == "test_results":
157157
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."
158158
else:
@@ -163,13 +163,13 @@ def generate_upload_data(self, report_type="coverage") -> UploadCollectionResult
163163
fg="red",
164164
)
165165
)
166-
for file in files:
166+
for file in report_files:
167167
logger.info(f"> {file}")
168168
return UploadCollectionResult(
169169
network=network,
170-
files=files,
170+
files=report_files,
171171
file_fixes=(
172-
self._produce_file_fixes_for_network(network)
172+
self._produce_file_fixes(self.network_finder.find_files(True))
173173
if report_type == "coverage"
174174
else []
175175
),

tests/commands/test_invoke_upload_process.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ def test_upload_process_options(mocker):
118118
" The type of the file to upload, coverage by",
119119
" default. Possible values are: testing,",
120120
" coverage.",
121+
" --network-filter TEXT Specify a filter on the files listed in the",
122+
" network section of the Codecov report. This",
123+
" will only add files whose path begin with the",
124+
" specified filter. Useful for upload-specific",
125+
" path fixing",
126+
" --network-prefix TEXT Specify a prefix on files listed in the",
127+
" network section of the Codecov report. Useful",
128+
" to help resolve path fixing",
121129
" --parent-sha TEXT SHA (with 40 chars) of what should be the",
122130
" parent of this commit",
123131
" -h, --help Show this message and exit.",

tests/helpers/test_network_finder.py

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,46 @@
66

77

88
def test_find_files(mocker, tmp_path):
9+
filenames = ["a.txt", "b.txt"]
10+
filtered_filenames = []
911

10-
expected_filenames = ["a.txt", "b.txt"]
12+
mocked_vs = MagicMock()
13+
mocked_vs.list_relevant_files.return_value = filenames
14+
15+
assert NetworkFinder(versioning_system=mocked_vs, network_filter=None, network_prefix=None, network_root_folder=tmp_path).find_files() == filenames
16+
assert NetworkFinder(versioning_system=mocked_vs, network_filter="hello", network_prefix="bello", network_root_folder=tmp_path).find_files(False) == filtered_filenames
17+
assert NetworkFinder(versioning_system=mocked_vs, network_filter="hello", network_prefix="bello", network_root_folder=tmp_path).find_files(True) == filenames
18+
mocked_vs.list_relevant_files.assert_called_with(tmp_path)
19+
20+
def test_find_files_with_filter(mocker, tmp_path):
21+
filenames = ["hello/a.txt", "hello/c.txt", "bello/b.txt"]
22+
filtered_filenames = ["hello/a.txt", "hello/c.txt"]
23+
24+
mocked_vs = MagicMock()
25+
mocked_vs.list_relevant_files.return_value = filenames
26+
27+
assert NetworkFinder(versioning_system=mocked_vs, network_filter="hello", network_prefix=None, network_root_folder=tmp_path).find_files() == filtered_filenames
28+
assert NetworkFinder(versioning_system=mocked_vs, network_filter="hello", network_prefix="bello", network_root_folder=tmp_path).find_files(True) == filenames
29+
mocked_vs.list_relevant_files.assert_called_with(tmp_path)
30+
31+
def test_find_files_with_prefix(mocker, tmp_path):
32+
filenames = ["hello/a.txt", "hello/c.txt", "bello/b.txt"]
33+
filtered_filenames = ["hellohello/a.txt", "hellohello/c.txt", "hellobello/b.txt"]
34+
35+
mocked_vs = MagicMock()
36+
mocked_vs.list_relevant_files.return_value = filenames
37+
38+
assert NetworkFinder(versioning_system=mocked_vs, network_filter=None, network_prefix="hello", network_root_folder=tmp_path).find_files() == filtered_filenames
39+
assert NetworkFinder(versioning_system=mocked_vs, network_filter="hello", network_prefix="bello", network_root_folder=tmp_path).find_files(True) == filenames
40+
mocked_vs.list_relevant_files.assert_called_with(tmp_path)
41+
42+
def test_find_files_with_filter_and_prefix(mocker, tmp_path):
43+
filenames = ["hello/a.txt", "hello/c.txt", "bello/b.txt"]
44+
filtered_filenames = ["bellohello/a.txt", "bellohello/c.txt"]
1145

1246
mocked_vs = MagicMock()
13-
mocked_vs.list_relevant_files.return_value = expected_filenames
47+
mocked_vs.list_relevant_files.return_value = filenames
1448

15-
assert NetworkFinder(mocked_vs).find_files(tmp_path) == expected_filenames
49+
assert NetworkFinder(versioning_system=mocked_vs, network_filter="hello", network_prefix="bello", network_root_folder=tmp_path).find_files() == filtered_filenames
50+
assert NetworkFinder(versioning_system=mocked_vs, network_filter="hello", network_prefix="bello", network_root_folder=tmp_path).find_files(True) == filenames
1651
mocked_vs.list_relevant_files.assert_called_with(tmp_path)

0 commit comments

Comments
 (0)