1212import time
1313import subprocess
1414import shlex
15+ import re
16+ from urllib .parse import urlparse
1517
1618
1719BASE_URI = "https://staging.kernelci.org:9000/latest"
@@ -38,6 +40,19 @@ def retrieve_job_definition(url):
3840 return response .json ()
3941
4042
43+ def parse_job_definition_url (url ):
44+ """Extract date and job ID from job definition URL."""
45+ try :
46+ parsed = urlparse (url )
47+ path = parsed .path
48+ match = re .search (r'/pull_labs_jobs/(\d{8})/([a-f0-9]+)\.json' , path )
49+ if match :
50+ return match .group (1 ), match .group (2 )
51+ except Exception as e :
52+ print (f"Failed to parse job definition URL: { e } " )
53+ return None , None
54+
55+
4156def run_tuxrun (kernel_url , modules_url , device = "qemu-x86_64" , tests = None , rootfs_url = None , cache_dir = None ):
4257 """
4358 Launch a test using tuxrun
@@ -67,8 +82,8 @@ def run_tuxrun(kernel_url, modules_url, device="qemu-x86_64", tests=None, rootfs
6782
6883 if cache_dir :
6984 os .makedirs (cache_dir , exist_ok = True )
70- cmd .extend (["--save-outputs" , "--cache-dir" , cache_dir ])
71- print (f"Outputs will be saved to: { cache_dir } " )
85+ cmd .extend (["--save-outputs" , "--cache-dir" , cache_dir , "--log-file" , "-" ])
86+ print (f"✓ Outputs will be saved to: { cache_dir } " )
7287
7388 print (f"Executing command: { ' ' .join (shlex .quote (arg ) for arg in cmd )} " )
7489
@@ -80,7 +95,7 @@ def run_tuxrun(kernel_url, modules_url, device="qemu-x86_64", tests=None, rootfs
8095 return result .returncode
8196 except (subprocess .CalledProcessError , FileNotFoundError ) as e :
8297 print (f"\n ✗ Error running tuxrun: { e } " )
83- return e .returncode
98+ return e .returncode if hasattr ( e , 'returncode' ) else 1
8499
85100
86101def prepare_and_run (artifacts , device = "qemu-x86_64" , tests = None , rootfs_override = None , cache_dir = None ):
@@ -96,7 +111,6 @@ def prepare_and_run(artifacts, device="qemu-x86_64", tests=None, rootfs_override
96111 """
97112 kernel_url = artifacts .get ("kernel" )
98113 modules_url = artifacts .get ("modules" )
99- # Try rootfs first, then ramdisk as fallback
100114 rootfs_url = rootfs_override if rootfs_override else (artifacts .get ("rootfs" ) or artifacts .get ("ramdisk" ))
101115
102116 if not kernel_url or not modules_url :
@@ -137,7 +151,13 @@ def main():
137151 )
138152 parser .add_argument (
139153 "--cache-dir" ,
140- help = "Directory to save tuxrun outputs and cache (e.g., ./outputs). Enables --save-outputs flag." ,
154+ default = "./test_output" ,
155+ help = "Directory to save tuxrun outputs and cache (default: ./test_output). Use --no-save-outputs to disable." ,
156+ )
157+ parser .add_argument (
158+ "--no-save-outputs" ,
159+ action = "store_true" ,
160+ help = "Disable saving outputs (overrides --cache-dir)" ,
141161 )
142162 parser .add_argument (
143163 "--platform" ,
@@ -242,9 +262,13 @@ def main():
242262 continue
243263
244264 cache_dir = None
245- if args .cache_dir :
246- node_id = node .get ("id" , "unknown" )
247- cache_dir = os .path .join (args .cache_dir , node_id )
265+ if not args .no_save_outputs and args .cache_dir :
266+ date , job_id = parse_job_definition_url (job_definition_url )
267+ if date and job_id :
268+ cache_dir = os .path .join (args .cache_dir , date , job_id )
269+ else :
270+ node_id = node .get ("id" , "unknown" )
271+ cache_dir = os .path .join (args .cache_dir , node_id )
248272
249273 prepare_and_run (
250274 job_artifacts ,
0 commit comments