From aab22e7f323206ddc735d3c5157ca975c03cf771 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 8 Aug 2022 23:23:08 +0200 Subject: [PATCH] Add remaining copyright statements, add licenses sanity test (#5098) * Add sanity test (currently fails). * doc_fragments can also be non-GPLv3+. * Replace 'Author:' by 'Copyright:' in some specific cases. * Avoid matching string for license checkers. * Reformulate not to throw license detection off. * Add PSF copyright notice for plugins/module_utils/_mount.py. * Add generic copyright notices. * Update changelog fragment. --- changelogs/fragments/licenses.yml | 2 +- plugins/module_utils/_mount.py | 2 + .../monitoring/datadog/datadog_event.py | 1 + plugins/modules/monitoring/icinga2_host.py | 1 + plugins/modules/net_tools/snmp_facts.py | 1 + .../integration/targets/jboss/tasks/jboss.yml | 4 +- .../targets/kernel_blacklist/tasks/main.yml | 6 +- tests/sanity/extra/licenses.json | 4 + tests/sanity/extra/licenses.py | 113 ++++++++++++++++++ .../modules/packaging/language/test_cpanm.py | 6 +- .../packaging/os/test_redhat_subscription.py | 2 +- .../modules/system/test_gconftool2_info.py | 2 +- .../plugins/modules/system/test_xfconf.py | 6 +- .../modules/system/test_xfconf_info.py | 2 +- 14 files changed, 137 insertions(+), 15 deletions(-) create mode 100644 tests/sanity/extra/licenses.json create mode 100755 tests/sanity/extra/licenses.py diff --git a/changelogs/fragments/licenses.yml b/changelogs/fragments/licenses.yml index 468dc4b343..465effc699 100644 --- a/changelogs/fragments/licenses.yml +++ b/changelogs/fragments/licenses.yml @@ -1,3 +1,3 @@ minor_changes: - - "All software licenses are now in the ``LICENSES/`` directory of the collection root (https://github.com/ansible-collections/community.general/pull/5065, https://github.com/ansible-collections/community.general/pull/5079, https://github.com/ansible-collections/community.general/pull/5080, https://github.com/ansible-collections/community.general/pull/5083, https://github.com/ansible-collections/community.general/pull/5087, https://github.com/ansible-collections/community.general/pull/5095)." + - "All software licenses are now in the ``LICENSES/`` directory of the collection root (https://github.com/ansible-collections/community.general/pull/5065, https://github.com/ansible-collections/community.general/pull/5079, https://github.com/ansible-collections/community.general/pull/5080, https://github.com/ansible-collections/community.general/pull/5083, https://github.com/ansible-collections/community.general/pull/5087, https://github.com/ansible-collections/community.general/pull/5095, https://github.com/ansible-collections/community.general/pull/5098)." - "Added MIT license as ``LICENSES/MIT.txt`` for tests/unit/plugins/modules/packaging/language/test_gem.py (https://github.com/ansible-collections/community.general/pull/5065)." diff --git a/plugins/module_utils/_mount.py b/plugins/module_utils/_mount.py index 07fff92053..63de457d7d 100644 --- a/plugins/module_utils/_mount.py +++ b/plugins/module_utils/_mount.py @@ -2,6 +2,8 @@ # This code is part of Ansible, but is an independent component. # This particular file snippet, and this file snippet only, is based on # Lib/posixpath.py of cpython +# +# Copyright (c) 2001-2022 Python Software Foundation. All rights reserved. # It is licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 # (See LICENSES/PSF-2.0.txt in this collection) # SPDX-License-Identifier: PSF-2.0 diff --git a/plugins/modules/monitoring/datadog/datadog_event.py b/plugins/modules/monitoring/datadog/datadog_event.py index b7a4c75e43..45671dd7d7 100644 --- a/plugins/modules/monitoring/datadog/datadog_event.py +++ b/plugins/modules/monitoring/datadog/datadog_event.py @@ -6,6 +6,7 @@ # # This module is proudly sponsored by iGeolise (www.igeolise.com) and # Tiny Lab Productions (www.tinylabproductions.com). +# Copyright (c) Ansible project # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later diff --git a/plugins/modules/monitoring/icinga2_host.py b/plugins/modules/monitoring/icinga2_host.py index 498f1a9938..6b42a5d8da 100644 --- a/plugins/modules/monitoring/icinga2_host.py +++ b/plugins/modules/monitoring/icinga2_host.py @@ -3,6 +3,7 @@ # This module is proudly sponsored by CGI (www.cgi.com) and # KPN (www.kpn.com). +# Copyright (c) Ansible project # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later diff --git a/plugins/modules/net_tools/snmp_facts.py b/plugins/modules/net_tools/snmp_facts.py index 71dd9259bb..7683d7308b 100644 --- a/plugins/modules/net_tools/snmp_facts.py +++ b/plugins/modules/net_tools/snmp_facts.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # This file is part of Networklore's snmp library for Ansible +# Copyright (c) Ansible project # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later diff --git a/tests/integration/targets/jboss/tasks/jboss.yml b/tests/integration/targets/jboss/tasks/jboss.yml index ec04a13f26..13d0c6bc70 100644 --- a/tests/integration/targets/jboss/tasks/jboss.yml +++ b/tests/integration/targets/jboss/tasks/jboss.yml @@ -4,8 +4,8 @@ # Integration tests for jboss module. # SPDX-License-Identifier: GPL-3.0-or-later -# helloworld.war (got from https://github.com/aeimer/java-example-helloworld-war/) license: -# MIT License +# helloworld.war (got from https://github.com/aeimer/java-example-helloworld-war/) is licensed +# under the MIT license: # # Copyright (c) 2017 Alex Eimer # diff --git a/tests/integration/targets/kernel_blacklist/tasks/main.yml b/tests/integration/targets/kernel_blacklist/tasks/main.yml index 3b34bfe423..e169d5479e 100644 --- a/tests/integration/targets/kernel_blacklist/tasks/main.yml +++ b/tests/integration/targets/kernel_blacklist/tasks/main.yml @@ -49,7 +49,7 @@ expected_content: | # Copyright (c) Ansible Project # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) - # SPDX-License-Identifier: GPL-3.0-or-later + # SPDX-{{ '' }}License-Identifier: GPL-3.0-or-later blacklist aaaa blacklist bbbb @@ -76,7 +76,7 @@ content: | # Copyright (c) Ansible Project # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) - # SPDX-License-Identifier: GPL-3.0-or-later + # SPDX-{{ '' }}License-Identifier: GPL-3.0-or-later blacklist aaaa blacklist bbbb @@ -104,7 +104,7 @@ content: | # Copyright (c) Ansible Project # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) - # SPDX-License-Identifier: GPL-3.0-or-later + # SPDX-{{ '' }}License-Identifier: GPL-3.0-or-later blacklist aaaa blacklist cccc diff --git a/tests/sanity/extra/licenses.json b/tests/sanity/extra/licenses.json new file mode 100644 index 0000000000..50e47ca88b --- /dev/null +++ b/tests/sanity/extra/licenses.json @@ -0,0 +1,4 @@ +{ + "include_symlinks": false, + "output": "path-message" +} diff --git a/tests/sanity/extra/licenses.py b/tests/sanity/extra/licenses.py new file mode 100755 index 0000000000..7fdc21bcae --- /dev/null +++ b/tests/sanity/extra/licenses.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# Copyright (c) 2022, Felix Fontein +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +"""Prevent files without a correct license identifier from being added to the source tree.""" +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import glob +import sys + + +def format_license_list(licenses): + if not licenses: + return '(empty)' + return ', '.join(['"%s"' % license for license in licenses]) + + +def find_licenses(filename, relax=False): + spdx_license_identifiers = [] + other_license_identifiers = [] + has_copyright = False + try: + with open(filename, 'r', encoding='utf-8') as f: + for line in f: + line = line.rstrip() + if 'Copyright ' in line: + has_copyright = True + if 'Copyright: ' in line: + print('%s: found copyright line with "Copyright:". Please remove the colon.' % (filename, )) + if 'SPDX-FileCopyrightText: ' in line: + has_copyright = True + idx = line.find('SPDX-License-Identifier: ') + if idx >= 0: + spdx_license_identifiers.append(line[idx + len('SPDX-License-Identifier: '):]) + if 'GNU General Public License' in line: + if 'v3.0+' in line: + other_license_identifiers.append('GPL-3.0-or-later') + if 'version 3 or later' in line: + other_license_identifiers.append('GPL-3.0-or-later') + if 'Simplified BSD License' in line: + other_license_identifiers.append('BSD-2-Clause') + if 'Apache License 2.0' in line: + other_license_identifiers.append('Apache-2.0') + if 'PSF License' in line or 'Python-2.0' in line: + other_license_identifiers.append('PSF-2.0') + if 'MIT License' in line: + other_license_identifiers.append('MIT') + except Exception as exc: + print('%s: error while processing file: %s' % (filename, exc)) + if len(set(spdx_license_identifiers)) < len(spdx_license_identifiers): + print('%s: found identical SPDX-License-Identifier values' % (filename, )) + if other_license_identifiers and set(other_license_identifiers) != set(spdx_license_identifiers): + print('%s: SPDX-License-Identifier yielded the license list %s, while manual guessing yielded the license list %s' % ( + filename, format_license_list(spdx_license_identifiers), format_license_list(other_license_identifiers))) + if not has_copyright and not relax: + print('%s: found no copyright notice' % (filename, )) + return sorted(spdx_license_identifiers) + + +def main(): + """Main entry point.""" + paths = sys.argv[1:] or sys.stdin.read().splitlines() + + # The following paths are allowed to have no license identifier + no_comments_allowed = [ + 'changelogs/fragments/*.yml', + 'changelogs/fragments/*.yaml', + 'tests/sanity/extra/*.json', + 'tests/sanity/ignore-2.*.txt', + 'COPYING', + ] + + # These files are completely ignored + ignore_paths = [ + 'CHANGELOG.rst', + 'changelogs/changelog.yaml', + 'tests/sanity/extra/licenses.py', # The strings in find_licenses() confuse this code :-) + '.ansible-test-timeout.json', + 'LICENSES/*.txt', + ] + + no_comments_allowed = [fn for pattern in no_comments_allowed for fn in glob.glob(pattern)] + ignore_paths = [fn for pattern in ignore_paths for fn in glob.glob(pattern)] + + valid_licenses = [license_file[len('LICENSES/'):-len('.txt')] for license_file in glob.glob('LICENSES/*.txt')] + + for path in paths: + if path.startswith('./'): + path = path[2:] + if path in ignore_paths or path.startswith('tests/output/'): + continue + if os.stat(path).st_size == 0: + continue + if not path.endswith('.license') and os.path.exists(path + '.license'): + path = path + '.license' + valid_licenses_for_path = valid_licenses + if path.startswith('plugins/') and not path.startswith(('plugins/modules/', 'plugins/module_utils/', 'plugins/doc_fragments/')): + valid_licenses_for_path = [license for license in valid_licenses if license == 'GPL-3.0-or-later'] + licenses = find_licenses(path, relax=path in no_comments_allowed) + if not licenses: + if path not in no_comments_allowed: + print('%s: must have at least one license' % (path, )) + else: + for license in licenses: + if license not in valid_licenses_for_path: + print('%s: found not allowed license "%s", must be one of %s' % ( + path, license, format_license_list(valid_licenses_for_path))) + + +if __name__ == '__main__': + main() diff --git a/tests/unit/plugins/modules/packaging/language/test_cpanm.py b/tests/unit/plugins/modules/packaging/language/test_cpanm.py index af79101599..a52396cd36 100644 --- a/tests/unit/plugins/modules/packaging/language/test_cpanm.py +++ b/tests/unit/plugins/modules/packaging/language/test_cpanm.py @@ -1,6 +1,6 @@ -# Author: Alexei Znamensky (russoz@gmail.com) -# Largely adapted from test_redhat_subscription by -# Jiri Hnidek (jhnidek@redhat.com) +# Copyright (c) Alexei Znamensky (russoz@gmail.com) +# Largely adapted from test_redhat_subscription: +# Copyright (c) Jiri Hnidek (jhnidek@redhat.com) # # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later diff --git a/tests/unit/plugins/modules/packaging/os/test_redhat_subscription.py b/tests/unit/plugins/modules/packaging/os/test_redhat_subscription.py index 11a0ca7cfe..95c02137b9 100644 --- a/tests/unit/plugins/modules/packaging/os/test_redhat_subscription.py +++ b/tests/unit/plugins/modules/packaging/os/test_redhat_subscription.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Author: Jiri Hnidek (jhnidek@redhat.com) +# Copyright (c) Jiri Hnidek (jhnidek@redhat.com) # # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later diff --git a/tests/unit/plugins/modules/system/test_gconftool2_info.py b/tests/unit/plugins/modules/system/test_gconftool2_info.py index e94b62dc25..1847dce428 100644 --- a/tests/unit/plugins/modules/system/test_gconftool2_info.py +++ b/tests/unit/plugins/modules/system/test_gconftool2_info.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Author: Alexei Znamensky (russoz@gmail.com) +# Copyright (c) Alexei Znamensky (russoz@gmail.com) # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later diff --git a/tests/unit/plugins/modules/system/test_xfconf.py b/tests/unit/plugins/modules/system/test_xfconf.py index 653cb13664..c944d7be05 100644 --- a/tests/unit/plugins/modules/system/test_xfconf.py +++ b/tests/unit/plugins/modules/system/test_xfconf.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -# Author: Alexei Znamensky (russoz@gmail.com) -# Largely adapted from test_redhat_subscription by -# Jiri Hnidek (jhnidek@redhat.com) +# Copyright (c) Alexei Znamensky (russoz@gmail.com) +# Largely adapted from test_redhat_subscription: +# Copyright (c) Jiri Hnidek (jhnidek@redhat.com) # # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later diff --git a/tests/unit/plugins/modules/system/test_xfconf_info.py b/tests/unit/plugins/modules/system/test_xfconf_info.py index 4d6d626f65..cdb59e81af 100644 --- a/tests/unit/plugins/modules/system/test_xfconf_info.py +++ b/tests/unit/plugins/modules/system/test_xfconf_info.py @@ -1,4 +1,4 @@ -# Author: Alexei Znamensky (russoz@gmail.com) +# Copyright (c) Alexei Znamensky (russoz@gmail.com) # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later