diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 73562f74f..501008eaf 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -55,6 +55,9 @@ jobs: - name: Run crates update run: bin/check/crates.sh + - name: Check crates licence + run: python3 bin/check/license.py + - name: Check CHANGELOG run: bin/check/changelog.sh diff --git a/bin/check/license.py b/bin/check/license.py new file mode 100755 index 000000000..8e190f15b --- /dev/null +++ b/bin/check/license.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +from typing import List, Tuple + +import json +import subprocess + + +def main(): + deps = get_deps() + check_licenses(deps) + + +def is_authorized(license: str) -> bool: + for l in ["MIT", "Apache-2.0", "Zlib", "CC0-1.0", "MPL-2.0", "BSD-3-Clause"]: + if l in license: + return True + return False + + +def is_forbidden(license: str) -> bool: + for l in ["GNU"]: + if l in license: + return True + return False + + +def check_licenses(deps: List[Tuple[str, str, str, str]]): + authorized = [] + forbidden = [] + unknown = [] + for dep in deps: + lic = dep[3] + if is_authorized(lic): + authorized.append(dep) + elif is_forbidden(lic): + forbidden.append(dep) + else: + unknown.append(dep) + print("Authorized:") + for (name, repository, version, lic) in authorized: + name_str = f"\x1b[1;34m{name}\x1b[0m" + lic_str = f"\x1b[1;32m{lic}\x1b[0m" + print(f" {name_str} {version} {repository}: {lic_str}") + + print("Forbidden:") + for (name, repository, version, lic) in forbidden: + name_str = f"\x1b[1;34m{name}\x1b[0m" + lic_str = f"\x1b[1;31m{lic}\x1b[0m" + print(f" {name_str} {version} {repository}: {lic_str}") + + print("Unknown:") + for (name, repository, version, lic) in forbidden: + name_str = f"\x1b[1;34m{name}\x1b[0m" + lic_str = f"\x1b[1;33m{lic}\x1b[0m" + print(f" {name_str} {version} {repository}: {lic_str}") + + if len(forbidden) > 0 or len(unknown) > 0: + print("There are not authorized licenses") + exit(1) + + +def get_deps() -> List[Tuple[str, str, str, str]]: + """Returns a list of crates name and licenses""" + p = subprocess.run( + [ + "cargo", + "metadata", + "--format-version", + "1", + ], + capture_output=True, + text=True, + ) + if p.returncode != 0: + print("Error calling cargo metadata") + exit(1) + data = json.loads(p.stdout) + packages = data["packages"] + licenses = [ + (p["name"], p["repository"], p["version"], p["license"]) for p in packages + ] + return licenses + + +if __name__ == "__main__": + main()