Skip to content
Draft
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ dependencies = [
"pyyaml",
"beautifulsoup4",
"fosslight_util>=2.2.2,<3.0.0",
"fosslight_source>=2.2.16,<3.0.0",
"fosslight_source>=2.3.5,<3.0.0",
"fosslight_dependency>=4.1.31,<5.0.0",
"fosslight_binary>=5.1.17,<6.0.0",
]
Expand Down
39 changes: 29 additions & 10 deletions src/fosslight_scanner/fosslight_scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import logging
import warnings
import shutil
import shlex
import subprocess
import platform
from pathlib import Path
Expand Down Expand Up @@ -75,6 +74,29 @@ def _all_exclude_mode_for_scanner(
)


def _build_source_docker_command(
output_dir, path_to_scan, path_to_exclude=None,
kb_url="", kb_token="", ui_mode=False):
"""Build docker argv for fosslight_source fallback when the package is not installed."""
command = [
"docker", "run", "-it",
"-v", f"{output_dir}:/app/output",
"fosslight",
"-p", path_to_scan,
"-o", "output",
]
if path_to_exclude:
command.append("-e")
command.extend(path_to_exclude)
if kb_url:
command.extend(["--kb_url", kb_url])
if kb_token:
command.extend(["--kb_token", kb_token])
if ui_mode:
command.append("--ui")
return command


def run_dependency(path_to_analyze, output_file_with_path, params="", path_to_exclude=[], formats=[],
recursive_dep=False, all_exclude_mode=()):
result = []
Expand Down Expand Up @@ -140,13 +162,14 @@ def source_analysis_wrapper(*args, **kwargs):
kb_url = kwargs.pop('kb_url', '')
kb_token = kwargs.pop('kb_token', '')
formats = kwargs.pop('formats', [])
ui_mode = kwargs.pop('ui_mode', False)
args = list(args)
args.insert(2, source_write_json_file)
args.insert(5, source_print_matched_text)
args.insert(6, formats)

return source_analysis(*args, selected_scanner=selected_scanner, time_out=source_time_out,
kb_url=kb_url, kb_token=kb_token, **kwargs)
kb_url=kb_url, kb_token=kb_token, ui_mode=ui_mode, **kwargs)


def run_scanner(src_path, dep_arguments, output_path, keep_raw_data=False,
Expand Down Expand Up @@ -241,6 +264,7 @@ def run_scanner(src_path, dep_arguments, output_path, keep_raw_data=False,
kb_url=kb_url,
kb_token=kb_token,
formats=formats,
ui_mode=ui_mode,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
all_exclude_mode=_all_exclude_mode_for_scanner(
excluded_path_with_default_exclusion,
excluded_path_without_dot,
Expand All @@ -253,14 +277,9 @@ def run_scanner(src_path, dep_arguments, output_path, keep_raw_data=False,

else: # Run fosslight_source by using docker image
output_rel_path = os.path.relpath(abs_path, os.getcwd())
command = shlex.quote(f"docker run -it -v {_output_dir}:/app/output "
f"fosslight -p {output_rel_path} -o output")
if path_to_exclude:
command += f" -e {' '.join(path_to_exclude)}"
if kb_url:
command += f" --kb_url {shlex.quote(kb_url)}"
if kb_token:
command += f" --kb_token {shlex.quote(kb_token)}"
command = _build_source_docker_command(
_output_dir, output_rel_path, path_to_exclude,
kb_url, kb_token, ui_mode)
command_result = subprocess.run(command, stdout=subprocess.PIPE, text=True)
logger.info(f"Source Analysis Result:{command_result.stdout}")

Expand Down
88 changes: 87 additions & 1 deletion tests/test_fosslight_scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
import openpyxl
import pytest
from pathlib import Path
from fosslight_scanner.fosslight_scanner import run_scanner, download_source, init, run_main, run_dependency
from fosslight_scanner.fosslight_scanner import (
run_scanner, download_source, init, run_main, run_dependency,
_build_source_docker_command,
)
from fosslight_util.oss_item import ScannerItem
from fosslight_util.constant import FOSSLIGHT_BINARY, FOSSLIGHT_DEPENDENCY, FOSSLIGHT_SOURCE, SHEET_NAME_FOR_SCANNER

Expand Down Expand Up @@ -42,6 +45,89 @@ def _get_sheet_row_count(xlsx_path: str, sheet_name: str) -> int:
return row_count


def test_build_source_docker_command_includes_ui_and_optional_args():
command = _build_source_docker_command(
output_dir="/tmp/out",
path_to_scan="src",
path_to_exclude=["vendor", "third_party"],
kb_url="http://kb.example",
kb_token="secret",
ui_mode=True,
)

assert command[:3] == ["docker", "run", "-it"]
assert command[3:5] == ["-v", "/tmp/out:/app/output"]
assert "fosslight" in command
assert command[command.index("-p") + 1] == "src"
assert command[command.index("-o") + 1] == "output"
e_idx = command.index("-e")
assert command[e_idx + 1:e_idx + 3] == ["vendor", "third_party"]
assert command[command.index("--kb_url") + 1] == "http://kb.example"
assert command[command.index("--kb_token") + 1] == "secret"
assert command[-1] == "--ui"


def test_build_source_docker_command_omits_optional_args_by_default():
command = _build_source_docker_command("/tmp/out", "src")

assert "-e" not in command
assert "--kb_url" not in command
assert "--kb_token" not in command
assert "--ui" not in command


def test_run_scanner_docker_fallback_passes_argv_and_ui(monkeypatch, tmp_path):
import subprocess
import fosslight_scanner.fosslight_scanner as scanner_mod

monkeypatch.setattr(scanner_mod, "fosslight_source_installed", False)
monkeypatch.setattr(scanner_mod, "_output_dir", "fosslight_raw_data")

captured = {}

def fake_run(cmd, **kwargs):
captured["cmd"] = cmd
captured["kwargs"] = kwargs
return subprocess.CompletedProcess(cmd, 0, stdout="docker-ok", stderr="")

monkeypatch.setattr(scanner_mod.subprocess, "run", fake_run)

src_path = tmp_path / "test_src"
output_path = tmp_path / "output"
src_path.mkdir(parents=True, exist_ok=True)
output_path.mkdir(parents=True, exist_ok=True)
(src_path / "test_file.py").write_text("print('hi')\n")

run_scanner(
src_path=str(src_path),
dep_arguments="",
output_path=str(output_path),
keep_raw_data=True,
run_src=True,
run_bin=False,
run_dep=False,
remove_src_data=False,
result_log={},
output_files=["test_output"],
output_extensions=[".yaml"],
num_cores=1,
ui_mode=True,
path_to_exclude=["vendor"],
kb_url="http://kb.example",
kb_token="secret",
)

assert "cmd" in captured, "Docker fallback should call subprocess.run"
cmd = captured["cmd"]
assert isinstance(cmd, list), "Docker command must be passed as an argv list"
assert cmd[0] == "docker"
assert "--ui" in cmd
assert cmd[cmd.index("--kb_url") + 1] == "http://kb.example"
assert cmd[cmd.index("--kb_token") + 1] == "secret"
assert "vendor" in cmd
assert captured["kwargs"].get("text") is True


def test_run_dependency(tmp_path):
# given
path_to_analyze = tmp_path / "test_project"
Expand Down
Loading