From 44c0c084f806cedc5c7dc16f40b7fd83bfa3ead7 Mon Sep 17 00:00:00 2001 From: soonhong99 <67502252+soonhong99@users.noreply.github.com> Date: Sat, 21 Sep 2024 02:20:42 +0900 Subject: [PATCH 01/10] feat: Add Docker support for -p and -o options, and create Windows executable for easier volume mounting * refactor: Update Dockerfile to handle -p and -o options without errors * feat: Implement fosslight_wrapper.py to simplify Docker volume mounting process * ci: Add GitHub Actions workflow to create Windows executable using PyInstaller on release Signed-off-by: soonhong99 <67502252+soonhong99@users.noreply.github.com> --- .github/workflows/docker-release.yml | 62 +++++++++ Dockerfile | 69 ++++++++-- entrypoint.sh | 16 +++ fosslight_wrapper.py | 195 +++++++++++++++++++++++++++ 4 files changed, 333 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/docker-release.yml create mode 100644 entrypoint.sh create mode 100644 fosslight_wrapper.py diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml new file mode 100644 index 0000000..243e6bb --- /dev/null +++ b/.github/workflows/docker-release.yml @@ -0,0 +1,62 @@ +name: Docker Build and Push + +on: + release: + types: [published] + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + tags: | + nanayah99/fosslight_scanner:latest + nanayah99/fosslight_scanner:${{ github.event.release.tag_name }} + + create-windows-executable: + runs-on: windows-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.9' + + - name: Install dependencies + run: | + pip install pyinstaller + + - name: Create executable + run: pyinstaller --onefile fosslight_wrapper.py + + - name: Upload executable to release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./dist/fosslight_wrapper.exe + asset_name: fosslight_wrapper.exe + asset_content_type: application/vnd.microsoft.portable-executable \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 35f15eb..e683b19 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,23 +3,74 @@ FROM python:3.8-slim-buster COPY . /app -WORKDIR /app +WORKDIR /app -RUN ln -sf /bin/bash /bin/sh && \ +# Install necessary packages including nodejs, npm, and default-jdk +RUN ln -sf /bin/bash /bin/sh && \ apt-get update && \ - apt-get install --no-install-recommends -y \ + apt-get install --no-install-recommends -y \ build-essential \ python3 python3-distutils python3-pip python3-dev python3-magic \ libxml2-dev \ libxslt1-dev \ libhdf5-dev \ - bzip2 xz-utils zlib1g libpopt0 && \ + bzip2 xz-utils zlib1g libpopt0 \ + curl \ + default-jdk && \ + curl -sL https://deb.nodesource.com/setup_14.x | bash - && \ + apt-get install -y nodejs && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* -RUN pip3 install --upgrade pip && \ - pip3 install . && \ - pip3 install dparse && \ - rm -rf ~/.cache/pip /root/.cache/pipe +# Set JAVA_HOME dynamically +RUN echo "export JAVA_HOME=\$(dirname \$(dirname \$(readlink -f \$(which java))))" >> /etc/profile && \ + echo "export PATH=\$JAVA_HOME/bin:\$PATH" >> /etc/profile -ENTRYPOINT ["/usr/local/bin/fosslight"] +# Install license-checker globally +RUN npm install -g license-checker + +RUN pip3 install --upgrade pip && \ + pip3 install fosslight_util && \ + pip3 install python-magic && \ + pip3 install dparse + +RUN pip3 install fosslight_source --no-deps && \ + pip3 show fosslight_source | grep "Requires:" | sed 's/Requires://' | tr ',' '\n' | grep -v "typecode-libmagic" > /tmp/fosslight_source_deps.txt && \ + pip3 install -r /tmp/fosslight_source_deps.txt && \ + rm /tmp/fosslight_source_deps.txt + +COPY requirements.txt /tmp/requirements.txt +RUN grep -vE "fosslight[-_]source" /tmp/requirements.txt > /tmp/custom_requirements.txt && \ + pip3 install -r /tmp/custom_requirements.txt && \ + rm /tmp/requirements.txt /tmp/custom_requirements.txt + +COPY . /fosslight_scanner +WORKDIR /fosslight_scanner +RUN pip3 install . --no-deps && \ + rm -rf ~/.cache/pip /root/.cache/pip + +# Add /usr/local/bin to the PATH +ENV PATH="/usr/local/bin:${PATH}" + +VOLUME /src +WORKDIR /src + +# Create and set up the entrypoint script +RUN echo '#!/bin/bash' > /entrypoint.sh && \ + echo 'source /etc/profile' >> /entrypoint.sh && \ + echo 'export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))' >> /entrypoint.sh && \ + echo 'export PATH=$JAVA_HOME/bin:$PATH' >> /entrypoint.sh && \ + echo 'if command -v "$1" > /dev/null 2>&1; then' >> /entrypoint.sh && \ + echo ' exec "$@"' >> /entrypoint.sh && \ + echo 'else' >> /entrypoint.sh && \ + echo ' exec fosslight "$@"' >> /entrypoint.sh && \ + echo 'fi' >> /entrypoint.sh && \ + chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] + +CMD ["-h"] + +# Clean up the build +RUN apt-get clean && \ + rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..ecf2ec0 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Copyright (c) 2022 LG Electronics Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Set JAVA_HOME dynamically +export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java)))) +export PATH=$JAVA_HOME/bin:$PATH + +# Check if the first argument is a command, if so execute it +if command -v "$1" > /dev/null 2>&1; then + exec "$@" +else + # If not a command, run fosslight with arguments + exec fosslight "$@" +fi \ No newline at end of file diff --git a/fosslight_wrapper.py b/fosslight_wrapper.py new file mode 100644 index 0000000..dd90b2f --- /dev/null +++ b/fosslight_wrapper.py @@ -0,0 +1,195 @@ +import sys +import io +import subprocess +import logging +from datetime import datetime + +def setup_logging(): + current_time = datetime.now().strftime("%Y%m%d_%H%M") + log_filename = f'fosslight_log_{current_time}.txt' + logging.basicConfig(filename=log_filename, level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + encoding='utf-8') + +def get_user_input(): + print("FossLight Wrapper") + image = input("Enter Docker image name (e.g., fosslight/fosslight): ") + + analysis_type = input("Choose analysis type (1 for local path, 2 for Git repository): ") + + if analysis_type == '1': + input_path = input("Enter local path to analyze: ") + return image, 'local', input_path + elif analysis_type == '2': + git_url = input("Enter Git repository URL to analyze: ") + return image, 'git', git_url + else: + print("Invalid choice. Exiting.") + sys.exit(1) + +def display_current_options(options): + if not options: + print("Only the default option has been applied.") + else: + print("Current additional options:") + for i, option in enumerate(options, 1): + print(f"{i}. {option}") + +def get_additional_options(): + options = [] + while True: + print("\nManage additional options:") + print("1. Add new option") + print("2. Remove option") + print("3. View current options") + print("4. Finish and proceed") + + choice = input("\nEnter your choice (1-4): ") + + if choice == '1': + options.extend(add_option()) + elif choice == '2': + options = remove_option(options) + elif choice == '3': + display_current_options(options) + elif choice == '4': + break + else: + print("Invalid choice. Please try again.") + + return options + +def add_option(): + print("\nAvailable additional options:") + print("1. -f : FOSSLight Report file format (excel, yaml)") + print("2. -c : Number of processes to analyze source") + print("3. -r: Keep raw data") + print("4. -t: Hide the progress bar") + print("5. -s : Path to apply setting from file") + print("6. --no_correction: Don't correct OSS information") + print("7. --correct_fpath : Path to the sbom-info.yaml file") + print("8. -u : DB Connection (for 'all' or 'bin' mode)") + print("9. -d : Additional arguments for dependency analysis") + + choice = input("\nEnter the number of the option you want to add: ") + + if choice == '1': + format_type = input("Enter format (excel/yaml): ") + return ['-f', format_type] + elif choice == '2': + processes = input("Enter number of processes: ") + return ['-c', processes] + elif choice == '3': + return ['-r'] + elif choice == '4': + return ['-t'] + elif choice == '5': + settings_path = input("Enter path to settings file: ") + return ['-s', settings_path] + elif choice == '6': + return ['--no_correction'] + elif choice == '7': + sbom_path = input("Enter path to sbom-info.yaml: ") + return ['--correct_fpath', sbom_path] + elif choice == '8': + db_url = input("Enter DB URL: ") + return ['-u', db_url] + elif choice == '9': + dep_arg = input("Enter dependency argument: ") + return ['-d', dep_arg] + else: + print("Invalid option. No option added.") + return [] + +def remove_option(options): + if not options: + print("No options to remove.") + return options + + display_current_options(options) + choice = input("Enter the number of the option you want to remove (or 0 to cancel): ") + + try: + index = int(choice) - 1 + if 0 <= index < len(options): + removed_option = options.pop(index) + print(f"Removed option: {removed_option}") + elif index == -1: + print("Removal cancelled.") + else: + print("Invalid number. No option removed.") + except ValueError: + print("Invalid input. No option removed.") + + return options + +def run_fosslight(image, analysis_type, input_source, output_path, additional_options): + # Convert Windows paths to Docker-compatible paths + output_path = output_path.replace('\\', '/').replace('C:', '/c') + + # Construct the Docker command + docker_cmd = [ + "docker", "run", "--rm", + "-v", f"{output_path}:/output", + image, + "fosslight", + "all", + "-o", "/output" + ] + + if analysis_type == 'local': + input_path = input_source.replace('\\', '/').replace('C:', '/c') + docker_cmd.extend(["-v", f"{input_path}:/src", "-p", "/src"]) + else: # Git repository + docker_cmd.extend(["-w", input_source]) + + # Add additional options + docker_cmd.extend(additional_options) + + # Log the Docker command + logging.info(f"Running Docker command: {' '.join(docker_cmd)}") + + # Run the Docker command with real-time output and UTF-8 encoding + try: + process = subprocess.Popen(docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True, encoding='utf-8') + for line in process.stdout: + line = line.strip() + if line: # Only log non-empty lines + print(line) # Print to console in real-time + sys.stdout.flush() # Ensure real-time output + logging.info(line) # Log to file + process.wait() + if process.returncode != 0: + logging.error(f"FossLight exited with error code {process.returncode}") + else: + logging.info("FossLight completed successfully") + except subprocess.CalledProcessError as e: + logging.error(f"Error running FossLight: {e}") + except Exception as e: + logging.error(f"Unexpected error: {e}") + +def main(): + # Redirect stdout to use utf-8 encoding without buffering + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', line_buffering=True) + + setup_logging() + + image, analysis_type, input_source = get_user_input() + output_path = input("Enter path for output: ") + + additional_options = get_additional_options() + + logging.info("Starting FossLight wrapper") + logging.info(f"Docker image: {image}") + logging.info(f"Analysis type: {analysis_type}") + logging.info(f"Input source: {input_source}") + logging.info(f"Output path: {output_path}") + logging.info(f"Additional options: {' '.join(additional_options)}") + + run_fosslight(image, analysis_type, input_source, output_path, additional_options) + + print("\nFossLight wrapper completed. Press Enter to exit.") + input() + +if __name__ == "__main__": + main() \ No newline at end of file From 1650f657b5bbf57740b7a4c70566ba8c0a8ffd78 Mon Sep 17 00:00:00 2001 From: soonhong99 <67502252+soonhong99@users.noreply.github.com> Date: Sat, 21 Sep 2024 02:28:08 +0900 Subject: [PATCH 02/10] fix: error of github reuse Signed-off-by: soonhong99 <67502252+soonhong99@users.noreply.github.com> --- fosslight_wrapper.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fosslight_wrapper.py b/fosslight_wrapper.py index dd90b2f..3f56293 100644 --- a/fosslight_wrapper.py +++ b/fosslight_wrapper.py @@ -1,3 +1,6 @@ +# Copyright (c) 2022 LG Electronics Inc. +# SPDX-License-Identifier: Apache-2.0 + import sys import io import subprocess From 3621f30f2dedc726e3c2e5164f992186c582ae2b Mon Sep 17 00:00:00 2001 From: soonhong99 <67502252+soonhong99@users.noreply.github.com> Date: Sat, 21 Sep 2024 02:39:10 +0900 Subject: [PATCH 03/10] fix: flake8 error Signed-off-by: soonhong99 <67502252+soonhong99@users.noreply.github.com> --- fosslight_wrapper.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/fosslight_wrapper.py b/fosslight_wrapper.py index 3f56293..129288e 100644 --- a/fosslight_wrapper.py +++ b/fosslight_wrapper.py @@ -7,6 +7,7 @@ import logging from datetime import datetime + def setup_logging(): current_time = datetime.now().strftime("%Y%m%d_%H%M") log_filename = f'fosslight_log_{current_time}.txt' @@ -14,12 +15,13 @@ def setup_logging(): format='%(asctime)s - %(levelname)s - %(message)s', encoding='utf-8') + def get_user_input(): print("FossLight Wrapper") image = input("Enter Docker image name (e.g., fosslight/fosslight): ") - + analysis_type = input("Choose analysis type (1 for local path, 2 for Git repository): ") - + if analysis_type == '1': input_path = input("Enter local path to analyze: ") return image, 'local', input_path @@ -30,6 +32,7 @@ def get_user_input(): print("Invalid choice. Exiting.") sys.exit(1) + def display_current_options(options): if not options: print("Only the default option has been applied.") @@ -38,6 +41,7 @@ def display_current_options(options): for i, option in enumerate(options, 1): print(f"{i}. {option}") + def get_additional_options(): options = [] while True: @@ -62,6 +66,7 @@ def get_additional_options(): return options + def add_option(): print("\nAvailable additional options:") print("1. -f : FOSSLight Report file format (excel, yaml)") @@ -104,6 +109,7 @@ def add_option(): print("Invalid option. No option added.") return [] + def remove_option(options): if not options: print("No options to remove.") @@ -111,7 +117,7 @@ def remove_option(options): display_current_options(options) choice = input("Enter the number of the option you want to remove (or 0 to cancel): ") - + try: index = int(choice) - 1 if 0 <= index < len(options): @@ -126,6 +132,7 @@ def remove_option(options): return options + def run_fosslight(image, analysis_type, input_source, output_path, additional_options): # Convert Windows paths to Docker-compatible paths output_path = output_path.replace('\\', '/').replace('C:', '/c') @@ -154,7 +161,8 @@ def run_fosslight(image, analysis_type, input_source, output_path, additional_op # Run the Docker command with real-time output and UTF-8 encoding try: - process = subprocess.Popen(docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True, encoding='utf-8') + process = subprocess.Popen(docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + bufsize=1, universal_newlines=True, encoding='utf-8') for line in process.stdout: line = line.strip() if line: # Only log non-empty lines @@ -171,6 +179,7 @@ def run_fosslight(image, analysis_type, input_source, output_path, additional_op except Exception as e: logging.error(f"Unexpected error: {e}") + def main(): # Redirect stdout to use utf-8 encoding without buffering sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', line_buffering=True) @@ -194,5 +203,6 @@ def main(): print("\nFossLight wrapper completed. Press Enter to exit.") input() + if __name__ == "__main__": - main() \ No newline at end of file + main() From abd6283b5919fc598fd79bac6499e8caf41583e8 Mon Sep 17 00:00:00 2001 From: soonhong99 <67502252+soonhong99@users.noreply.github.com> Date: Sat, 28 Sep 2024 20:52:33 +0900 Subject: [PATCH 04/10] fix: Renaming files for consistency Signed-off-by: soonhong99 <67502252+soonhong99@users.noreply.github.com> --- .github/workflows/{docker-release.yml => docker-build-push.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{docker-release.yml => docker-build-push.yml} (100%) diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-build-push.yml similarity index 100% rename from .github/workflows/docker-release.yml rename to .github/workflows/docker-build-push.yml From d8c8b851d8bd5d9b0058f0e418481f7c72281aec Mon Sep 17 00:00:00 2001 From: soonhong99 <67502252+soonhong99@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:38:52 +0900 Subject: [PATCH 05/10] fix: docker image name nanayah99 to fosslight Signed-off-by: soonhong99 <67502252+soonhong99@users.noreply.github.com> --- .github/workflows/docker-build-push.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml index 243e6bb..5ef77e0 100644 --- a/.github/workflows/docker-build-push.yml +++ b/.github/workflows/docker-build-push.yml @@ -30,8 +30,8 @@ jobs: push: true platforms: linux/amd64,linux/arm64 tags: | - nanayah99/fosslight_scanner:latest - nanayah99/fosslight_scanner:${{ github.event.release.tag_name }} + fosslight/fosslight_scanner:latest + fosslight/fosslight_scanner:${{ github.event.release.tag_name }} create-windows-executable: runs-on: windows-latest From 70145f0948195d984226ec62f928efb22f5d5341 Mon Sep 17 00:00:00 2001 From: soonhong99 Date: Fri, 4 Oct 2024 16:48:35 +0900 Subject: [PATCH 06/10] Add Mac OS support and .app creation in GitHub Actions Signed-off-by: soonhong99 --- .github/workflows/docker-build-push.yml | 39 ++++++++- fosslight_wrapper.py | 106 ++++++++++++++++++++---- 2 files changed, 128 insertions(+), 17 deletions(-) diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml index 67dcb99..65f5dbd 100644 --- a/.github/workflows/docker-build-push.yml +++ b/.github/workflows/docker-build-push.yml @@ -30,8 +30,9 @@ jobs: push: true platforms: linux/amd64,linux/arm64 tags: | - fosslight/fosslight_scanner:latest - fosslight/fosslight_scanner:${{ github.event.release.tag_name }} + # nanayah99 -> fosslight 수정 필요 + nanayah99/fosslight_scanner:latest + nanayah99/fosslight_scanner:${{ github.event.release.tag_name }} create-windows-executable: runs-on: windows-latest @@ -60,3 +61,37 @@ jobs: asset_path: ./dist/fosslight_wrapper.exe asset_name: fosslight_wrapper.exe asset_content_type: application/vnd.microsoft.portable-executable + + create-macos-app: + runs-on: macos-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.9' + + - name: Install dependencies + run: | + pip install pyinstaller + + - name: Create .app bundle + run: | + pyinstaller --windowed --name "FossLight Wrapper" --add-data "fosslight_wrapper.py:." fosslight_wrapper.py + + - name: Compress .app to .zip + run: | + cd dist + zip -r FossLight_Wrapper.zip "FossLight Wrapper.app" + + - name: Upload .app bundle to release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./dist/FossLight_Wrapper.zip + asset_name: FossLight_Wrapper_macOS.zip + asset_content_type: application/zip \ No newline at end of file diff --git a/fosslight_wrapper.py b/fosslight_wrapper.py index 129288e..8d8c274 100644 --- a/fosslight_wrapper.py +++ b/fosslight_wrapper.py @@ -6,6 +6,8 @@ import subprocess import logging from datetime import datetime +import os +import platform def setup_logging(): @@ -16,10 +18,34 @@ def setup_logging(): encoding='utf-8') -def get_user_input(): - print("FossLight Wrapper") - image = input("Enter Docker image name (e.g., fosslight/fosslight): ") +def is_double_clicked(): + return (sys.argv[0].endswith('.exe') and len(sys.argv) == 1) or \ + (sys.argv[0].endswith('.app') and len(sys.argv) == 2 and sys.argv[1] == '-psn_0_0') + + +def check_and_pull_image(image_name): + try: + result = subprocess.run(["docker", "image", "inspect", image_name], + capture_output=True, text=True) + if result.returncode == 0: + logging.info(f"Image {image_name} already exists locally.") + return True + + logging.info(f"Pulling the image {image_name} from Docker Hub") + subprocess.run(["docker", "pull", image_name], check=True) + logging.info(f"Successfully pulled the image {image_name}") + return True + except subprocess.CalledProcessError as e: + logging.error(f"Error with Docker image {image_name}: {e}") + return False + +def get_user_input(auto_image=None): + if auto_image: + return auto_image, 'local', os.getcwd() + + print("FossLight Wrapper") + image = input("Enter Docker image name (e.g., fosslight/fosslight_scanner:latest): ") analysis_type = input("Choose analysis type (1 for local path, 2 for Git repository): ") if analysis_type == '1': @@ -133,23 +159,44 @@ def remove_option(options): return options +def remove_wfp_file(output_path): + wfp_file = os.path.join(output_path, "scanner_output.wfp") + if os.path.exists(wfp_file): + try: + os.remove(wfp_file) + logging.info(f"Successfully removed WFP file: {wfp_file}") + except Exception as e: + logging.error(f"Failed to remove WFP file: {wfp_file}. Error: {e}") + + def run_fosslight(image, analysis_type, input_source, output_path, additional_options): - # Convert Windows paths to Docker-compatible paths - output_path = output_path.replace('\\', '/').replace('C:', '/c') + # Convert paths to Docker-compatible paths based on OS + if platform.system() == 'Windows': + output_path = output_path.replace('\\', '/').replace('C:', '/c') + if analysis_type == 'local': + input_source = input_source.replace('\\', '/').replace('C:', '/c') + elif platform.system() == 'Darwin': # macOS + output_path = output_path.replace('/Volumes/', '/').replace(' ', '\ ') + if analysis_type == 'local': + input_source = input_source.replace('/Volumes/', '/').replace(' ', '\ ') # Construct the Docker command docker_cmd = [ "docker", "run", "--rm", - "-v", f"{output_path}:/output", + "-v", f"{output_path}:/output" + ] + + if analysis_type == 'local': + docker_cmd.extend(["-v", f"{input_source}:/src"]) + + docker_cmd.extend([ image, "fosslight", - "all", - "-o", "/output" - ] + "-o", "/output", + ]) if analysis_type == 'local': - input_path = input_source.replace('\\', '/').replace('C:', '/c') - docker_cmd.extend(["-v", f"{input_path}:/src", "-p", "/src"]) + docker_cmd.extend(["-p", "/src"]) else: # Git repository docker_cmd.extend(["-w", input_source]) @@ -179,6 +226,16 @@ def run_fosslight(image, analysis_type, input_source, output_path, additional_op except Exception as e: logging.error(f"Unexpected error: {e}") + remove_wfp_file(output_path) + + +def get_execution_mode(): + if platform.system() == 'Darwin' and sys.argv[0].endswith('.app'): + return "auto" + elif len(sys.argv) > 1 and sys.argv[1] == "--manual": + return "manual" + return "auto" + def main(): # Redirect stdout to use utf-8 encoding without buffering @@ -186,10 +243,29 @@ def main(): setup_logging() - image, analysis_type, input_source = get_user_input() - output_path = input("Enter path for output: ") + execution_mode = get_execution_mode() + + if execution_mode == "auto": + logging.info("Executing in automatic mode") + # nanayah99 -> fosslight 수정 필요 + image_name = "nanayah99/fosslight_scanner:latest" + if not check_and_pull_image(image_name): + print(f"Failed to ensure the presence of the Docker image: {image_name}") + input("Press Enter to exit...") + sys.exit(1) + + current_dir = os.getcwd() + image, analysis_type, input_source = image_name, 'local', current_dir + output_path = current_dir + additional_options = ["-f", "excel"] + else: + logging.info("Executing in manual mode") + image, analysis_type, input_source = get_user_input() + output_path = input("Enter path for output: ") + additional_options = get_additional_options() - additional_options = get_additional_options() + # Ensure no duplicate options + additional_options = list(dict.fromkeys(additional_options)) logging.info("Starting FossLight wrapper") logging.info(f"Docker image: {image}") @@ -205,4 +281,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file From 084f3948ed9b669a8e69380a2302c43b0f3e4bb4 Mon Sep 17 00:00:00 2001 From: soonhong99 Date: Fri, 4 Oct 2024 16:53:51 +0900 Subject: [PATCH 07/10] fix: syntax error Signed-off-by: soonhong99 --- .github/workflows/docker-build-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml index 65f5dbd..1697914 100644 --- a/.github/workflows/docker-build-push.yml +++ b/.github/workflows/docker-build-push.yml @@ -30,7 +30,7 @@ jobs: push: true platforms: linux/amd64,linux/arm64 tags: | - # nanayah99 -> fosslight 수정 필요 + # nanayah99 -> fosslight 수정 필요 nanayah99/fosslight_scanner:latest nanayah99/fosslight_scanner:${{ github.event.release.tag_name }} From a69e319b1ddbbd09e5356e4c732fd6e95744fc6f Mon Sep 17 00:00:00 2001 From: soonhong99 Date: Sat, 5 Oct 2024 00:37:17 +0900 Subject: [PATCH 08/10] feat: add mac os command to execute Signed-off-by: soonhong99 --- .github/workflows/docker-build-push.yml | 36 ++---- fosslight_wrapper.py | 31 ++---- .../fosslight_wrapper_mac.command | 104 ++++++++++++++++++ 3 files changed, 126 insertions(+), 45 deletions(-) create mode 100755 src/fosslight_scanner/fosslight_wrapper_mac.command diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml index 1697914..9d457e1 100644 --- a/.github/workflows/docker-build-push.yml +++ b/.github/workflows/docker-build-push.yml @@ -30,9 +30,8 @@ jobs: push: true platforms: linux/amd64,linux/arm64 tags: | - # nanayah99 -> fosslight 수정 필요 - nanayah99/fosslight_scanner:latest - nanayah99/fosslight_scanner:${{ github.event.release.tag_name }} + fosslight/fosslight_scanner:latest + fosslight/fosslight_scanner:${{ github.event.release.tag_name }} create-windows-executable: runs-on: windows-latest @@ -62,36 +61,23 @@ jobs: asset_name: fosslight_wrapper.exe asset_content_type: application/vnd.microsoft.portable-executable - create-macos-app: - runs-on: macos-latest + create-macos-command-file: + runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.9' - - - name: Install dependencies - run: | - pip install pyinstaller - - - name: Create .app bundle - run: | - pyinstaller --windowed --name "FossLight Wrapper" --add-data "fosslight_wrapper.py:." fosslight_wrapper.py - - - name: Compress .app to .zip + - name: Create .command file run: | - cd dist - zip -r FossLight_Wrapper.zip "FossLight Wrapper.app" + cp fosslight_wrapper_mac.sh fosslight_wrapper_mac.command + chmod +x fosslight_wrapper_mac.command - - name: Upload .app bundle to release + - name: Upload .command file to release uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ github.event.release.upload_url }} - asset_path: ./dist/FossLight_Wrapper.zip - asset_name: FossLight_Wrapper_macOS.zip - asset_content_type: application/zip \ No newline at end of file + asset_path: ./fosslight_wrapper_mac.command + asset_name: fosslight_wrapper_mac.command + asset_content_type: application/x-sh \ No newline at end of file diff --git a/fosslight_wrapper.py b/fosslight_wrapper.py index 8d8c274..264862f 100644 --- a/fosslight_wrapper.py +++ b/fosslight_wrapper.py @@ -7,7 +7,6 @@ import logging from datetime import datetime import os -import platform def setup_logging(): @@ -19,18 +18,19 @@ def setup_logging(): def is_double_clicked(): - return (sys.argv[0].endswith('.exe') and len(sys.argv) == 1) or \ - (sys.argv[0].endswith('.app') and len(sys.argv) == 2 and sys.argv[1] == '-psn_0_0') + return sys.argv[0].endswith('.exe') and len(sys.argv) == 1 def check_and_pull_image(image_name): try: + # Check if the image exists locally result = subprocess.run(["docker", "image", "inspect", image_name], capture_output=True, text=True) if result.returncode == 0: logging.info(f"Image {image_name} already exists locally.") return True + # If the image doesn't exist, pull it logging.info(f"Pulling the image {image_name} from Docker Hub") subprocess.run(["docker", "pull", image_name], check=True) logging.info(f"Successfully pulled the image {image_name}") @@ -170,15 +170,8 @@ def remove_wfp_file(output_path): def run_fosslight(image, analysis_type, input_source, output_path, additional_options): - # Convert paths to Docker-compatible paths based on OS - if platform.system() == 'Windows': - output_path = output_path.replace('\\', '/').replace('C:', '/c') - if analysis_type == 'local': - input_source = input_source.replace('\\', '/').replace('C:', '/c') - elif platform.system() == 'Darwin': # macOS - output_path = output_path.replace('/Volumes/', '/').replace(' ', '\ ') - if analysis_type == 'local': - input_source = input_source.replace('/Volumes/', '/').replace(' ', '\ ') + # Convert Windows paths to Docker-compatible paths + output_path = output_path.replace('\\', '/').replace('C:', '/c') # Construct the Docker command docker_cmd = [ @@ -187,7 +180,8 @@ def run_fosslight(image, analysis_type, input_source, output_path, additional_op ] if analysis_type == 'local': - docker_cmd.extend(["-v", f"{input_source}:/src"]) + input_path = input_source.replace('\\', '/').replace('C:', '/c') + docker_cmd.extend(["-v", f"{input_path}:/src"]) docker_cmd.extend([ image, @@ -230,9 +224,7 @@ def run_fosslight(image, analysis_type, input_source, output_path, additional_op def get_execution_mode(): - if platform.system() == 'Darwin' and sys.argv[0].endswith('.app'): - return "auto" - elif len(sys.argv) > 1 and sys.argv[1] == "--manual": + if len(sys.argv) > 1 and sys.argv[1] == "--manual": return "manual" return "auto" @@ -246,9 +238,8 @@ def main(): execution_mode = get_execution_mode() if execution_mode == "auto": - logging.info("Executing in automatic mode") - # nanayah99 -> fosslight 수정 필요 - image_name = "nanayah99/fosslight_scanner:latest" + logging.info("Executing in automatic mode (double-click)") + image_name = "fosslight/fosslight_scanner:latest" if not check_and_pull_image(image_name): print(f"Failed to ensure the presence of the Docker image: {image_name}") input("Press Enter to exit...") @@ -259,7 +250,7 @@ def main(): output_path = current_dir additional_options = ["-f", "excel"] else: - logging.info("Executing in manual mode") + logging.info("Executing in manual mode (command prompt)") image, analysis_type, input_source = get_user_input() output_path = input("Enter path for output: ") additional_options = get_additional_options() diff --git a/src/fosslight_scanner/fosslight_wrapper_mac.command b/src/fosslight_scanner/fosslight_wrapper_mac.command new file mode 100755 index 0000000..ae9ec75 --- /dev/null +++ b/src/fosslight_scanner/fosslight_wrapper_mac.command @@ -0,0 +1,104 @@ +#!/bin/bash + +# Copyright (c) 2022 LG Electronics Inc. +# SPDX-License-Identifier: Apache-2.0 + +# FossLight Wrapper Shell Script + +# Get the directory of the script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Default values +IMAGE="fosslight/fosslight_scanner:latest" +OUTPUT_DIR="$SCRIPT_DIR/fosslight_output" +MANUAL_MODE=false + +# Function to check if running in terminal +is_running_in_terminal() { + [ -t 0 ] +} + +# Function to pause execution (for GUI mode) +pause() { + if ! is_running_in_terminal; then + echo "Press Enter to exit..." + read + fi +} + +# Function to check and pull Docker image +check_and_pull_image() { + if ! docker image inspect "$IMAGE" &> /dev/null; then + echo "Pulling image $IMAGE..." + if ! docker pull "$IMAGE"; then + echo "Failed to pull image $IMAGE" + exit 1 + fi + fi +} + +# Function to get user input in manual mode +get_user_input() { + echo "FossLight Wrapper (Manual Mode)" + read -p "Choose analysis type (1 for local path, 2 for Git repository): " analysis_type + if [ "$analysis_type" == "1" ]; then + read -p "Enter local path to analyze: " input_source + analysis_type="local" + elif [ "$analysis_type" == "2" ]; then + read -p "Enter Git repository URL to analyze: " input_source + analysis_type="git" + else + echo "Invalid choice. Exiting." + exit 1 + fi + read -p "Enter path for output (default: $OUTPUT_DIR): " user_output + OUTPUT_DIR=${user_output:-$OUTPUT_DIR} +} + +# Function to run FossLight +run_fosslight() { + local docker_cmd="docker run --rm" + + if [ "$analysis_type" == "local" ]; then + docker_cmd="$docker_cmd -v $input_source:/src -v $OUTPUT_DIR:/output" + docker_cmd="$docker_cmd $IMAGE fosslight -p /src -o /output -f excel" + else + docker_cmd="$docker_cmd -v $OUTPUT_DIR:/output" + docker_cmd="$docker_cmd $IMAGE fosslight -o /output -w $input_source -f excel" + fi + + echo "Running FossLight..." + if ! eval $docker_cmd; then + echo "Error running FossLight" + exit 1 + fi +} + +# Main execution +if [ "$1" == "--manual" ]; then + MANUAL_MODE=true +fi + +if [ "$MANUAL_MODE" = true ]; then + get_user_input +else + echo "FossLight Wrapper (Automatic Mode)" + analysis_type="local" + input_source="$SCRIPT_DIR" + echo "Analyzing directory: $input_source" +fi + +# Ensure output directory exists +mkdir -p "$OUTPUT_DIR" + +# Change to the script directory +cd "$SCRIPT_DIR" + +# Check and pull Docker image +check_and_pull_image + +# Run FossLight +run_fosslight + +echo "FossLight analysis completed. Results are in $OUTPUT_DIR" +pause \ No newline at end of file From 9601fa42a3e98032247fc372d7a57cca2e7d49f7 Mon Sep 17 00:00:00 2001 From: soonhong99 Date: Sat, 5 Oct 2024 00:42:46 +0900 Subject: [PATCH 09/10] fix: error with docker build yml Signed-off-by: soonhong99 --- .github/workflows/docker-build-push.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml index 9d457e1..8cc5eb3 100644 --- a/.github/workflows/docker-build-push.yml +++ b/.github/workflows/docker-build-push.yml @@ -69,7 +69,6 @@ jobs: - name: Create .command file run: | - cp fosslight_wrapper_mac.sh fosslight_wrapper_mac.command chmod +x fosslight_wrapper_mac.command - name: Upload .command file to release From c85f7ce280bb14ac7fc5e0bbf270f4662e3de70d Mon Sep 17 00:00:00 2001 From: soonhong99 Date: Sat, 5 Oct 2024 00:44:53 +0900 Subject: [PATCH 10/10] fix: error with docker build yml 2 Signed-off-by: soonhong99 --- ...fosslight_wrapper_mac.command => fosslight_wrapper_mac.command | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/fosslight_scanner/fosslight_wrapper_mac.command => fosslight_wrapper_mac.command (100%) diff --git a/src/fosslight_scanner/fosslight_wrapper_mac.command b/fosslight_wrapper_mac.command similarity index 100% rename from src/fosslight_scanner/fosslight_wrapper_mac.command rename to fosslight_wrapper_mac.command