From 0d0daed7f5da2e1d57c615470b9c0484234bc3f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Fri, 20 Feb 2026 05:53:40 +0100 Subject: [PATCH] ci: cdrouter: validate package manifests before DUT bringup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the cdrouter pipeline validates package manifests only when package_apply runs in the script phase, after the DUT bringup and init steps in before_script. When a manifest has human errors, the job spends several minutes on setup before failing on package_apply. So lets add an explicit package_validate subcommand that reuses the same manifest resolution and package option checks without requiring API mutation, and execute it as the first operational step in before_script. This fails fast on manifest mistakes and avoids wasting DUT bringup time. References: PCF-2532 Assisted-by: codex:gpt-5.4:xhigh Assisted-by: claude:opus-4-6:1m-context Signed-off-by: Petr Štetiar --- .gitlab/cdrouter.yml | 3 +++ .gitlab/scripts/testbed-cdrouter.py | 35 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/.gitlab/cdrouter.yml b/.gitlab/cdrouter.yml index 030e29ca90..7f3b61f0e5 100644 --- a/.gitlab/cdrouter.yml +++ b/.gitlab/cdrouter.yml @@ -20,6 +20,9 @@ CDROUTER_ETH0_MAC_ADDRESS_TESTBED_02: 00:03:2d:49:2e:c8 before_script: + - export TEST_PACKAGE="$(echo $CI_JOB_NAME | sed 's/\(\w\) .*/\1/')" + - .gitlab/scripts/testbed-cdrouter.py package_validate $TEST_PACKAGE + - source .gitlab/scripts/helpers.sh - section_start "testbed-setup" "Testbed Setup" "collapsed" diff --git a/.gitlab/scripts/testbed-cdrouter.py b/.gitlab/scripts/testbed-cdrouter.py index 7d31d09969..ef9109b7cb 100755 --- a/.gitlab/scripts/testbed-cdrouter.py +++ b/.gitlab/scripts/testbed-cdrouter.py @@ -782,6 +782,33 @@ class TestbedCDRouter: p = self.cdr.packages.create(p) logging.info("Created package '{}' with {} tests".format(name, len(tests))) + def package_validate(self): + manifest_path = os.path.join( + self.packages_path, self.args.package_name + ".yaml" + ) + resolved = self.resolve_manifest(manifest_path) + + name = resolved["name"] + tests = resolved["tests"] + options = resolved.get("options", {}) + + if not name: + logging.error( + "Resolved manifest name is empty for '{}'".format(manifest_path) + ) + exit(1) + + if not tests: + logging.error("Resolved manifest has empty test list for '{}'".format(name)) + exit(1) + + self.build_package_options(options) + logging.info( + "Validated package manifest '{}' as '{}' with {} tests".format( + manifest_path, name, len(tests) + ) + ) + def main(): logging.basicConfig( @@ -852,6 +879,14 @@ def main(): ) subparser.set_defaults(func=TestbedCDRouter.package_apply) + subparser = subparsers.add_parser( + "package_validate", help="validate package YAML manifest" + ) + subparser.add_argument( + "package_name", help="package name (resolves to packages/.yaml)" + ) + subparser.set_defaults(func=TestbedCDRouter.package_validate) + subparser = subparsers.add_parser("config_export", help="export configuration") subparser.add_argument("name", help="configuration name") subparser.add_argument("filename", help="destination filename")