Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CM-40908 - Implement NuGet restore support for SCA #252

Merged
merged 8 commits into from
Oct 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
import click

from cycode.cli.models import Document
from cycode.cli.utils.path_utils import get_file_content, get_file_dir, join_paths
from cycode.cli.utils.path_utils import get_file_content, get_file_dir, get_path_from_context, join_paths
from cycode.cli.utils.shell_executor import shell
from cycode.cyclient import logger

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


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

def get_manifest_file_path(self, document: Document) -> str:
return (
join_paths(self.context.params['paths'][0], document.path)
join_paths(get_path_from_context(self.context), document.path)
if self.context.obj.get('monitor')
else document.path
)
Original file line number Diff line number Diff line change
@@ -3,15 +3,15 @@

import click

from cycode.cli.files_collector.sca.maven.base_restore_maven_dependencies import BaseRestoreMavenDependencies
from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies
from cycode.cli.models import Document

BUILD_GRADLE_FILE_NAME = 'build.gradle'
BUILD_GRADLE_KTS_FILE_NAME = 'build.gradle.kts'
BUILD_GRADLE_DEP_TREE_FILE_NAME = 'gradle-dependencies-generated.txt'


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

Original file line number Diff line number Diff line change
@@ -3,8 +3,8 @@

import click

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


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

Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os
from typing import List

import click

from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies
from cycode.cli.models import Document

NUGET_PROJECT_FILE_EXTENSIONS = ['.csproj', '.vbproj']
NUGET_LOCK_FILE_NAME = 'packages.lock.json'


class RestoreNugetDependencies(BaseRestoreDependencies):
def __init__(self, context: click.Context, is_git_diff: bool, command_timeout: int) -> None:
super().__init__(context, is_git_diff, command_timeout)

def is_project(self, document: Document) -> bool:
return any(document.path.endswith(ext) for ext in NUGET_PROJECT_FILE_EXTENSIONS)

def get_command(self, manifest_file_path: str) -> List[str]:
return ['dotnet', 'restore', manifest_file_path, '--use-lock-file', '--verbosity', 'quiet']

def get_lock_file_name(self) -> str:
return NUGET_LOCK_FILE_NAME

def verify_restore_file_already_exist(self, restore_file_path: str) -> bool:
return os.path.isfile(restore_file_path)
19 changes: 10 additions & 9 deletions cycode/cli/files_collector/sca/sca_code_scanner.py
Original file line number Diff line number Diff line change
@@ -4,22 +4,20 @@
import click

from cycode.cli import consts
from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies
from cycode.cli.files_collector.sca.maven.restore_gradle_dependencies import RestoreGradleDependencies
from cycode.cli.files_collector.sca.maven.restore_maven_dependencies import RestoreMavenDependencies
from cycode.cli.files_collector.sca.nuget.restore_nuget_dependencies import RestoreNugetDependencies
from cycode.cli.models import Document
from cycode.cli.utils.git_proxy import git_proxy
from cycode.cli.utils.path_utils import get_file_content, get_file_dir, join_paths
from cycode.cli.utils.path_utils import get_file_content, get_file_dir, get_path_from_context, join_paths
from cycode.cyclient import logger

if TYPE_CHECKING:
from git import Repo

from cycode.cli.files_collector.sca.maven.base_restore_maven_dependencies import BaseRestoreMavenDependencies

BUILD_GRADLE_FILE_NAME = 'build.gradle'
BUILD_GRADLE_KTS_FILE_NAME = 'build.gradle.kts'
BUILD_GRADLE_DEP_TREE_FILE_NAME = 'gradle-dependencies-generated.txt'
BUILD_GRADLE_DEP_TREE_TIMEOUT = 180
BUILD_NUGET_DEP_TREE_TIMEOUT = 180


def perform_pre_commit_range_scan_actions(
@@ -90,7 +88,7 @@ def get_project_file_ecosystem(document: Document) -> Optional[str]:
def try_restore_dependencies(
context: click.Context,
documents_to_add: Dict[str, Document],
restore_dependencies: 'BaseRestoreMavenDependencies',
restore_dependencies: 'BaseRestoreDependencies',
document: Document,
) -> None:
if restore_dependencies.is_project(document):
@@ -104,7 +102,9 @@ def try_restore_dependencies(
restore_dependencies_document.content = ''
else:
is_monitor_action = context.obj['monitor']
project_path = context.params['paths'][0]

project_path = get_path_from_context(context)

manifest_file_path = get_manifest_file_path(document, is_monitor_action, project_path)
logger.debug('Succeeded to generate dependencies tree on path: %s', manifest_file_path)

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


def restore_handlers(context: click.Context, is_git_diff: bool) -> List[RestoreGradleDependencies]:
def restore_handlers(context: click.Context, is_git_diff: bool) -> List[BaseRestoreDependencies]:
return [
RestoreGradleDependencies(context, is_git_diff, BUILD_GRADLE_DEP_TREE_TIMEOUT),
RestoreMavenDependencies(context, is_git_diff, BUILD_GRADLE_DEP_TREE_TIMEOUT),
RestoreNugetDependencies(context, is_git_diff, BUILD_NUGET_DEP_TREE_TIMEOUT),
]


8 changes: 8 additions & 0 deletions cycode/cli/utils/path_utils.py
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
from functools import lru_cache
from typing import AnyStr, List, Optional

import click
from binaryornot.helpers import is_binary_string

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

return os.path.join(unique_id, filename)


def get_path_from_context(context: click.Context) -> Optional[str]:
path = context.params.get('path')
if path is None and 'paths' in context.params:
path = context.params['paths'][0]
return path