From 653dc6e00b27778c4d5452503697a8faa7982d0d Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 18 Apr 2022 12:56:35 -0700 Subject: [PATCH 1/7] Support --no-signoff with checkpatch.pl This lets the configuration disable the Signed-off-by check. --- run-ci.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/run-ci.py b/run-ci.py index 87ff7dc..5c63640 100755 --- a/run-ci.py +++ b/run-ci.py @@ -493,6 +493,9 @@ def config(self): logger.debug("checkpatch_pl = %s" % self.checkpatch_pl) + if 'no_signoff' not in config['checkpatch']: + config['checkpatch']['no_signoff'] = False + def run(self): logger.debug("##### Run CheckPatch Test #####") self.start_timer() @@ -512,7 +515,8 @@ def run(self): patch = patchwork_get_patch(str(patch_item["id"])) # Run checkpatch - (output, error) = self.run_checkpatch(patch) + (output, error) = self.run_checkpatch(patch, + no_sob=config['checkpatch']['no_signoff']) # Failed / Warning if error != None: @@ -540,7 +544,7 @@ def run(self): if self.verdict != Verdict.FAIL: self.success() - def run_checkpatch(self, patch): + def run_checkpatch(self, patch, no_sob=False): """ Run checkpatch script with patch from the patchwork. It saves to file first and run checkpatch with the saved patch file. @@ -548,18 +552,23 @@ def run_checkpatch(self, patch): On success, it returns None. On failure, it returns the stderr output string """ + args = [ self.checkpatch_pl, '--no-tree' ] output = None error = None + if no_sob: + args.append('--no-signoff') + # Save the patch content to file filename = os.path.join(src_dir, str(patch['id']) + ".patch") logger.debug("Save patch: %s" % filename) patch_file = patchwork_save_patch(patch, filename) + args.append(patch_file) + try: - output = subprocess.check_output((self.checkpatch_pl, '--no-tree', - patch_file), + output = subprocess.check_output(args, stderr=subprocess.STDOUT, cwd=src_dir) output = output.decode("utf-8") From 7108f5f64c71614073269753c4254b405625b2d7 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 18 Apr 2022 13:52:44 -0700 Subject: [PATCH 2/7] Don't report skipped checks If the configuration disabled a check there is no reason to notify the author that the check was skipped. --- run-ci.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/run-ci.py b/run-ci.py index 5c63640..af22ec1 100755 --- a/run-ci.py +++ b/run-ci.py @@ -1298,13 +1298,7 @@ def report_ci(): result='ERROR', elapsed=test.elapsed()) if test.verdict == Verdict.SKIP: - results += TEST_REPORT_FAIL.format(test.display_name, - "SKIPPED", - test.desc, - test.output) - summary += ONELINE_RESULT.format(test=test.display_name, - result='ERROR', - elapsed=test.elapsed()) + continue body = EMAIL_MESSAGE.format(pw_series["web_url"], summary + '\n' + results) From 0b5c12f26846f73362f07783230f69a1818e8715 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 18 Apr 2022 14:03:14 -0700 Subject: [PATCH 3/7] Add support for passing config/email via URL --- Dockerfile | 1 + action.yml | 10 ++++++++++ default-email-message.txt | 15 ++++++++++++++ entrypoint.sh | 4 +++- run-ci.py | 41 ++++++++++++++++++++++----------------- 5 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 default-email-message.txt diff --git a/Dockerfile b/Dockerfile index 509957f..1830e03 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,5 +4,6 @@ COPY *.sh / COPY *.py / COPY *.ini / COPY gitlint /.gitlint +COPY *.txt / ENTRYPOINT [ "/entrypoint.sh" ] diff --git a/action.yml b/action.yml index 341f640..3f1b831 100644 --- a/action.yml +++ b/action.yml @@ -16,6 +16,14 @@ inputs: patchwork_token: description: Patchwork token required: true + config: + description: Configuration file or URL + required: false + default: /config.ini + email_message: + description: Email message file or URL + required: false + default: /default-email-message.txt runs: using: 'docker' @@ -26,3 +34,5 @@ runs: GITHUB_TOKEN: ${{ inputs.github_token }} EMAIL_TOKEN: ${{ inputs.email_token }} PATCHWORK_TOKEN: ${{ inputs.patchwork_token }} + CONFIG: ${{ inputs.config }} + EMAIL: ${{ inputs.email_message }} diff --git a/default-email-message.txt b/default-email-message.txt new file mode 100644 index 0000000..d3d6e83 --- /dev/null +++ b/default-email-message.txt @@ -0,0 +1,15 @@ +This is automated email and please do not reply to this email! + +Dear submitter, + +Thank you for submitting the patches to the linux bluetooth mailing list. +This is a CI test results with your patch series: +PW Link:{} + +---Test result--- + +{} + +--- +Regards, +Linux Bluetooth diff --git a/entrypoint.sh b/entrypoint.sh index 9f030be..107e1b5 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -11,6 +11,8 @@ echo "SHA: $GITHUB_SHA" echo "REF: $GITHUB_REF" echo "HEAD-REF: $GITHUB_HEAD_REF" echo "BASE-REF: $GITHUB_BASE_REF" +echo "CONFIG: $CONFIG" +echo "EMAIL: $EMAIL" echo "PWD: $(pwd)" git config --global user.name "$GITHUB_ACTOR" @@ -32,4 +34,4 @@ git clone --depth=1 https://git.kernel.org/pub/scm/libs/ell/ell.git $ELL_PATH PR=${GITHUB_REF#"refs/pull/"} PR=${PR%"/merge"} -/run-ci.py -c /config.ini -p $PR -r $GITHUB_REPOSITORY -s $SRC_PATH -e $ELL_PATH -v +/run-ci.py -c $CONFIG -m $EMAIL -p $PR -r $GITHUB_REPOSITORY -s $SRC_PATH -e $ELL_PATH -v diff --git a/run-ci.py b/run-ci.py index af22ec1..e505275 100755 --- a/run-ci.py +++ b/run-ci.py @@ -17,6 +17,8 @@ from github import Github from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText +from urllib.request import urlretrieve + # Globals logger = None @@ -41,23 +43,7 @@ PW_BASE_URL = "https://patchwork.kernel.org/api/1.1" -EMAIL_MESSAGE = '''This is automated email and please do not reply to this email! - -Dear submitter, - -Thank you for submitting the patches to the linux bluetooth mailing list. -This is a CI test results with your patch series: -PW Link:{} - ----Test result--- - -{} - ---- -Regards, -Linux Bluetooth - -''' +EMAIL_MESSAGE = '' def requests_url(url): """ Helper function to requests WEB API GET with URL """ @@ -1382,7 +1368,7 @@ def parse_args(): parser = argparse.ArgumentParser( description="Check patch style in the pull request") parser.add_argument('-c', '--config-file', default='config.ini', - help='Configuration file') + help='Configuration file or URL') parser.add_argument('-l', '--show-test-list', action='store_true', help='Display supported CI tests') parser.add_argument('-p', '--pr-num', required=True, type=int, @@ -1395,15 +1381,34 @@ def parse_args(): help='Path to ELL source') parser.add_argument('-v', '--verbose', action='store_true', help='Display debugging info') + parser.add_argument('-m', '--email-message', + default='/default-email-message.txt') return parser.parse_args() +def is_url(config: str) -> bool: + prefixes = ('http://', 'https://') + + return config.startswith(prefixes) + def main(): global src_dir, src2_dir, src3_dir, src4_dir, ell_dir, base_dir + global EMAIL_MESSAGE args = parse_args() + if is_url(args.config_file): + urlretrieve(args.config_file, '/tmp/config.ini') + args.config_file = '/tmp/config.ini' + + if is_url(args.email_message): + urlretrieve(args.email_message, '/tmp/email-message.txt') + args.email_message = '/tmp/email-message.txt' + + with open(args.email_message, 'r') as f: + EMAIL_MESSAGE = f.read() + init_logging(args.verbose) init_config(args.config_file, args.verbose) From d665ef3b897f3c9234dcd1be4688e81761edb0bc Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 18 Apr 2022 14:20:59 -0700 Subject: [PATCH 4/7] Don't submit disabled checks to patchwork No sense in sending a check that was disabled by the config --- run-ci.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/run-ci.py b/run-ci.py index e505275..e1dfb06 100755 --- a/run-ci.py +++ b/run-ci.py @@ -234,6 +234,9 @@ def config_submit_pw(config, name): Return True if it is specified and value is "yes" """ + if not config_enable(config, name): + return False + if name in config: if 'submit_pw' in config[name]: if config[name]['submit_pw'] == 'yes': From 68759d444b9de699841d22653aeef4bd313d633b Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 18 Apr 2022 14:35:32 -0700 Subject: [PATCH 5/7] Submit PENDING results before all checks This makes it clear on the Patchwork UI what checks are going to run rather than each check updating to PASS/FAIL once it finishes. --- run-ci.py | 51 +++++++++++---------------------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/run-ci.py b/run-ci.py index e1dfb06..3cda01b 100755 --- a/run-ci.py +++ b/run-ci.py @@ -388,14 +388,16 @@ class CiBase: name = None display_name = None desc = None - enable = True start_time = 0 end_time = 0 - submit_pw = False verdict = Verdict.PENDING output = "" + def __init__(self): + self.enable = config_enable(config, self.name) + self.submit_pw = config_submit_pw(config, self.name) + def success(self): self.end_timer() self.verdict = Verdict.PASS @@ -473,9 +475,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, self.name) - self.submit_pw = config_submit_pw(config, self.name) - if self.name in config: if 'bin_path' in config[self.name]: self.checkpatch_pl = config[self.name]['bin_path'] @@ -583,9 +582,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, self.name) - self.submit_pw = config_submit_pw(config, self.name) - if self.name in config: if 'config_path' in config[self.name]: self.gitlint_config = config[self.name]['config_path'] @@ -667,9 +663,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, "build") - self.submit_pw = config_submit_pw(config, "build") - def run(self): logger.debug("##### Run Build: Setup ELL #####") self.start_timer() @@ -718,9 +711,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, "build") - self.submit_pw = config_submit_pw(config, "build") - def run(self): logger.debug("##### Run Build: Prep #####") self.start_timer() @@ -754,9 +744,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, self.name) - self.submit_pw = config_submit_pw(config, self.name) - def run(self): logger.debug("##### Run Build Test #####") self.start_timer() @@ -794,9 +781,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, self.name) - self.submit_pw = config_submit_pw(config, self.name) - def run(self): logger.debug("##### Run Build Make Test #####") self.start_timer() @@ -839,9 +823,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, self.name) - self.submit_pw = config_submit_pw(config, self.name) - def run(self): logger.debug("##### Run MakeCheck Test #####") self.start_timer() @@ -884,9 +865,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, self.name) - self.submit_pw = config_submit_pw(config, self.name) - def run(self): logger.debug("##### Run MakeCheck w/ Valgrind Test #####") self.start_timer() @@ -946,9 +924,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, self.name) - self.submit_pw = config_submit_pw(config, self.name) - def run(self): logger.debug("##### Run Make Distcheck Test #####") self.start_timer() @@ -994,9 +969,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, self.name) - self.submit_pw = config_submit_pw(config, self.name) - def run(self): logger.debug("##### Run Build w/exteranl ell - configure Test #####") self.start_timer() @@ -1035,9 +1007,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, 'build_extell') - self.submit_pw = config_submit_pw(config, 'build_extell') - def run(self): logger.debug("##### Run Build w/exteranl ell - make Test #####") self.start_timer() @@ -1081,9 +1050,6 @@ def config(self): """ logger.debug("Parser configuration") - self.enable = config_enable(config, 'incremental_build') - self.submit_pw = config_submit_pw(config, 'incremental_build') - def run(self): logger.debug("##### Run Incremental Build Test #####") self.start_timer() @@ -1106,6 +1072,8 @@ def run(self): # If there is only one patch, no need to run and just return success if github_pr.commits == 1: logger.debug("Only 1 patch and no need to run here") + self.submit_result(pw_series_patch_1, Verdict.PASS, + "Incremental build not run PASS") self.success() return @@ -1204,12 +1172,15 @@ def run_ci(args): print(testcase.name) return 0 - # Run tests + # Initialize patchwork checks as 'pending' for testcase in CiBase.__subclasses__(): test = testcase() - test_suite[test.name] = test + test.submit_result(pw_series_patch_1, Verdict.PENDING, + "%s PENDING" % test.display_name) + # Run tests + for test in test_suite.values(): try: test.run() except EndTest: From c8fb9ab09d6a9665af25e9d3ff88626573787652 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Tue, 19 Apr 2022 10:01:08 -0700 Subject: [PATCH 6/7] Support passing Patchwork user as argument/input --- action.yml | 5 +++++ entrypoint.sh | 3 ++- run-ci.py | 7 +++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index 3f1b831..72ede70 100644 --- a/action.yml +++ b/action.yml @@ -24,6 +24,10 @@ inputs: description: Email message file or URL required: false default: /default-email-message.txt + user: + description: User ID + required: false + default: 104215 runs: using: 'docker' @@ -36,3 +40,4 @@ runs: PATCHWORK_TOKEN: ${{ inputs.patchwork_token }} CONFIG: ${{ inputs.config }} EMAIL: ${{ inputs.email_message }} + USER: ${{ inputs.user }} diff --git a/entrypoint.sh b/entrypoint.sh index 107e1b5..0464417 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -13,6 +13,7 @@ echo "HEAD-REF: $GITHUB_HEAD_REF" echo "BASE-REF: $GITHUB_BASE_REF" echo "CONFIG: $CONFIG" echo "EMAIL: $EMAIL" +echo "USER: $USER" echo "PWD: $(pwd)" git config --global user.name "$GITHUB_ACTOR" @@ -34,4 +35,4 @@ git clone --depth=1 https://git.kernel.org/pub/scm/libs/ell/ell.git $ELL_PATH PR=${GITHUB_REF#"refs/pull/"} PR=${PR%"/merge"} -/run-ci.py -c $CONFIG -m $EMAIL -p $PR -r $GITHUB_REPOSITORY -s $SRC_PATH -e $ELL_PATH -v +/run-ci.py -c $CONFIG -m $EMAIL -p $PR -r $GITHUB_REPOSITORY -s $SRC_PATH -e $ELL_PATH -v -u $USER diff --git a/run-ci.py b/run-ci.py index 3cda01b..84c4759 100755 --- a/run-ci.py +++ b/run-ci.py @@ -42,7 +42,7 @@ test_suite = {} PW_BASE_URL = "https://patchwork.kernel.org/api/1.1" - +PW_USER = None EMAIL_MESSAGE = '' def requests_url(url): @@ -140,7 +140,7 @@ def patchwork_post_checks(url, state, target_url, context, description): headers['Authorization'] = f'Token {token}' content = { - 'user': 104215, + 'user': PW_USER, 'state': state, 'target_url': target_url, 'context': context, @@ -1357,6 +1357,7 @@ def parse_args(): help='Display debugging info') parser.add_argument('-m', '--email-message', default='/default-email-message.txt') + parser.add_argument('-u', '--user', type=int, required=True) return parser.parse_args() @@ -1383,6 +1384,8 @@ def main(): with open(args.email_message, 'r') as f: EMAIL_MESSAGE = f.read() + PW_USER = args.user + init_logging(args.verbose) init_config(args.config_file, args.verbose) From 77160d1e9dbdcc580839b7694999fa8f183ec531 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Tue, 19 Apr 2022 12:29:02 -0700 Subject: [PATCH 7/7] Don't comment to GH for disabled tests If a test is disabled skip posting a comment to Github. --- run-ci.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/run-ci.py b/run-ci.py index 84c4759..f88507b 100755 --- a/run-ci.py +++ b/run-ci.py @@ -1192,8 +1192,10 @@ def run_ci(args): num_fails += 1 logger.info(test.name + " result: " + test.verdict.name) - logger.debug("Post message to github: " + test.output) - github_pr_post_comment(test) + + if test.enable: + logger.debug("Post message to github: " + test.output) + github_pr_post_comment(test) return num_fails