diff --git a/.github/workflows/map-deploy-to-develop-template.yml b/.github/workflows/map-deploy-to-develop-template.yml index 6951a8b..0bcd89f 100644 --- a/.github/workflows/map-deploy-to-develop-template.yml +++ b/.github/workflows/map-deploy-to-develop-template.yml @@ -22,6 +22,14 @@ jobs: contents: read steps: + - name: Checkout the action from the current branch + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: action.yml + sparse-checkout-cone-mode: false + path: scancode-action + persist-credentials: false + - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -32,19 +40,19 @@ jobs: uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: ${{ inputs['artifact-name'] }} - path: ../scancode-inputs/ + path: scancode-inputs/ - name: Prepare D2D inputs shell: bash run: | - for file in ../scancode-inputs/*; do + for file in scancode-inputs/*; do base=$(basename "$file") - mv "$file" "../scancode-inputs/to_$base" + mv "$file" "scancode-inputs/to_$base" done - git archive --format=tar.gz -o ../scancode-inputs/from.tar.gz HEAD + git archive --format=tar.gz -o scancode-inputs/from.tar.gz HEAD - name: Run D2D pipeline - uses: aboutcode-org/scancode-action@main + uses: ./scancode-action with: pipelines: ${{ inputs.steps && format('map_deploy_to_develop:%s', inputs.steps) || 'map_deploy_to_develop' }} - inputs-path: ../scancode-inputs + inputs-path: scancode-inputs diff --git a/.github/workflows/map-source-binary-boolean-py.yml b/.github/workflows/map-source-binary-boolean-py.yml index 694b195..83664b6 100644 --- a/.github/workflows/map-source-binary-boolean-py.yml +++ b/.github/workflows/map-source-binary-boolean-py.yml @@ -1,47 +1,58 @@ -name: Run source to binary mapping on boolean.py +# Replace the whl build step by pre-built file -on: - workflow_dispatch: - pull_request: - push: - branches: - - main - -jobs: - build-python-wheel: - name: Build python wheel - runs-on: ubuntu-24.04 - permissions: - contents: read - - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: bastikr/boolean.py - persist-credentials: false - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: 3.12 - - - name: Install pypa/build and twine - run: python -m pip install --user --upgrade build twine packaging pip setuptools - - - name: Build a binary wheel - run: python -m build --wheel --outdir dist/ - - - name: Upload wheel - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 - with: - name: wheel_archives - path: dist/*.whl - - map-source-binary: - name: Generate source to binary mapping - needs: build-python-wheel - uses: ./.github/workflows/map-deploy-to-develop-template.yml - with: - artifact-name: wheel_archives - repository: bastikr/boolean.py - steps: "python" \ No newline at end of file +#name: Run source to binary mapping on boolean.py +# +#on: +# workflow_dispatch: +# pull_request: +# push: +# branches: +# - main +# +#jobs: +# build-python-wheel: +# name: Build python wheel +# runs-on: ubuntu-24.04 +# permissions: +# contents: read +# +# steps: +# - name: Checkout repository +# uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 +# with: +# repository: ${{ inputs.repository || github.repository }} +# persist-credentials: false +# +# - name: Checkout the action from the current branch +# uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 +# with: +# sparse-checkout: action.yml +# sparse-checkout-cone-mode: false +# path: scancode-action +# persist-credentials: false +# +# - name: Set up Python +# uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 +# with: +# python-version: 3.12 +# +# - name: Install pypa/build and twine +# run: python -m pip install --user --upgrade build twine packaging pip setuptools +# +# - name: Build a binary wheel +# run: python -m build --wheel --outdir dist/ +# +# - name: Upload wheel +# uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 +# with: +# name: wheel_archives +# path: dist/*.whl +# +# map-source-binary: +# name: Generate source to binary mapping +# needs: build-python-wheel +# uses: ./.github/workflows/map-deploy-to-develop-template.yml +# with: +# artifact-name: wheel_archives +# repository: bastikr/boolean.py +# steps: "python" diff --git a/action.yml b/action.yml index 26cedc5..b319b20 100644 --- a/action.yml +++ b/action.yml @@ -52,31 +52,33 @@ inputs: runs: using: "composite" steps: - - uses: actions/setup-python@v5 + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ inputs.python-version }} - name: Set up environment shell: bash + env: + INPUT_PROJECT_NAME: ${{ inputs.project-name }} run: | - echo "SECRET_KEY=$(openssl rand -base64 32)" >> $GITHUB_ENV - echo "SCANCODEIO_DB_NAME=scancodeio" >> $GITHUB_ENV - echo "SCANCODEIO_DB_USER=scancodeio" >> $GITHUB_ENV - echo "SCANCODEIO_DB_PASSWORD=scancodeio" >> $GITHUB_ENV + echo "SECRET_KEY=$(openssl rand -base64 32)" >> "$GITHUB_ENV" + echo "SCANCODEIO_DB_NAME=scancodeio" >> "$GITHUB_ENV" + echo "SCANCODEIO_DB_USER=scancodeio" >> "$GITHUB_ENV" + echo "SCANCODEIO_DB_PASSWORD=scancodeio" >> "$GITHUB_ENV" # Sanitize project name for artifact usage - SAFE_PROJECT_NAME="${{ inputs.project-name }}" - SAFE_PROJECT_NAME="${SAFE_PROJECT_NAME//[^a-zA-Z0-9._-]/_}" - echo "SAFE_PROJECT_NAME=$SAFE_PROJECT_NAME" >> $GITHUB_ENV + SAFE_PROJECT_NAME="${INPUT_PROJECT_NAME//[^a-zA-Z0-9._-]/_}" + echo "SAFE_PROJECT_NAME=$SAFE_PROJECT_NAME" >> "$GITHUB_ENV" - name: Detect if ScanCode.io is already installed shell: bash run: | if command -v scanpipe &> /dev/null; then echo "ScanCode.io already installed." - echo "SCANCODEIO_IS_INSTALLED=true" >> $GITHUB_ENV + echo "SCANCODEIO_IS_INSTALLED=true" >> "$GITHUB_ENV" else echo "ScanCode.io not found." - echo "SCANCODEIO_IS_INSTALLED=false" >> $GITHUB_ENV + echo "SCANCODEIO_IS_INSTALLED=false" >> "$GITHUB_ENV" fi - name: Start and setup the PostgreSQL service @@ -84,31 +86,35 @@ runs: shell: bash run: | sudo systemctl start postgresql.service - sudo -u postgres createuser --no-createrole --no-superuser --login --inherit --createdb ${{ env.SCANCODEIO_DB_USER }} - sudo -u postgres psql -c "ALTER USER ${{ env.SCANCODEIO_DB_USER }} WITH ENCRYPTED PASSWORD '${{ env.SCANCODEIO_DB_PASSWORD }}'" - sudo -u postgres createdb --owner=scancodeio --encoding=UTF-8 ${{ env.SCANCODEIO_DB_NAME }} + sudo -u postgres createuser --no-createrole --no-superuser --login --inherit --createdb "$SCANCODEIO_DB_USER" + sudo -u postgres psql -c "ALTER USER $SCANCODEIO_DB_USER WITH ENCRYPTED PASSWORD '$SCANCODEIO_DB_PASSWORD'" + sudo -u postgres createdb --owner=scancodeio --encoding=UTF-8 "$SCANCODEIO_DB_NAME" - name: Generate scancodeio pip install argument if: env.SCANCODEIO_IS_INSTALLED != 'true' shell: bash + env: + INPUT_EXTRAS: ${{ inputs.scancodeio-extras }} run: | SCANCODEIO_PIP_PACKAGE_ARG="scancodeio" - TRIMMED_EXTRAS="$(echo "${{ inputs.scancodeio-extras }}" | tr -d '[:space:]')" + TRIMMED_EXTRAS="$(echo "$INPUT_EXTRAS" | tr -d '[:space:]')" if [ -n "$TRIMMED_EXTRAS" ]; then SCANCODEIO_PIP_PACKAGE_ARG+="[$TRIMMED_EXTRAS]" fi - echo "SCANCODEIO_PIP_PACKAGE_ARG=${SCANCODEIO_PIP_PACKAGE_ARG}" >> $GITHUB_ENV + echo "SCANCODEIO_PIP_PACKAGE_ARG=${SCANCODEIO_PIP_PACKAGE_ARG}" >> "$GITHUB_ENV" - name: Install ScanCode.io (only if not already installed) if: env.SCANCODEIO_IS_INSTALLED != 'true' shell: bash + env: + INPUT_REPO_BRANCH: ${{ inputs.scancodeio-repo-branch }} run: | - if [ -z "${{ inputs.scancodeio-repo-branch }}" ]; then - echo "Installing the latest ${{ env.SCANCODEIO_PIP_PACKAGE_ARG }} release from PyPI" - pip install --upgrade "${{ env.SCANCODEIO_PIP_PACKAGE_ARG }}" + if [ -z "$INPUT_REPO_BRANCH" ]; then + echo "Installing the latest ${SCANCODEIO_PIP_PACKAGE_ARG} release from PyPI" + pip install --upgrade "$SCANCODEIO_PIP_PACKAGE_ARG" else - echo "Installing ${{ env.SCANCODEIO_PIP_PACKAGE_ARG }} from the GitHub branch: ${{ inputs.scancodeio-repo-branch }}" - pip install "${{ env.SCANCODEIO_PIP_PACKAGE_ARG }} @ git+https://github.com/aboutcode-org/scancode.io.git@${{ inputs.scancodeio-repo-branch }}" + echo "Installing ${SCANCODEIO_PIP_PACKAGE_ARG} from the GitHub branch: $INPUT_REPO_BRANCH" + pip install "${SCANCODEIO_PIP_PACKAGE_ARG} @ git+https://github.com/aboutcode-org/scancode.io.git@${INPUT_REPO_BRANCH}" fi - name: Run migrations to prepare the database @@ -118,55 +124,79 @@ runs: - name: Generate `--pipeline` CLI arguments shell: bash + env: + INPUT_PIPELINES: ${{ inputs.pipelines }} run: | - IFS=',' read -ra PIPELINES <<< "${{ inputs.pipelines }}" + IFS=',' read -ra PIPELINES <<< "$INPUT_PIPELINES" PIPELINE_CLI_ARGS="" for pipeline in "${PIPELINES[@]}"; do PIPELINE_CLI_ARGS+=" --pipeline $pipeline" done - echo "PIPELINE_CLI_ARGS=${PIPELINE_CLI_ARGS}" >> $GITHUB_ENV + echo "PIPELINE_CLI_ARGS=${PIPELINE_CLI_ARGS}" >> "$GITHUB_ENV" - name: Generate `--input-url` CLI arguments shell: bash + env: + INPUT_URLS: ${{ inputs.input-urls }} run: | INPUT_URL_CLI_ARGS="" - for url in ${{ inputs.input-urls }}; do - INPUT_URL_CLI_ARGS+=" --input-url $url" + for url in $INPUT_URLS; do + if [[ "$url" =~ ^(https?|docker|pkg): ]]; then + INPUT_URL_CLI_ARGS+=" --input-url $url" + else + echo "::warning::Skipping unsupported URL scheme: $url" + fi done - echo "INPUT_URL_CLI_ARGS=${INPUT_URL_CLI_ARGS}" >> $GITHUB_ENV + echo "INPUT_URL_CLI_ARGS=${INPUT_URL_CLI_ARGS}" >> "$GITHUB_ENV" - name: Create project shell: bash + env: + INPUT_PROJECT_NAME: ${{ inputs.project-name }} run: | - scanpipe create-project ${{ inputs.project-name }} \ - ${{ env.PIPELINE_CLI_ARGS }} \ - ${{ env.INPUT_URL_CLI_ARGS }} + scanpipe create-project "$INPUT_PROJECT_NAME" \ + $PIPELINE_CLI_ARGS \ + $INPUT_URL_CLI_ARGS - name: Set project work directory in the environment shell: bash + env: + INPUT_PROJECT_NAME: ${{ inputs.project-name }} run: | - project_status=$(scanpipe status --project ${{ inputs.project-name }}) + project_status=$(scanpipe status --project "$INPUT_PROJECT_NAME") work_directory=$(echo "$project_status" | grep -oP 'Work directory:\s*\K[^\n]+') - echo "PROJECT_WORK_DIRECTORY=$work_directory" >> $GITHUB_ENV + echo "PROJECT_WORK_DIRECTORY=$work_directory" >> "$GITHUB_ENV" - name: Copy input files to project work directory if: ${{ !inputs.input-urls }} shell: bash + env: + INPUT_INPUTS_PATH: ${{ inputs.inputs-path }} + WORKSPACE: ${{ github.workspace }} run: | - SOURCE_PATH="${{ inputs.inputs-path }}" - [[ "$SOURCE_PATH" != /* ]] && SOURCE_PATH="${{ github.workspace }}/$SOURCE_PATH" - DESTINATION_PATH="${{ env.PROJECT_WORK_DIRECTORY }}/input/" + SOURCE_PATH="$INPUT_INPUTS_PATH" + [[ "$SOURCE_PATH" != /* ]] && SOURCE_PATH="${WORKSPACE}/$SOURCE_PATH" + + # Prevent path traversal outside the workspace + REAL_SOURCE=$(realpath -m "$SOURCE_PATH") + REAL_WORKSPACE=$(realpath "$WORKSPACE") + if [[ "$REAL_SOURCE" != "$REAL_WORKSPACE"* ]]; then + echo "::error::inputs-path resolves outside the workspace. Aborting." + exit 1 + fi + + DESTINATION_PATH="${PROJECT_WORK_DIRECTORY}/input/" mkdir -p "$DESTINATION_PATH" if [ -d "$SOURCE_PATH" ]; then if [ "$(ls -A "$SOURCE_PATH")" ]; then - echo "Copying contents of directory: $SOURCE_PATH → $DESTINATION_PATH" + echo "Copying contents of directory: $SOURCE_PATH -> $DESTINATION_PATH" cp -r "$SOURCE_PATH"/* "$DESTINATION_PATH" else echo "Input directory '$SOURCE_PATH' is empty, nothing to copy." fi elif [[ -f "$SOURCE_PATH" ]]; then - echo "Copying file: $SOURCE_PATH → $DESTINATION_PATH" + echo "Copying file: $SOURCE_PATH -> $DESTINATION_PATH" cp "$SOURCE_PATH" "$DESTINATION_PATH" fi @@ -176,17 +206,23 @@ runs: - name: Run the pipelines shell: bash - run: scanpipe execute --project ${{ inputs.project-name }} --no-color + env: + INPUT_PROJECT_NAME: ${{ inputs.project-name }} + run: scanpipe execute --project "$INPUT_PROJECT_NAME" --no-color - name: Generate outputs id: scanpipe shell: bash - run: scanpipe output - --project ${{ inputs.project-name }} - --format ${{ inputs.output-formats }} + env: + INPUT_PROJECT_NAME: ${{ inputs.project-name }} + INPUT_OUTPUT_FORMATS: ${{ inputs.output-formats }} + run: | + scanpipe output \ + --project "$INPUT_PROJECT_NAME" \ + --format $INPUT_OUTPUT_FORMATS - name: Upload outputs - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 id: artifact-upload-step with: # Include the project name in case of multiple runs of the action @@ -197,13 +233,19 @@ runs: - name: Check compliance if: inputs.check-compliance == 'true' shell: bash + env: + INPUT_PROJECT_NAME: ${{ inputs.project-name }} + INPUT_FAIL_LEVEL: ${{ inputs.compliance-fail-level }} + INPUT_FAIL_ON_VULNS: ${{ inputs.compliance-fail-on-vulnerabilities }} run: | - cmd="scanpipe check-compliance \ - --project ${{ inputs.project-name }} \ - --fail-level ${{ inputs.compliance-fail-level }}" - - if [[ "${{ inputs.compliance-fail-on-vulnerabilities }}" == "true" ]]; then - cmd="$cmd --fail-on-vulnerabilities" + cmd=( + scanpipe check-compliance + --project "$INPUT_PROJECT_NAME" + --fail-level "$INPUT_FAIL_LEVEL" + ) + + if [[ "$INPUT_FAIL_ON_VULNS" == "true" ]]; then + cmd+=(--fail-on-vulnerabilities) fi - eval "$cmd" + "${cmd[@]}"