Skip to content

Commit 010531e

Browse files
committed
Merge branch 'maint'
2 parents 6c65146 + 956c18d commit 010531e

File tree

3 files changed

+166
-0
lines changed

3 files changed

+166
-0
lines changed

.github/workflows/main.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ jobs:
4343
changes: ${{ steps.changes.outputs.changes }}
4444
c-code-changes: ${{ steps.c-code-changes.outputs.changes }}
4545
all: ${{ steps.apps.outputs.all }}
46+
added_files: ${{ steps.cache.outputs.added_files }}
4647
steps:
4748
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # ratchet:actions/[email protected]
4849
- uses: ./.github/actions/build-base-image
@@ -112,6 +113,8 @@ jobs:
112113
- deleted: '**/*.h'
113114
deleted:
114115
- deleted: '**'
116+
added:
117+
- added: '**'
115118
bootstrap:
116119
- 'bootstrap/**'
117120
configure:
@@ -470,6 +473,9 @@ jobs:
470473
- name: Run dialyzer
471474
run: docker run -v $PWD/:/github otp '/github/scripts/run-dialyzer'
472475

476+
- name: License Compliance Check
477+
run: docker run -v $PWD/:/github otp 'sudo apt install -y pip && pip install scancode-toolkit==32.3.0 && export PATH="$HOME/.local/bin:$PATH" && /github/scripts/scan-code.escript --file-or-dir "${{ needs.pack.outputs.added_files }}" --template-path /github/scripts/scan-code/template.txt --prefix /github/'
478+
473479
test:
474480
name: Test Erlang/OTP
475481
runs-on: ubuntu-latest

scripts/scan-code.escript

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#!/usr/bin/env escript
2+
%% -*- erlang -*-
3+
4+
%%
5+
%% %CopyrightBegin%
6+
%%
7+
%% Copyright Ericsson AB 1996-2024. All Rights Reserved.
8+
%%
9+
%% Licensed under the Apache License, Version 2.0 (the "License");
10+
%% you may not use this file except in compliance with the License.
11+
%% You may obtain a copy of the License at
12+
%%
13+
%% http://www.apache.org/licenses/LICENSE-2.0
14+
%%
15+
%% Unless required by applicable law or agreed to in writing, software
16+
%% distributed under the License is distributed on an "AS IS" BASIS,
17+
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
%% See the License for the specific language governing permissions and
19+
%% limitations under the License.
20+
%%
21+
%% %CopyrightEnd%
22+
23+
main(Args) ->
24+
argparse:run(Args, cli(), #{progname => otp_compliance}).
25+
26+
cli() ->
27+
#{ help =>
28+
"""
29+
Run 'scancode' with multiple options
30+
""",
31+
arguments => [ scan_option(),
32+
template_option(),
33+
prefix_option(),
34+
file_or_dir() ],
35+
handler => fun scancode/1}.
36+
37+
approved() ->
38+
[ "mit", "agpl-3.0", "apache-2.0", "boost-1.0", "llvm-exception",
39+
"lgpl-2.1-plus", "cc0-1.0", "bsd-simplified", "bsd-new", "pcre",
40+
"fsf-free", "autoconf-exception-3.0", "mpl-1.1", "public-domain",
41+
"autoconf-simple-exception", "unicode", "tcl", "gpl-2.0 WITH classpath-exception-2.0",
42+
"zlib", "lgpl-2.0-plus WITH wxwindows-exception-3.1", "lgpl-2.0-plus",
43+
"openssl-ssleay", "cc-by-sa-3.0", "cc-by-4.0", "dco-1.1", "fsf-ap",
44+
"agpl-1.0-plus", "agpl-1.0", "agpl-3.0-plus", "classpath-exception-2.0",
45+
"ietf-trust"].
46+
47+
not_approved() ->
48+
["gpl", "gpl-3.0-plus", "gpl-2.0", "gpl-1.0-plus", "unlicense",
49+
"erlangpl-1.1", "gpl-2.0-plus", "null"].
50+
51+
52+
scan_option() ->
53+
#{name => scan_option,
54+
type => string,
55+
default => "cli",
56+
long => "-scan-option"}.
57+
58+
prefix_option() ->
59+
#{name => prefix,
60+
type => string,
61+
default => "",
62+
long => "-prefix"}.
63+
64+
65+
file_or_dir() ->
66+
#{name => file_or_dir,
67+
type => string,
68+
required => true,
69+
long => "-file-or-dir"}.
70+
71+
template_option() ->
72+
#{name => template_path,
73+
type => string,
74+
default => "scripts/scan-code/template.txt",
75+
long => "-template-path"}.
76+
77+
78+
scancode(#{ file_or_dir := FilesOrDirs}=Config) ->
79+
Files = string:split(FilesOrDirs, " ", all),
80+
Results = lists:foldl(fun (File, Errors) ->
81+
Command = scancode(Config, File),
82+
case execute(Command, File) of
83+
{error, Err} ->
84+
[Err | Errors];
85+
ok ->
86+
Errors
87+
end
88+
end, [], Files),
89+
case Results of
90+
[] ->
91+
ok;
92+
Errors ->
93+
error(Errors)
94+
end.
95+
96+
scancode(#{scan_option := Options,
97+
prefix := Prefix,
98+
template_path := TemplatePath}, File) ->
99+
"scancode -" ++ Options ++ " --custom-output - --custom-template " ++ TemplatePath ++ " " ++ Prefix ++ File.
100+
101+
execute(Command, File) ->
102+
Port = open_port({spawn, Command}, [stream, in, eof, hide, exit_status]),
103+
Result = loop(Port, []),
104+
Ls = string:split(string:trim(Result, both), ",", all),
105+
106+
case lists:filter(fun ([]) -> false; (_) -> true end, Ls) of
107+
[] ->
108+
{error, {File, no_license_found}};
109+
Ls1 ->
110+
NotApproved = lists:any(fun (License) -> lists:member(License, not_approved()) end, Ls1),
111+
case NotApproved of
112+
true ->
113+
{error, {File, license_not_approved}};
114+
false ->
115+
InPolicy = lists:all(fun (License) -> lists:member(License, approved()) end, Ls1),
116+
case InPolicy of
117+
false ->
118+
%% this can happen if a license is
119+
%% not in the approve/not_approved list
120+
{error, {File, license_not_approved}};
121+
true ->
122+
ok
123+
end
124+
end
125+
end.
126+
127+
loop(Port, Acc) ->
128+
receive
129+
{Port, {data, Data}} ->
130+
loop(Port, [Data|Acc]);
131+
{Port,{exit_status, _ExitStatus}} ->
132+
lists:flatten(lists:reverse(Acc))
133+
end.

scripts/scan-code/template.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{#
2+
%CopyrightBegin%
3+
4+
Copyright Ericsson AB 1996-2024. All Rights Reserved.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
%CopyrightEnd%
19+
#}
20+
21+
{%- if files.license_copyright %}
22+
{%- for location, data in files.license_copyright.items() %}
23+
{%- for row in data %}
24+
{%- if row.what == 'license'%}{{ row.value|escape }},{% endif %}
25+
{%- endfor %}
26+
{%- endfor %}
27+
{% endif %}

0 commit comments

Comments
 (0)