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

Incorporate ScanCode into CI for OSS compliance #183

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
21 changes: 20 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,30 @@ jobs:
- name: Run cppcheck
run: |
docker run --rm --volume $(pwd):/note-c/ --workdir /note-c/ --entrypoint ./scripts/run_cppcheck.sh ghcr.io/blues/note_c_ci:latest

run_scancode:
runs-on: ubuntu-latest
if: ${{ always() }}
needs: [build_ci_docker_image]

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Load CI Docker image
# Only load the Docker image artifact if build_ci_docker_image actually
# ran (e.g. it wasn't skipped and was successful).
if: ${{ needs.build_ci_docker_image.result == 'success' }}
uses: ./.github/actions/load-ci-image

- name: Run license compliance check
run: |
docker run --rm --volume $(pwd):/note-c/ --workdir /note-c/ --entrypoint ./scripts/run_scancode.sh ghcr.io/blues/note_c_ci:latest

publish_ci_image:
runs-on: ubuntu-latest
# Make sure unit tests unit tests passed before publishing.
needs: [build_ci_docker_image, run_unit_tests]
needs: [build_ci_docker_image, run_unit_tests, run_scancode]
# Only publish the image if this is a push event and the Docker image was rebuilt
if: ${{ github.event_name == 'push' && needs.build_ci_docker_image.result == 'success' }}

Expand Down
14 changes: 14 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,19 @@
],
"group": "test"
}
,
{
"label": "Note-C: Run License Compliance Check",
"type": "shell",
"command": "${workspaceFolder}/scripts/run_scancode.sh",
"options": {
"cwd": "${workspaceFolder}",
"env": {
"LC_ALL": "C"
}
},
"problemMatcher": [],
"group": "test"
}
]
}
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ RUN ["dash", "-c", "\
&& pip install --break-system-packages \
breathe \
sphinx-rtd-theme \
scancode-toolkit \
&& apt-get clean \
&& apt-get purge \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
Expand Down
103 changes: 103 additions & 0 deletions scripts/run_scancode.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/bin/bash
set -eo pipefail

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
SRC_DIR="$SCRIPT_DIR/.."

echo "Running License Compliance Analysis..."
echo

# Create a function to generate the summary
generate_summary() {
{
# Initialize flag
has_critical_issues=false

echo

# Always generate and display summary regardless of exit code
echo "=== License Compliance Summary ==="
echo

# Display license information
echo "License Information:"
echo "-------------------"
jq -r '.summary.declared_license_expression' scancode_output.json || echo "None found"
echo

# Display license clarity score
echo "License Clarity Score:"
echo "---------------------"
jq -r '.summary.license_clarity_score.score' scancode_output.json || echo "Not available"
echo

# Display other licenses found
echo "Other Licenses Found:"
echo "--------------------"
jq -r '.summary.other_license_expressions[] | select(.value != null) | "\(.value): \(.count) occurrences"' scancode_output.json || echo "None found"
echo

# Display copyright holders
echo "Copyright Holders:"
echo "-----------------"
jq -r '.tallies.holders[] | select(.value != null) | "\(.value): \(.count) occurrences"' scancode_output.json || echo "None found"
echo

# Check for non-compliant licenses
echo "License Compliance Issues:"
echo "-------------------------"
# List of non-compliant or problematic licenses
problematic_licenses=("gpl-2.0" "gpl-3.0" "agpl-3.0" "cc-by-nc" "proprietary")

found_problematic=false
for license in "${problematic_licenses[@]}"; do
count=$(jq -r ".summary.other_license_expressions[] | select(.value == \"$license\") | .count" scancode_output.json 2>/dev/null || echo "0")
if [ "$count" != "0" ] && [ "$count" != "" ]; then
echo "WARNING: Found $count occurrences of $license license, which may have compliance implications."
found_problematic=true
has_critical_issues=true
fi
done

if ! $found_problematic; then
echo "No problematic licenses found."
fi
echo

# Display status and details
if $has_critical_issues; then
echo "Status: FAILED - License compliance issues found"
echo
echo "Review and fix license compliance issues before proceeding"
else
echo "Status: PASSED - No license compliance issues found"
echo
echo "Note: Review license information for potential improvements"
fi
}

# Return 1 if critical issues found, 0 otherwise
if $has_critical_issues; then
return 1
else
return 0
fi
}

# Run scancode and capture output and exit code
scancode \
--license \
--copyright \
--classify \
--summary \
--license-clarity-score \
--tallies \
--json-pp scancode_output.json \
--timeout 120 \
--processes 2 \
. 2>&1 | tee scancode_console_output.txt

generate_summary

# Exit with scancode's status code
exit $?
Loading