Skip to content

Commit c3ffced

Browse files
authored
CM-40908 - Implement NuGet restore support for SCA (#252)
1 parent 70d3cce commit c3ffced

File tree

7 files changed

+53
-17
lines changed

7 files changed

+53
-17
lines changed

cycode/cli/files_collector/sca/maven/base_restore_maven_dependencies.py renamed to cycode/cli/files_collector/sca/base_restore_dependencies.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import click
55

66
from cycode.cli.models import Document
7-
from cycode.cli.utils.path_utils import get_file_content, get_file_dir, join_paths
7+
from cycode.cli.utils.path_utils import get_file_content, get_file_dir, get_path_from_context, join_paths
88
from cycode.cli.utils.shell_executor import shell
99
from cycode.cyclient import logger
1010

@@ -23,7 +23,7 @@ def execute_command(command: List[str], file_name: str, command_timeout: int) ->
2323
return dependencies
2424

2525

26-
class BaseRestoreMavenDependencies(ABC):
26+
class BaseRestoreDependencies(ABC):
2727
def __init__(self, context: click.Context, is_git_diff: bool, command_timeout: int) -> None:
2828
self.context = context
2929
self.is_git_diff = is_git_diff
@@ -34,7 +34,7 @@ def restore(self, document: Document) -> Optional[Document]:
3434

3535
def get_manifest_file_path(self, document: Document) -> str:
3636
return (
37-
join_paths(self.context.params['paths'][0], document.path)
37+
join_paths(get_path_from_context(self.context), document.path)
3838
if self.context.obj.get('monitor')
3939
else document.path
4040
)

cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33

44
import click
55

6-
from cycode.cli.files_collector.sca.maven.base_restore_maven_dependencies import BaseRestoreMavenDependencies
6+
from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies
77
from cycode.cli.models import Document
88

99
BUILD_GRADLE_FILE_NAME = 'build.gradle'
1010
BUILD_GRADLE_KTS_FILE_NAME = 'build.gradle.kts'
1111
BUILD_GRADLE_DEP_TREE_FILE_NAME = 'gradle-dependencies-generated.txt'
1212

1313

14-
class RestoreGradleDependencies(BaseRestoreMavenDependencies):
14+
class RestoreGradleDependencies(BaseRestoreDependencies):
1515
def __init__(self, context: click.Context, is_git_diff: bool, command_timeout: int) -> None:
1616
super().__init__(context, is_git_diff, command_timeout)
1717

cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
import click
55

6-
from cycode.cli.files_collector.sca.maven.base_restore_maven_dependencies import (
7-
BaseRestoreMavenDependencies,
6+
from cycode.cli.files_collector.sca.base_restore_dependencies import (
7+
BaseRestoreDependencies,
88
build_dep_tree_path,
99
execute_command,
1010
)
@@ -16,7 +16,7 @@
1616
MAVEN_DEP_TREE_FILE_NAME = 'bcde.mvndeps'
1717

1818

19-
class RestoreMavenDependencies(BaseRestoreMavenDependencies):
19+
class RestoreMavenDependencies(BaseRestoreDependencies):
2020
def __init__(self, context: click.Context, is_git_diff: bool, command_timeout: int) -> None:
2121
super().__init__(context, is_git_diff, command_timeout)
2222

cycode/cli/files_collector/sca/nuget/__init__.py

Whitespace-only changes.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import os
2+
from typing import List
3+
4+
import click
5+
6+
from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies
7+
from cycode.cli.models import Document
8+
9+
NUGET_PROJECT_FILE_EXTENSIONS = ['.csproj', '.vbproj']
10+
NUGET_LOCK_FILE_NAME = 'packages.lock.json'
11+
12+
13+
class RestoreNugetDependencies(BaseRestoreDependencies):
14+
def __init__(self, context: click.Context, is_git_diff: bool, command_timeout: int) -> None:
15+
super().__init__(context, is_git_diff, command_timeout)
16+
17+
def is_project(self, document: Document) -> bool:
18+
return any(document.path.endswith(ext) for ext in NUGET_PROJECT_FILE_EXTENSIONS)
19+
20+
def get_command(self, manifest_file_path: str) -> List[str]:
21+
return ['dotnet', 'restore', manifest_file_path, '--use-lock-file', '--verbosity', 'quiet']
22+
23+
def get_lock_file_name(self) -> str:
24+
return NUGET_LOCK_FILE_NAME
25+
26+
def verify_restore_file_already_exist(self, restore_file_path: str) -> bool:
27+
return os.path.isfile(restore_file_path)

cycode/cli/files_collector/sca/sca_code_scanner.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,20 @@
44
import click
55

66
from cycode.cli import consts
7+
from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies
78
from cycode.cli.files_collector.sca.maven.restore_gradle_dependencies import RestoreGradleDependencies
89
from cycode.cli.files_collector.sca.maven.restore_maven_dependencies import RestoreMavenDependencies
10+
from cycode.cli.files_collector.sca.nuget.restore_nuget_dependencies import RestoreNugetDependencies
911
from cycode.cli.models import Document
1012
from cycode.cli.utils.git_proxy import git_proxy
11-
from cycode.cli.utils.path_utils import get_file_content, get_file_dir, join_paths
13+
from cycode.cli.utils.path_utils import get_file_content, get_file_dir, get_path_from_context, join_paths
1214
from cycode.cyclient import logger
1315

1416
if TYPE_CHECKING:
1517
from git import Repo
1618

17-
from cycode.cli.files_collector.sca.maven.base_restore_maven_dependencies import BaseRestoreMavenDependencies
18-
19-
BUILD_GRADLE_FILE_NAME = 'build.gradle'
20-
BUILD_GRADLE_KTS_FILE_NAME = 'build.gradle.kts'
21-
BUILD_GRADLE_DEP_TREE_FILE_NAME = 'gradle-dependencies-generated.txt'
2219
BUILD_GRADLE_DEP_TREE_TIMEOUT = 180
20+
BUILD_NUGET_DEP_TREE_TIMEOUT = 180
2321

2422

2523
def perform_pre_commit_range_scan_actions(
@@ -90,7 +88,7 @@ def get_project_file_ecosystem(document: Document) -> Optional[str]:
9088
def try_restore_dependencies(
9189
context: click.Context,
9290
documents_to_add: Dict[str, Document],
93-
restore_dependencies: 'BaseRestoreMavenDependencies',
91+
restore_dependencies: 'BaseRestoreDependencies',
9492
document: Document,
9593
) -> None:
9694
if restore_dependencies.is_project(document):
@@ -104,7 +102,9 @@ def try_restore_dependencies(
104102
restore_dependencies_document.content = ''
105103
else:
106104
is_monitor_action = context.obj['monitor']
107-
project_path = context.params['paths'][0]
105+
106+
project_path = get_path_from_context(context)
107+
108108
manifest_file_path = get_manifest_file_path(document, is_monitor_action, project_path)
109109
logger.debug('Succeeded to generate dependencies tree on path: %s', manifest_file_path)
110110

@@ -127,10 +127,11 @@ def add_dependencies_tree_document(
127127
documents_to_scan.extend(list(documents_to_add.values()))
128128

129129

130-
def restore_handlers(context: click.Context, is_git_diff: bool) -> List[RestoreGradleDependencies]:
130+
def restore_handlers(context: click.Context, is_git_diff: bool) -> List[BaseRestoreDependencies]:
131131
return [
132132
RestoreGradleDependencies(context, is_git_diff, BUILD_GRADLE_DEP_TREE_TIMEOUT),
133133
RestoreMavenDependencies(context, is_git_diff, BUILD_GRADLE_DEP_TREE_TIMEOUT),
134+
RestoreNugetDependencies(context, is_git_diff, BUILD_NUGET_DEP_TREE_TIMEOUT),
134135
]
135136

136137

cycode/cli/utils/path_utils.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from functools import lru_cache
44
from typing import AnyStr, List, Optional
55

6+
import click
67
from binaryornot.helpers import is_binary_string
78

89
from cycode.cyclient import logger
@@ -100,3 +101,10 @@ def concat_unique_id(filename: str, unique_id: str) -> str:
100101
filename = filename[len(os.sep) :]
101102

102103
return os.path.join(unique_id, filename)
104+
105+
106+
def get_path_from_context(context: click.Context) -> Optional[str]:
107+
path = context.params.get('path')
108+
if path is None and 'paths' in context.params:
109+
path = context.params['paths'][0]
110+
return path

0 commit comments

Comments
 (0)