From d35c346bcc8849ed2da1d57257d97c11be85637d Mon Sep 17 00:00:00 2001 From: sip21 Date: Thu, 14 Mar 2024 00:21:56 -0600 Subject: [PATCH] Update test.py and workflows --- .ci/test.py | 107 +++++++++++++++++++++++++++------- .github/workflows/main.yml | 9 ++- .github/workflows/nightly.yml | 2 +- 3 files changed, 96 insertions(+), 22 deletions(-) diff --git a/.ci/test.py b/.ci/test.py index 946210143..b7edaf54f 100644 --- a/.ci/test.py +++ b/.ci/test.py @@ -1,15 +1,14 @@ -from pathlib import Path -import subprocess -from pprint import pprint -from collections import namedtuple -from typing import Generator - +import json import logging +import os +import shlex import shutil +import subprocess import sys import tempfile -import shlex -import os +from collections import namedtuple +from pathlib import Path, PosixPath +from typing import Generator, List logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) @@ -18,8 +17,8 @@ '.ci', '.git', '.github', + 'archived', 'lightning', - 'feeadjuster' ] global_dependencies = [ @@ -50,13 +49,15 @@ def enumerate_plugins(basedir: Path) -> Generator[Plugin, None, None]: pip_pytest = [ x for x in plugins if (x / Path('requirements.txt')).exists() ] + print(f'Pip plugins: {", ".join([p.name for p in sorted(pip_pytest)])}') poetry_pytest = [ x for x in plugins if (x / Path("pyproject.toml")).exists() ] - print(poetry_pytest) + print(f'Poetry plugins: {", ".join([p.name for p in sorted(poetry_pytest)])}') other_plugins = [x for x in plugins if x not in pip_pytest and x not in poetry_pytest] + print(f'Other plugins: {", ".join([p.name for p in sorted(other_plugins)])}') for p in sorted(pip_pytest): yield Plugin( @@ -227,20 +228,24 @@ def install_pyln_testing(pip_path): stderr=subprocess.STDOUT, ) -def run_one(p: Plugin) -> bool: - print("Running tests on plugin {p.name}".format(p=p)) - - testfiles = [ +def get_testfiles(p: Plugin) -> List[PosixPath]: + return [ x for x in p.path.iterdir() if (x.is_dir() and x.name == 'tests') or (x.name.startswith("test_") and x.name.endswith('.py')) ] - if len(testfiles) == 0: +def has_testfiles(p: Plugin) -> bool: + return len(get_testfiles(p)) > 0 + +def run_one(p: Plugin) -> bool: + print("Running tests on plugin {p.name}".format(p=p)) + + if not has_testfiles(p): print("No test files found, skipping plugin {p.name}".format(p=p)) return True - print("Found {ctestfiles} test files, creating virtualenv and running tests".format(ctestfiles=len(testfiles))) + print("Found {ctestfiles} test files, creating virtualenv and running tests".format(ctestfiles=len(get_testfiles(p)))) print("##[group]{p.name}".format(p=p)) # Create a virtual env @@ -296,7 +301,7 @@ def run_one(p: Plugin) -> bool: print("##[endgroup]") -def run_all(args): +def run_all(workflow, update_badges, plugin_names): root_path = subprocess.check_output([ 'git', 'rev-parse', @@ -306,8 +311,8 @@ def run_all(args): root = Path(root_path) plugins = list(enumerate_plugins(root)) - if args != []: - plugins = [p for p in plugins if p.name in args] + if plugin_names != []: + plugins = [p for p in plugins if p.name in plugin_names] print("Testing the following plugins: {names}".format(names=[p.name for p in plugins])) else: print("Testing all plugins in {root}".format(root=root)) @@ -315,11 +320,73 @@ def run_all(args): results = [(p, run_one(p)) for p in plugins] success = all([t[1] for t in results]) + if sys.version_info[0:2] == (3, 12) and update_badges: + push_badges_data(collect_badges_data(results, success), workflow) + if not success: print("The following tests failed:") for t in filter(lambda t: not t[1], results): print(" - {p.name} ({p.path})".format(p=t[0])) sys.exit(1) + else: + print("All tests passed.") + + +def collect_badges_data(results, success): + badges_data = {} + for t in results: + p = t[0] + if has_testfiles(p): + if success or t[1]: + badges_data[p.name] = True + else: + badges_data[p.name] = False + return badges_data + + +def configure_git(): + subprocess.run(["git", "config", "--global", "user.email", '"lightningd@plugins.repo"']) + subprocess.run(["git", "config", "--global", "user.name", '"lightningd"']) + + +def update_and_commit_badge(plugin_name, passed, workflow): + json_data = { "schemaVersion": 1, "label": "", "message": " ✔ ", "color": "green" } + if not passed: + json_data.update({"message": "✗", "color": "red"}) + + filename = os.path.join("badges", f"{plugin_name}_{workflow}.json") + with open(filename, "w") as file: + file.write(json.dumps(json_data)) + + output = subprocess.check_output(["git", "add", "-v", filename]).decode("utf-8") + if output != "": + subprocess.run(["git", "commit", "-m", f'Update {plugin_name} badge to {"passed" if passed else "failed"} ({workflow})']) + return True + return False + + +def push_badges_data(data, workflow): + print("Pushing badge data...") + configure_git() + subprocess.run(["git", "fetch"]) + subprocess.run(["git", "checkout", "badges"]) + + any_changes = False + for plugin_name, passed in data.items(): + any_changes |= update_and_commit_badge(plugin_name, passed, workflow) + + if any_changes: + subprocess.run(["git", "push", "origin", "badges"]) + print("Done.") + if __name__ == "__main__": - run_all(sys.argv[1:]) + import argparse + + parser = argparse.ArgumentParser(description='Plugins test script') + parser.add_argument("workflow", type=str, help="Name of the GitHub workflow") + parser.add_argument("--update-badges", action='store_true', help="Whether badges data should be updated") + parser.add_argument("plugins", nargs="*", default=[], help="List of plugins") + args = parser.parse_args() + + run_all(args.workflow, args.update_badges, args.plugins) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e8d8c8ed4..3b3a9cf80 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -98,7 +98,14 @@ jobs: # Run the tests: In the case of a 'pull_request' event only the plugins in `plugin_dirs` # are going to be tested; otherwise ('push' event) we test all plugins. - python3 .ci/test.py $(echo "$plugin_dirs") + + update_badges='' + if [[ "${{ github.event_name }}" == 'push' && "${{ github.ref }}" == 'refs/heads/master' ]] || [[ "${{ github.event_name }}" == 'schedule' ]] + then + update_badges='--update-badges' + fi + + python3 .ci/test.py main $update_badges $(echo "$plugin_dirs") gather: # A dummy task that depends on the full matrix of tests, and diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 8abfde298..ce3859ea4 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -91,7 +91,7 @@ jobs: export CLN_PATH=${{ github.workspace }}/lightning pip3 install --upgrade pip pip3 install --user -U virtualenv pip > /dev/null - python3 .ci/test.py + python3 .ci/test.py nightly --update-badges gather: # A dummy task that depends on the full matrix of tests, and