From 1f035c4456fb3e1d87841acac4427a564a283650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Pi=C3=A9dallu?= Date: Sun, 9 Jun 2024 23:22:03 +0200 Subject: [PATCH 1/2] Use a wrapper for file-backed cached functions --- package_linter.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/package_linter.py b/package_linter.py index 1fd51ef..e18773f 100755 --- a/package_linter.py +++ b/package_linter.py @@ -310,26 +310,27 @@ def file_exists(file_path): return os.path.isfile(file_path) and os.stat(file_path).st_size > 0 +def cache_file(cachefile: str, ttl_s: int): + def cache_is_fresh(): + return os.path.exists(cachefile) and time.time() - os.path.getmtime(cachefile) < ttl_s + def decorator(function): + def wrapper(*args, **kwargs): + if not cache_is_fresh(): + with open(cachefile, "w+") as outfile: + outfile.write(function(*args, **kwargs)) + return open(cachefile).read() + return wrapper + return decorator + + +@cache_file(".spdx_licenses", 3600) def spdx_licenses(): - cachefile = ".spdx_licenses" - if os.path.exists(cachefile) and time.time() - os.path.getmtime(cachefile) < 3600: - return open(cachefile).read() - - url = "https://spdx.org/licenses/" - content = urlopen(url)["content"] - open(cachefile, "w").write(content) - return content + return urlopen("https://spdx.org/licenses/")["content"] +@cache_file(".manifest.v2.schema.json", 3600) def manifest_v2_schema(): - cachefile = ".manifest.v2.schema.json" - if os.path.exists(cachefile) and time.time() - os.path.getmtime(cachefile) < 3600: - return json.loads(open(cachefile).read()) - - url = "https://raw.githubusercontent.com/YunoHost/apps/master/schemas/manifest.v2.schema.json" - content = urlopen(url)["content"] - open(cachefile, "w").write(content) - return json.loads(content) + return urlopen("https://raw.githubusercontent.com/YunoHost/apps/master/schemas/manifest.v2.schema.json")["content"] tests = {} From 1c4eff6a407985f41fa993ebc6b88ac3f7683c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Pi=C3=A9dallu?= Date: Sun, 9 Jun 2024 23:25:03 +0200 Subject: [PATCH 2/2] Lint the tests.toml and config_panel.toml with schemas too --- package_linter.py | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/package_linter.py b/package_linter.py index e18773f..c771a43 100755 --- a/package_linter.py +++ b/package_linter.py @@ -333,6 +333,27 @@ def manifest_v2_schema(): return urlopen("https://raw.githubusercontent.com/YunoHost/apps/master/schemas/manifest.v2.schema.json")["content"] +@cache_file(".tests.v1.schema.json", 3600) +def tests_v1_schema(): + return urlopen("https://raw.githubusercontent.com/YunoHost/apps/master/schemas/tests.v1.schema.json")["content"] + + +@cache_file(".config_panel.v1.schema.json", 3600) +def config_panel_v1_schema(): + return urlopen("https://raw.githubusercontent.com/YunoHost/apps/master/schemas/config_panel.v1.schema.json")["content"] + + +def validate_schema(name: str, schema, data): + v = jsonschema.Draft7Validator(schema) + + for error in v.iter_errors(data): + try: + error_path = " > ".join(error.path) + except: + error_path = str(error.path) + + yield Info(f"Error validating {name} using schema: in key {error_path}\n {error.message}") + tests = {} tests_reports = { "success": [], @@ -761,6 +782,8 @@ class App(TestSuite): "The config panel is set to version 1.x, but the config script is apparently still using some old code from 0.1 such as '$YNH_CONFIG_STUFF' or 'yunohost app action'" ) + validate_schema("config_panel", config_panel_v1_schema(), toml.load(app.path + "config_panel.toml")) + @test() def badges_in_readme(app): @@ -1158,7 +1181,7 @@ class Configurations(TestSuite): ############################ @test() - def tests_toml_exists(self): + def tests_toml(self): app = self.app @@ -1174,6 +1197,8 @@ class Configurations(TestSuite): yield Error( "The 'check_process' file that interfaces with the app CI has now been replaced with 'tests.toml' format and is now mandatory for apps v2." ) + else: + validate_schema("tests.toml", tests_v1_schema(), toml.load(app.path + "tests.toml")) @test() def check_process_syntax(self): @@ -2230,24 +2255,9 @@ class Manifest(TestSuite): @test() def manifest_schema(self): - - v = jsonschema.Draft7Validator(manifest_v2_schema()) - if app_packaging_format <= 1: return - - for error in v.iter_errors(self.manifest): - try: - error_path = " > ".join(error.path) - except: - error_path = str(error.path) - - yield Info( - "Error validating manifest using schema: in key " - + error_path - + "\n " - + error.message - ) + validate_schema("manifest", manifest_v2_schema(), self.manifest) ########################################