4
4
import json
5
5
import logging
6
6
import os
7
+ import re
7
8
import time
8
9
9
10
from pathlib import Path
10
11
from typing import Any
12
+ from typing import Callable
11
13
from typing import Dict
12
14
from typing import Generator
13
15
from typing import List
14
16
15
17
import pytest
16
18
19
+ from pluggy ._result import _Result as pluggy_result
20
+
17
21
from .defs import AnsibleProject
18
22
from .defs import CmlWrapper
19
23
from .defs import VirshWrapper
@@ -185,6 +189,24 @@ def required_environment_variables() -> Dict[str, str]:
185
189
return variables # type: ignore[return-value]
186
190
187
191
192
+ def _github_action_log (message : str ) -> None :
193
+ """Log a message to GitHub Actions.
194
+
195
+ :param message: The message
196
+ """
197
+ if os .environ .get ("GITHUB_ACTIONS" ):
198
+ print (f"\n { message } " , flush = True )
199
+
200
+
201
+ @pytest .fixture (scope = "session" , autouse = True )
202
+ def github_action_log () -> Callable [[str ], None ]:
203
+ """Log a message to GitHub Actions.
204
+
205
+ :returns: The log function
206
+ """
207
+ return _github_action_log
208
+
209
+
188
210
@pytest .fixture (scope = "session" , name = "appliance_dhcp_address" )
189
211
def _appliance_dhcp_address (env_vars : Dict [str , str ]) -> Generator [str , None , None ]:
190
212
"""Build the lab and collect the appliance DHCP address.
@@ -193,45 +215,57 @@ def _appliance_dhcp_address(env_vars: Dict[str, str]) -> Generator[str, None, No
193
215
:raises Exception: Missing environment variables, lab, or appliance
194
216
:yields: The appliance DHCP address
195
217
"""
196
- logger . info ( " Starting lab provisioning" )
218
+ _github_action_log ( "::group:: Starting lab provisioning" )
197
219
198
- if not OPTIONS :
199
- raise Exception ("Missing CML lab" )
200
- lab_file = OPTIONS .cml_lab
201
- if not os .path .exists (lab_file ):
202
- raise Exception (f"Missing lab file '{ lab_file } '" )
220
+ logger .info ("Starting lab provisioning" )
203
221
204
- start = time .time ()
205
- cml = CmlWrapper (
206
- host = env_vars ["cml_host" ],
207
- username = env_vars ["cml_ui_user" ],
208
- password = env_vars ["cml_ui_password" ],
209
- )
210
- cml .bring_up (file = lab_file )
211
- lab_id = cml .current_lab_id
222
+ try :
212
223
213
- virsh = VirshWrapper (
214
- host = env_vars ["cml_host" ],
215
- user = env_vars ["cml_ssh_user" ],
216
- password = env_vars ["cml_ssh_password" ],
217
- port = int (env_vars ["cml_ssh_port" ]),
218
- )
224
+ if not OPTIONS :
225
+ raise Exception ("Missing CML lab" )
226
+ lab_file = OPTIONS .cml_lab
227
+ if not os .path .exists (lab_file ):
228
+ raise Exception (f"Missing lab file '{ lab_file } '" )
229
+
230
+ start = time .time ()
231
+ cml = CmlWrapper (
232
+ host = env_vars ["cml_host" ],
233
+ username = env_vars ["cml_ui_user" ],
234
+ password = env_vars ["cml_ui_password" ],
235
+ )
236
+ cml .bring_up (file = lab_file )
237
+ lab_id = cml .current_lab_id
238
+
239
+ virsh = VirshWrapper (
240
+ host = env_vars ["cml_host" ],
241
+ user = env_vars ["cml_ssh_user" ],
242
+ password = env_vars ["cml_ssh_password" ],
243
+ port = int (env_vars ["cml_ssh_port" ]),
244
+ )
245
+
246
+ try :
247
+ ip_address = virsh .get_dhcp_lease (lab_id )
248
+ except Exception as exc :
249
+ virsh .close ()
250
+ cml .remove ()
251
+ raise Exception ("Failed to get DHCP lease for the appliance" ) from exc
252
+
253
+ end = time .time ()
254
+ logger .info ("Elapsed time to provision %s seconds" , end - start )
219
255
220
- try :
221
- ip_address = virsh .get_dhcp_lease (lab_id )
222
256
except Exception as exc :
223
- virsh .close ()
224
- cml .remove ()
225
- raise Exception ("Failed to get DHCP lease for the appliance" ) from exc
226
-
227
- end = time .time ()
228
- logger .info ("Elapsed time to provision %s seconds" , end - start )
257
+ logger .error ("Failed to provision lab" )
258
+ _github_action_log ("::endgroup::" )
259
+ raise Exception ("Failed to provision lab" ) from exc
229
260
230
261
virsh .close ()
262
+ _github_action_log ("::endgroup::" )
231
263
232
264
yield ip_address
233
265
266
+ _github_action_log ("::group::Removing lab" )
234
267
cml .remove ()
268
+ _github_action_log ("::endgroup::" )
235
269
236
270
237
271
@pytest .fixture
@@ -293,3 +327,45 @@ def environment() -> Dict[str, Any]:
293
327
if "VIRTUAL_ENV" in os .environ :
294
328
env ["PATH" ] = os .path .join (os .environ ["VIRTUAL_ENV" ], "bin" ) + os .pathsep + env ["PATH" ]
295
329
return env
330
+
331
+
332
+ @pytest .hookimpl (tryfirst = True , hookwrapper = True ) # type: ignore[misc]
333
+ def pytest_runtest_makereport (
334
+ item : pytest .Item , * _args : Any , ** _kwargs : Any
335
+ ) -> Generator [None , pluggy_result , None ]:
336
+ """Add additional information to the test item.
337
+
338
+ :param item: The test item
339
+ :param _args: The positional arguments
340
+ :param _kwargs: The keyword arguments
341
+ :yields: To all other hooks
342
+ """
343
+ # execute all other hooks to obtain the report object
344
+ outcome = yield
345
+ rep = outcome .get_result ()
346
+
347
+ # set a report attribute for each phase of a call, which can
348
+ # be "setup", "call", "teardown"
349
+
350
+ setattr (item , "rep_" + rep .when , rep )
351
+
352
+
353
+ @pytest .fixture (autouse = True )
354
+ def github_log (request : pytest .FixtureRequest ) -> Generator [None , None , None ]:
355
+ """Log a message to GitHub Actions.
356
+
357
+ :param request: The request
358
+ :yields: To the test
359
+ """
360
+ if not os .environ .get ("GITHUB_ACTIONS" ):
361
+ return
362
+
363
+ name = request .node .name
364
+
365
+ _github_action_log (f"::group::Run integration test: '{ name } '" )
366
+ yield
367
+
368
+ if request .node .rep_setup .passed and request .node .rep_call .failed :
369
+ _github_action_log (f"::error title=Integration test failure::{ name } " )
370
+
371
+ _github_action_log ("::endgroup::" )
0 commit comments