Skip to content

Commit f0deb14

Browse files
authored
Merge pull request #400 from boegel/2023.06-software.eessi.io_licenses
add JSON file + Python script to keep track of software licenses
2 parents e838f3f + 0421bae commit f0deb14

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions
2+
name: Test software licenses
3+
on: [push, pull_request]
4+
permissions:
5+
contents: read # to fetch code (actions/checkout)
6+
jobs:
7+
build:
8+
runs-on: ubuntu-20.04
9+
steps:
10+
- name: Check out software-layer repository
11+
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
12+
13+
- name: set up Python
14+
uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # v4.3.0
15+
with:
16+
python-version: '3.9'
17+
18+
- name: Check software licenses
19+
run: |
20+
python licenses/spdx.py licenses/licenses.json

licenses/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
see https://spdx.org/licenses
2+
3+
Python function to download SPDX list of licenses is available in `spdx.py`

licenses/licenses.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"EasyBuild": {
3+
"spdx": "GPL-2.0-only",
4+
"license_url": "https://easybuild.io"
5+
},
6+
"GCCcore": {
7+
"spdx": "GPL-2.0-with-GCC-exception",
8+
"license_url": "https://github.com/gcc-mirror/gcc/blob/master/COPYING"
9+
}
10+
}

licenses/spdx.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import json
2+
import logging
3+
import sys
4+
import urllib.request
5+
6+
SPDX_LICENSE_LIST_URL = 'https://raw.githubusercontent.com/spdx/license-list-data/main/json/licenses.json'
7+
8+
LICENSE_URL = 'license_url'
9+
SPDX = 'spdx'
10+
11+
spdx_license_list = None
12+
13+
# Configure the logging module
14+
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
15+
16+
17+
def get_spdx_license_list():
18+
"""
19+
Download JSON file with current list of SPDX licenses, parse it, and return it as a Python dictionary.
20+
"""
21+
global spdx_license_list
22+
23+
if spdx_license_list is None:
24+
with urllib.request.urlopen(SPDX_LICENSE_LIST_URL) as fp:
25+
spdx_license_list = json.load(fp)
26+
version, release_date = spdx_license_list['licenseListVersion'], spdx_license_list['releaseDate']
27+
logging.info(f"Downloaded version {version} of SPDX license list (release date: {release_date})")
28+
licenses = spdx_license_list['licenses']
29+
logging.info(f"Found info on {len(licenses)} licenses!")
30+
31+
return spdx_license_list
32+
33+
34+
def license_info(spdx_id):
35+
"""Find license with specified SPDX identifier."""
36+
37+
spdx_license_list = get_spdx_license_list()
38+
39+
licenses = spdx_license_list['licenses']
40+
for lic in licenses:
41+
if lic['licenseId'] == spdx_id:
42+
return lic
43+
44+
# if no match is found, return None as result
45+
return None
46+
47+
48+
def read_licenses(path):
49+
"""
50+
Read software project to license mapping from specified path
51+
"""
52+
with open(path) as fp:
53+
licenses = json.loads(fp.read())
54+
55+
return licenses
56+
57+
58+
def check_licenses(licenses):
59+
"""
60+
Check mapping of software licenses: make sure SPDX identifiers are valid.
61+
"""
62+
faulty_licenses = {}
63+
64+
for software_name in licenses:
65+
spdx_lic_id = licenses[software_name][SPDX]
66+
lic_info = license_info(spdx_lic_id)
67+
if lic_info:
68+
lic_url = licenses[software_name][LICENSE_URL]
69+
logging.info(f"License for software '{software_name}': {lic_info['name']} (see {lic_url})")
70+
else:
71+
logging.warning(f"Found faulty SPDX license ID for {software_name}: {spdx_lic_id}")
72+
faulty_licenses[software_name] = spdx_lic_id
73+
74+
if faulty_licenses:
75+
logging.warning(f"Found {len(faulty_licenses)} faulty SPDIX license IDs (out of {len(licenses)})!")
76+
result = False
77+
else:
78+
logging.info(f"License check passed for {len(licenses)} licenses!")
79+
result = True
80+
81+
return result
82+
83+
84+
def main(args):
85+
if len(args) == 1:
86+
licenses_path = args[0]
87+
else:
88+
logging.error("Usage: python spdx.py <path to licenses.json>")
89+
sys.exit(1)
90+
91+
licenses = read_licenses(licenses_path)
92+
if check_licenses(licenses):
93+
logging.info("All license checks PASSED!")
94+
else:
95+
logging.error("One or more licence checks failed!")
96+
sys.exit(2)
97+
98+
99+
if __name__ == '__main__':
100+
main(sys.argv[1:])

0 commit comments

Comments
 (0)