From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga14.intel.com (mga14.intel.com []) by mx.groups.io with SMTP id smtpd.web11.33610.1595234237313655791 for ; Mon, 20 Jul 2020 01:37:20 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: shenglei.zhang@intel.com) IronPort-SDR: tTotHDbvdQ0hKJiUjxOsp5aYEtCAT2h98r4KvOWMD+r7Tt2LOXd4CMDMsyACLqn+t34Zna9X6U 6kXPjHsRTi1A== X-IronPort-AV: E=McAfee;i="6000,8403,9687"; a="149029425" X-IronPort-AV: E=Sophos;i="5.75,374,1589266800"; d="scan'208";a="149029425" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Jul 2020 01:37:19 -0700 IronPort-SDR: 9EwL3TLtNUYa4ICC6m4h/pNAoCq/CLSPwUf0XLe0IWocP6V4l9lPCsAeCPLim3NadwSYAnvhok H44+Wy7+0itA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,374,1589266800"; d="scan'208";a="487651345" Received: from shenglei-dev.ccr.corp.intel.com ([10.239.158.52]) by fmsmga005.fm.intel.com with ESMTP; 20 Jul 2020 01:37:18 -0700 From: "Zhang, Shenglei" To: devel@edk2.groups.io Cc: Sean Brogan , Bret Barkelew , Michael D Kinney , Liming Gao Subject: [PATCH 01/15] .pytool/Plugin: Add a plugin LicenseCheck Date: Mon, 20 Jul 2020 16:36:55 +0800 Message-Id: <20200720083709.17264-2-shenglei.zhang@intel.com> X-Mailer: git-send-email 2.18.0.windows.1 In-Reply-To: <20200720083709.17264-1-shenglei.zhang@intel.com> References: <20200720083709.17264-1-shenglei.zhang@intel.com> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2691 REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2833 Add a plugin to check license conflict for new added files in a patch. It will report out errors when meeting files which are now contributed under BSD-2-Clause-Patent or BSD-3-Clause-Patent. Cc: Sean Brogan Cc: Bret Barkelew Cc: Michael D Kinney Cc: Liming Gao Signed-off-by: Shenglei Zhang --- .pytool/Plugin/LicenseCheck/LicenseCheck.py | 118 ++++++++++++++++++ .../LicenseCheck/LicenseCheck_plug_in.yaml | 11 ++ .pytool/Plugin/LicenseCheck/Readme.md | 17 +++ 3 files changed, 146 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 000000000000..98941ddda758 --- /dev/null +++ b/.pytool/Plugin/LicenseCheck/LicenseCheck.py @@ -0,0 +1,118 @@ +# @file LicenseCheck.py +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +import os +import logging +import re +from io import StringIO +from typing import List, Tuple +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): + 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: + if (self.IsIgnoreFile(added_file, ignore_files)): + line_index = line_index + 1 + 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 + " Hint: Only BSD-2-Clause-Patent and" + \ + " BSD-3-Clause-Patent are accepted." + 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 + + def IsIgnoreFile(self, file: str, ignore_files: List[str]) -> bool: + for f in ignore_files: + if f in file: + return True + return False diff --git a/.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml b/.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml new file mode 100644 index 000000000000..1d02f6da5a69 --- /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 000000000000..57d9db6769fa --- /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. -- 2.18.0.windows.1