From 1acd9ec2eeb2b1eefbee429da567309fdfa5217b Mon Sep 17 00:00:00 2001 From: Shenglei Zhang Date: Fri, 10 Jul 2020 15:37:59 +0800 Subject: [PATCH] LicenseCheck Change-Id: I185c8956dfe803b1f202c5a005b5e0cc80aadc2e Signed-off-by: Shenglei Zhang --- .pytool/Plugin/LicenseCheck/LicenseCheck.py | 105 ++++++++++++++++++ .../LicenseCheck/LicenseCheck_plug_in.yaml | 11 ++ .pytool/Plugin/LicenseCheck/Readme.md | 17 +++ 3 files changed, 133 insertions(+) create mode 100644 .pytool/Plugin/LicenseCheck/LicenseCheck.py create mode 100644 .pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml create mode 100644 .pytool/Plugin/LicenseCheck/Readme.md diff --git a/.pytool/Plugin/LicenseCheck/LicenseCheck.py b/.pytool/Plugin/LicenseCheck/LicenseCheck.py new file mode 100644 index 0000000000000..3e2433d86f7dc --- /dev/null +++ b/.pytool/Plugin/LicenseCheck/LicenseCheck.py @@ -0,0 +1,105 @@ +import os +import logging +import re +from io import StringIO +from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin +from edk2toolext.environment.var_dict import VarDict +from edk2toollib.utility_functions import RunCmd + +class LicenseCheck(ICiBuildPlugin): + + """ + A CiBuildPlugin to check the license for new added files. + + Configuration options: + "LicenseCheck": { + "IgnoreFiles": [] + }, + """ + + license_format_preflix = 'SPDX-License-Identifier' + + bsd2_patent = 'BSD-2-Clause-Patent' + + bsd3_patent = 'BSD-3-Clause-Patent' + + Readdedfileformat = re.compile(r'\+\+\+ b\/(.*)') + + file_extension_list = [".c", ".h", ".inf", ".dsc", ".dec", ".py", ".bat", ".sh", ".uni", ".yaml", ".fdf", ".inc", "yml", ".asm", \ + ".asm16", ".asl", ".vfr", ".s", ".S", ".aslc", ".nasm", ".nasmb", ".idf", ".Vfr", ".H"] + + def GetTestName(self, packagename: str, environment: VarDict) -> tuple: + """ Provide the testcase name and classname for use in reporting + testclassname: a descriptive string for the testcase can include whitespace + classname: should be patterned .. + + Args: + packagename: string containing name of package to build + environment: The VarDict for the test to run in + Returns: + a tuple containing the testcase name and the classname + (testcasename, classname) + """ + return ("Check for license for " + packagename, packagename + ".LicenseCheck") + + ## + # External function of plugin. This function is used to perform the task of the ci_build_plugin Plugin + # + # - package is the edk2 path to package. This means workspace/packagepath relative. + # - edk2path object configured with workspace and packages path + # - PkgConfig Object (dict) for the pkg + # - EnvConfig Object + # - Plugin Manager Instance + # - Plugin Helper Obj Instance + # - Junit Logger + # - output_stream the StringIO output stream from this plugin via logging + def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM, PLMHelper, tc, output_stream=None): + edk2_path = Edk2pathObj.WorkspacePath + + return_buffer = StringIO() + params = "diff --unified=0 origin/master HEAD" + RunCmd("git", params, outstream=return_buffer) + p = return_buffer.getvalue().strip() + patch = p.split("\n") + return_buffer.close() + + ignore_files = [] + if "IgnoreFiles" in pkgconfig: + ignore_files = pkgconfig["IgnoreFiles"] + + self.ok = True + self.startcheck = False + self.license = True + self.all_file_pass = True + count = len(patch) + line_index = 0 + for line in patch: + if line.startswith('--- /dev/null'): + nextline = patch[line_index + 1] + added_file = self.Readdedfileformat.search(nextline).group(1) + added_file_extension = os.path.splitext(added_file)[1] + if added_file_extension in self.file_extension_list and packagename in added_file: + for f in ignore_files: + if f in added_file: + continue + self.startcheck = True + self.license = False + if self.startcheck and self.license_format_preflix in line: + if self.bsd2_patent in line or self.bsd3_patent in line: + self.license = True + if line_index + 1 == count or patch[line_index + 1].startswith('diff --') and self.startcheck: + if not self.license: + self.all_file_pass = False + error_message = "Invalid license in: " + added_file + logging.error(error_message) + self.startcheck = False + self.license = True + line_index = line_index + 1 + + if self.all_file_pass: + tc.SetSuccess() + return 0 + else: + tc.SetFailed("License Check {0} Failed. ".format(packagename), "LICENSE_CHECK_FAILED") + return 1 + diff --git a/.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml b/.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml new file mode 100644 index 0000000000000..1d02f6da5a691 --- /dev/null +++ b/.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml @@ -0,0 +1,11 @@ +## @file +# CiBuildPlugin used to check license issues for new added files +# +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +## +{ + "scope": "cibuild", + "name": "License Check Test", + "module": "LicenseCheck" +} diff --git a/.pytool/Plugin/LicenseCheck/Readme.md b/.pytool/Plugin/LicenseCheck/Readme.md new file mode 100644 index 0000000000000..57d9db6769fab --- /dev/null +++ b/.pytool/Plugin/LicenseCheck/Readme.md @@ -0,0 +1,17 @@ +# License Check Plugin + +This CiBuildPlugin scans all new added files in a package to make sure code +is contributed under BSD-2-Clause-Patent or BSD-3-Clause-Patent. + +## Configuration + +The plugin can be configured to ignore certain files. + +``` yaml +"LicenseCheck": { + "IgnoreFiles": [] +} +``` +### IgnoreFiles + +OPTIONAL List of file to ignore.