@@ -1194,9 +1194,7 @@ def create_instance(compute, project, zone, test, reportURL) -> Dict:
11941194 startup_script = f .read ()
11951195 metadata_items = [
11961196 {'key' : 'startup-script' , 'value' : startup_script },
1197- {'key' : 'reportURL' , 'value' : reportURL },
1198- {'key' : 'bucket' , 'value' : config .get ('GCS_BUCKET_NAME' , '' )},
1199- {'key' : 'testID' , 'value' : str (test .id )}
1197+ {'key' : 'reportURL' , 'value' : reportURL }
12001198 ]
12011199 elif test .platform == TestPlatform .windows :
12021200 image_response = compute .images ().getFromFamily (project = config .get ('WINDOWS_INSTANCE_PROJECT_NAME' , '' ),
@@ -1217,9 +1215,7 @@ def create_instance(compute, project, zone, test, reportURL) -> Dict:
12171215 {'key' : 'windows-startup-script-ps1' , 'value' : startup_script },
12181216 {'key' : 'service_account' , 'value' : service_account },
12191217 {'key' : 'rclone_conf' , 'value' : rclone_conf },
1220- {'key' : 'reportURL' , 'value' : reportURL },
1221- {'key' : 'bucket' , 'value' : config .get ('GCS_BUCKET_NAME' , '' )},
1222- {'key' : 'testID' , 'value' : str (test .id )}
1218+ {'key' : 'reportURL' , 'value' : reportURL }
12231219 ]
12241220 source_disk_image = image_response ['selfLink' ]
12251221
@@ -2346,6 +2342,11 @@ def progress_reporter(test_id, token):
23462342 if not upload_type_request (log , test_id , repo_folder , test , request ):
23472343 return "EMPTY"
23482344
2345+ elif request .form ['type' ] == 'artifact' :
2346+ log .info (f'[PROGRESS_REPORTER][Test: { test_id } ] Artifact upload' )
2347+ if not artifact_upload_request (log , test_id , request ):
2348+ return "EMPTY"
2349+
23492350 elif request .form ['type' ] == 'finish' :
23502351 log .info (f'[PROGRESS_REPORTER][Test: { test_id } ] Test finished' )
23512352 finish_type_request (log , test_id , test , request )
@@ -2695,6 +2696,45 @@ def upload_type_request(log, test_id, repo_folder, test, request) -> bool:
26952696 return False
26962697
26972698
2699+ # Allowed artifact names that the VM can upload
2700+ ALLOWED_ARTIFACT_NAMES = {'ccextractor' , 'ccextractor.exe' , 'combined_stdout.log' , 'coredump' }
2701+
2702+
2703+ def artifact_upload_request (log , test_id , request ) -> bool :
2704+ """
2705+ Handle artifact upload from the CI VM.
2706+
2707+ Validates the artifact name against an allow-list, then uploads
2708+ the file to GCS under test_artifacts/{test_id}/{name}.
2709+
2710+ :param log: logger
2711+ :type log: Logger
2712+ :param test_id: The id of the test to update.
2713+ :type test_id: int
2714+ :param request: Request parameters
2715+ :type request: Request
2716+ :return: True if upload succeeded, False otherwise.
2717+ :rtype: bool
2718+ """
2719+ from run import storage_client_bucket
2720+
2721+ artifact_name = request .form .get ('name' , '' )
2722+ if artifact_name not in ALLOWED_ARTIFACT_NAMES :
2723+ log .warning (f"[Test: { test_id } ] Rejected artifact upload with disallowed name: { artifact_name } " )
2724+ return False
2725+
2726+ if 'file' not in request .files :
2727+ log .warning (f"[Test: { test_id } ] Artifact upload missing file" )
2728+ return False
2729+
2730+ uploaded_file = request .files ['file' ]
2731+ blob_path = f'test_artifacts/{ test_id } /{ artifact_name } '
2732+ blob = storage_client_bucket .blob (blob_path )
2733+ blob .upload_from_file (uploaded_file .stream )
2734+ log .info (f"[Test: { test_id } ] Artifact '{ artifact_name } ' uploaded to { blob_path } " )
2735+ return True
2736+
2737+
26982738def finish_type_request (log , test_id , test , request ):
26992739 """
27002740 Handle finish request type for progress reporter.
0 commit comments