Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 102 additions & 30 deletions .ci/test.py
Original file line number Diff line number Diff line change
@@ -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)

Expand All @@ -18,8 +17,8 @@
'.ci',
'.git',
'.github',
'archived',
'lightning',
'feeadjuster'
]

global_dependencies = [
Expand Down Expand Up @@ -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(
Expand All @@ -70,16 +71,16 @@ def enumerate_plugins(basedir: Path) -> Generator[Plugin, None, None]:
}
)

for p in sorted(poetry_pytest):
yield Plugin(
name=p.name,
path=p,
language="python",
framework="poetry",
details={
"pyproject": p / Path("pyproject.toml"),
}
)
# for p in sorted(poetry_pytest):
# yield Plugin(
# name=p.name,
# path=p,
# language="python",
# framework="poetry",
# details={
# "pyproject": p / Path("pyproject.toml"),
# }
# )

for p in sorted(other_plugins):
yield Plugin(
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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',
Expand All @@ -306,20 +311,87 @@ 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))

results = [(p, run_one(p)) for p in plugins]
success = all([t[1] for t in results])

badges_data = {}
if update_badges:
badges_data = collect_badges_data(results, success)

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.")

return badges_data


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.")

def main(args):
return run_all(args.workflow, args.update_badges, args.plugins)

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()

main(args)
24 changes: 24 additions & 0 deletions .ci/update_badges.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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__":
import argparse

parser = argparse.ArgumentParser(description='Plugins completion script')
parser.add_argument("data", nargs="*", default={}, help="Badges update data")
parser.add_argument("workflow", type=str, help="Name of the GitHub workflow")
args = parser.parse_args()

push_badges_data(args.data, args.workflow)
13 changes: 12 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ jobs:
python-version: ${{ matrix.python-version }}

- name: Run pytest tests
id: pytest_tests
run: |
export CLN_PATH=${{ github.workspace }}/lightning
export COMPAT=${{ matrix.deprecated }}
Expand All @@ -98,7 +99,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

echo "badges_data=$(python3 .ci/test.py main $update_badges $(echo $plugin_dirs))" >> "$GITHUB_OUTPUT"

gather:
# A dummy task that depends on the full matrix of tests, and
Expand All @@ -111,4 +119,7 @@ jobs:
steps:
- name: Complete
run: |
echo "Updating badges data..."
echo "${{ needs.build-and-test.outputs.my_output_key }}"
python3 .ci/update_badges.py ${{ needs.build-and-test.outputs.badges_data }} main
echo CI completed successfully
2 changes: 1 addition & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading