Initial public release #10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Copyright (c) 2026 Santander Group | |
| # SPDX-License-Identifier: Apache-2.0 | |
| # | |
| # License compliance: dependency-license allowlist + SPDX header verification. | |
| name: License check | |
| on: | |
| push: | |
| branches: [main, development] | |
| pull_request: | |
| permissions: | |
| contents: read | |
| jobs: | |
| dep-licenses: | |
| name: Dependency license allowlist | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| - name: Set up Python | |
| uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 | |
| with: | |
| python-version: "3.12" | |
| cache: pip | |
| - name: Install project + pip-licenses | |
| run: | | |
| python -m pip install --upgrade pip | |
| # Install the CPU-only torch build (pulled transitively via pgmpy) so | |
| # we don't pull NVIDIA CUDA wheels (proprietary licences) that are | |
| # irrelevant to this library. | |
| pip install torch --index-url https://download.pytorch.org/whl/cpu | |
| pip install -e "." | |
| pip install pip-licenses==5.0.0 | |
| - name: Verify all dependency licenses are in allowlist | |
| run: | | |
| pip-licenses --format=json > /tmp/licenses.json | |
| python - <<'PY' | |
| import json | |
| import re | |
| import sys | |
| # Canonical allowlist of OSI-approved permissive licences. | |
| ALLOWED = { | |
| "Apache Software License", "Apache 2.0", "Apache-2.0", | |
| "MIT License", "MIT", | |
| "BSD License", "BSD-3-Clause", "BSD-2-Clause", "BSD", | |
| "Mozilla Public License 2.0 (MPL 2.0)", "MPL-2.0", | |
| "Python Software Foundation License", "PSF-2.0", | |
| "The Unlicense (Unlicense)", "Unlicense", | |
| "ISC License (ISCL)", "ISC", | |
| } | |
| # Manual overrides for packages whose metadata reports UNKNOWN but | |
| # whose licence is publicly verified. Add a justification per entry. | |
| KNOWN_GOOD = { | |
| "numpy": "BSD-3-Clause (verified at https://github.com/numpy/numpy/blob/main/LICENSE.txt)", | |
| "scipy": "BSD-3-Clause (verified at https://github.com/scipy/scipy/blob/main/LICENSE.txt)", | |
| "scikit-learn": "BSD-3-Clause (verified at https://github.com/scikit-learn/scikit-learn/blob/main/COPYING)", | |
| "joblib": "BSD-3-Clause (verified at https://github.com/joblib/joblib/blob/main/LICENSE.txt)", | |
| "pgmpy": "MIT (verified at https://github.com/pgmpy/pgmpy/blob/dev/LICENSE)", | |
| "pandas": "BSD-3-Clause (verified at https://github.com/pandas-dev/pandas/blob/main/LICENSE)", | |
| "pyarrow": "Apache-2.0 (verified at https://github.com/apache/arrow/blob/main/LICENSE.txt)", | |
| # torch and its transitive deps (pulled via pgmpy). | |
| "torch": "BSD-3-Clause (verified at https://github.com/pytorch/pytorch/blob/main/LICENSE)", | |
| "tqdm": "MPL-2.0 AND MIT (verified at https://github.com/tqdm/tqdm/blob/master/LICENCE)", | |
| "sympy": "BSD-3-Clause (verified at https://github.com/sympy/sympy/blob/master/LICENSE)", | |
| "mpmath": "BSD-3-Clause (verified at https://github.com/mpmath/mpmath/blob/master/LICENSE)", | |
| "filelock": "Unlicense (verified at https://github.com/tox-dev/filelock/blob/main/LICENSE)", | |
| "networkx": "BSD-3-Clause (verified at https://github.com/networkx/networkx/blob/main/LICENSE.txt)", | |
| "fsspec": "BSD-3-Clause (verified at https://github.com/fsspec/filesystem_spec/blob/master/LICENSE)", | |
| "MarkupSafe": "BSD-3-Clause (verified at https://github.com/pallets/markupsafe/blob/main/LICENSE.txt)", | |
| "typing_extensions": "PSF-2.0 (verified at https://github.com/python/typing_extensions/blob/main/LICENSE)", | |
| "Jinja2": "BSD-3-Clause (verified at https://github.com/pallets/jinja/blob/main/LICENSE.txt)", | |
| "narwhals": "MIT (verified at https://github.com/narwhals-dev/narwhals/blob/main/LICENSE.md)", | |
| "packaging": "Apache-2.0 OR BSD-2-Clause (verified at https://github.com/pypa/packaging/blob/main/LICENSE)", | |
| } | |
| def tokens(license_str: str): | |
| return [t.strip() for t in re.split(r"\s*(?:;|,| AND | OR )\s*", license_str) if t.strip()] | |
| data = json.load(open("/tmp/licenses.json")) | |
| bad = [] | |
| for p in data: | |
| name = p["Name"] | |
| lic = p["License"] | |
| if name in KNOWN_GOOD: | |
| print(f"OVERRIDE: {name} {p['Version']} -> {lic!r} accepted ({KNOWN_GOOD[name]})") | |
| continue | |
| parts = tokens(lic) | |
| if not parts or not all(t in ALLOWED for t in parts): | |
| bad.append((name, p["Version"], lic)) | |
| if bad: | |
| print("\n--- DISALLOWED dependencies ---") | |
| for name, version, lic in bad: | |
| print(f" {name} {version} -> {lic!r}") | |
| print("\nIf the dependency licence is genuinely OSI-permissive but mis-reported,") | |
| print("add the package to KNOWN_GOOD in .github/workflows/license-check.yml") | |
| print("with a justification linking to the upstream LICENSE file.") | |
| sys.exit(1) | |
| print(f"\nOK: {len(data)} dependencies, all licences in allowlist.") | |
| PY | |
| spdx-headers: | |
| name: SPDX headers | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| - name: Verify every Python file declares SPDX-License-Identifier | |
| run: | | |
| missing=0 | |
| while IFS= read -r f; do | |
| if ! head -n 5 "$f" | grep -q "SPDX-License-Identifier:"; then | |
| echo "MISSING SPDX header: $f" | |
| missing=$((missing + 1)) | |
| fi | |
| done < <(find src tests -type f -name "*.py") | |
| if [ "$missing" -gt 0 ]; then | |
| echo "Found $missing files without SPDX header." | |
| exit 1 | |
| fi | |
| echo "OK: all Python files have SPDX headers." |