2
2
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
3
3
#
4
4
from abc import ABC
5
- from datetime import datetime
6
- from pathlib import Path
7
- from typing import Any , ClassVar , List , Optional , Tuple , cast
5
+ from typing import Any , ClassVar , List , Optional , Tuple
8
6
9
7
import pipelines .dagger .actions .system .docker
10
- from dagger import CacheSharingMode , CacheVolume , Container , QueryError
8
+ from dagger import CacheSharingMode , CacheVolume , Container , ExecError
11
9
from pipelines .airbyte_ci .connectors .context import ConnectorContext
12
10
from pipelines .consts import AMAZONCORRETTO_IMAGE
13
11
from pipelines .dagger .actions import secrets
14
12
from pipelines .hacks import never_fail_exec
15
- from pipelines .helpers .utils import sh_dash_c
13
+ from pipelines .helpers .utils import dagger_directory_as_zip_file , sh_dash_c
14
+ from pipelines .models .artifacts import Artifact
16
15
from pipelines .models .steps import Step , StepResult
17
16
18
17
@@ -38,15 +37,6 @@ class GradleTask(Step, ABC):
38
37
with_test_artifacts : ClassVar [bool ] = False
39
38
accept_extra_params = True
40
39
41
- @property
42
- def airbyte_logs_subdir (self ) -> str :
43
- return datetime .fromtimestamp (cast (float , self .context .pipeline_start_timestamp )).isoformat () + "-" + self .gradle_task_name
44
-
45
- @property
46
- def test_artifacts_path (self ) -> Path :
47
- test_artifacts_path = f"{ self .context .connector .code_directory } /build/test-artifacts/{ self .airbyte_logs_subdir } "
48
- return Path (test_artifacts_path )
49
-
50
40
@property
51
41
def gradle_task_options (self ) -> Tuple [str , ...]:
52
42
return self .STATIC_GRADLE_OPTIONS + (f"-Ds3BuildCachePrefix={ self .context .connector .technical_name } " ,)
@@ -111,8 +101,6 @@ async def _run(self, *args: Any, **kwargs: Any) -> StepResult:
111
101
.with_env_variable ("GRADLE_HOME" , self .GRADLE_HOME_PATH )
112
102
# Same for GRADLE_USER_HOME.
113
103
.with_env_variable ("GRADLE_USER_HOME" , self .GRADLE_HOME_PATH )
114
- # Set the AIRBYTE_LOG_SUBDIR for log4j
115
- .with_env_variable ("AIRBYTE_LOG_SUBDIR" , self .airbyte_logs_subdir )
116
104
# Install a bunch of packages as early as possible.
117
105
.with_exec (
118
106
sh_dash_c (
@@ -203,11 +191,18 @@ async def _run(self, *args: Any, **kwargs: Any) -> StepResult:
203
191
connector_gradle_task = f":airbyte-integrations:connectors:{ self .context .connector .technical_name } :{ self .gradle_task_name } "
204
192
gradle_command = self ._get_gradle_command (connector_gradle_task , task_options = self .params_as_cli_options )
205
193
gradle_container = gradle_container .with_ (never_fail_exec ([gradle_command ]))
206
- await self ._collect_logs (gradle_container )
207
- await self ._collect_test_report (gradle_container )
208
- return await self .get_step_result (gradle_container )
209
194
210
- async def get_step_result (self , container : Container ) -> StepResult :
195
+ # Collect the test artifacts, if applicable.
196
+ artifacts = []
197
+ if self .with_test_artifacts :
198
+ if test_logs := await self ._collect_test_logs (gradle_container ):
199
+ artifacts .append (test_logs )
200
+ if test_results := await self ._collect_test_results (gradle_container ):
201
+ artifacts .append (test_results )
202
+
203
+ return await self .get_step_result (gradle_container , artifacts )
204
+
205
+ async def get_step_result (self , container : Container , output_artifacts : List [Artifact ]) -> StepResult :
211
206
step_result = await super ().get_step_result (container )
212
207
# Decorate with test report, if applicable.
213
208
return StepResult (
@@ -216,48 +211,62 @@ async def get_step_result(self, container: Container) -> StepResult:
216
211
stdout = step_result .stdout ,
217
212
stderr = step_result .stderr ,
218
213
output_artifact = step_result .output_artifact ,
219
- test_artifacts_path = self . test_artifacts_path ,
214
+ artifacts = output_artifacts ,
220
215
)
221
216
222
- async def _collect_logs (self , gradle_container : Container ) -> None :
217
+ async def _collect_test_logs (self , gradle_container : Container ) -> Optional [ Artifact ] :
223
218
"""
224
219
Exports the java docs from the container into the host filesystem.
225
220
The docs in the container are expected to be in build/test-logs, and will end up test-artifact directory by default
226
- One can change the destination directory by setting the test_artifacts_path
221
+ One can change the destination directory by setting the output_artifacts
227
222
"""
228
- if not self .with_test_artifacts :
223
+ test_logs_dir_name = "test-logs"
224
+ if test_logs_dir_name not in await gradle_container .directory (f"{ self .context .connector .code_directory } /build" ).entries ():
225
+ self .context .logger .warn (f"No { test_logs_dir_name } found directory in the build folder" )
229
226
return None
230
- logs_dir_path = f"{ self .context .connector .code_directory } /build/test-logs/{ self .airbyte_logs_subdir } "
231
227
try :
232
- container_logs_dir = await gradle_container .directory (logs_dir_path )
233
- # the gradle task didn't create any logs.
234
- if not container_logs_dir :
235
- return None
236
-
237
- self .test_artifacts_path .mkdir (parents = True , exist_ok = True )
238
- if not await container_logs_dir .export (str (self .test_artifacts_path )):
239
- self .context .logger .error ("Error when trying to export log files from container" )
240
- except QueryError as e :
228
+ zip_file = await (
229
+ dagger_directory_as_zip_file (
230
+ self .dagger_client ,
231
+ await gradle_container .directory (f"{ self .context .connector .code_directory } /build/{ test_logs_dir_name } " ),
232
+ test_logs_dir_name ,
233
+ )
234
+ )
235
+ return Artifact (
236
+ name = "test-logs.zip" ,
237
+ content = zip_file ,
238
+ content_type = "application/zip" ,
239
+ to_upload = True ,
240
+ )
241
+ except ExecError as e :
241
242
self .context .logger .error (str (e ))
242
- self .context .logger .warn (f"Failed to retrieve junit test results from { logs_dir_path } gradle container." )
243
- return None
243
+ return None
244
244
245
- async def _collect_test_report (self , gradle_container : Container ) -> None :
245
+ async def _collect_test_results (self , gradle_container : Container ) -> Optional [ Artifact ] :
246
246
"""
247
247
Exports the junit test reports from the container into the host filesystem.
248
248
The docs in the container are expected to be in build/test-results, and will end up test-artifact directory by default
249
249
Only the XML files generated by junit are downloaded into the host filesystem
250
- One can change the destination directory by setting the test_artifacts_path
250
+ One can change the destination directory by setting the output_artifacts
251
251
"""
252
- if not self .with_test_artifacts :
252
+ test_results_dir_name = "test-results"
253
+ if test_results_dir_name not in await gradle_container .directory (f"{ self .context .connector .code_directory } /build" ).entries ():
254
+ self .context .logger .warn (f"No { test_results_dir_name } found directory in the build folder" )
253
255
return None
254
-
255
- junit_xml_path = f"{ self .context .connector .code_directory } /build/test-results/{ self .gradle_task_name } "
256
256
try :
257
- junit_xml_dir = await gradle_container .directory (junit_xml_path )
258
- for file_name in await junit_xml_dir .entries ():
259
- if file_name .endswith (".xml" ):
260
- await junit_xml_dir .file (file_name ).export (str (self .test_artifacts_path ), allow_parent_dir_path = True )
261
- except QueryError as e :
257
+ zip_file = await (
258
+ dagger_directory_as_zip_file (
259
+ self .dagger_client ,
260
+ await gradle_container .directory (f"{ self .context .connector .code_directory } /build/{ test_results_dir_name } " ),
261
+ test_results_dir_name ,
262
+ )
263
+ )
264
+ return Artifact (
265
+ name = "test-results.zip" ,
266
+ content = zip_file ,
267
+ content_type = "application/zip" ,
268
+ to_upload = True ,
269
+ )
270
+ except ExecError as e :
262
271
self .context .logger .error (str (e ))
263
272
return None
0 commit comments