Skip to content

Commit 8d6a533

Browse files
committed
refactor: redirect pytest output to log file without ANSI sequences
Signed-off-by: Gaëtan Lehmann <gaetan.lehmann@vates.tech>
1 parent 44dde91 commit 8d6a533

1 file changed

Lines changed: 34 additions & 8 deletions

File tree

compat_kit/entrypoint.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import getpass
1919
import logging
2020
import os
21+
import re
2122
import shutil
2223
import subprocess
2324
import sys
@@ -350,8 +351,6 @@ def run_pytest(phase: int, test_args: list[str], log_file: str) -> None:
350351
'--color=yes',
351352
'--no-header',
352353
'--maxfail=0',
353-
'--log-file-level=debug',
354-
f'--log-file={log_path}',
355354
f'--log-cli-level={logging.getLevelName(state.log_level)}',
356355
f'--vm={state.vm_image_url}',
357356
] + test_args
@@ -363,16 +362,43 @@ def run_pytest(phase: int, test_args: list[str], log_file: str) -> None:
363362

364363
logging.debug(f"Running: {' '.join(cmd)}")
365364
try:
366-
subprocess.run(cmd, check=True, timeout=3600)
367-
logging.info(f"Phase {phase}: Tests completed successfully")
368-
except subprocess.CalledProcessError as e:
369-
logging.warning(f"Phase {phase}: Tests failed with exit code {e.returncode}")
370-
state.tests_failed = True
371-
# Don't raise, allow other phases to run
365+
ansi_escape = re.compile(br'\x1b\[[0-9;]*[a-zA-Z]')
366+
367+
# Launch pytest. We force colors so the terminal output stays pretty.
368+
# 'bufsize=1' and 'universal_newlines=False' allow us to process line by line.
369+
process = subprocess.Popen(
370+
cmd,
371+
stdout=subprocess.PIPE,
372+
stderr=subprocess.STDOUT
373+
)
374+
375+
assert process.stdout is not None
376+
with open(log_path, "wb") as f:
377+
# Read from the pipe until the process finishes
378+
for line in iter(process.stdout.readline, b''):
379+
# 1. Write the original colorful line to the actual terminal
380+
sys.stdout.buffer.write(line)
381+
sys.stdout.buffer.flush()
382+
383+
# 2. Strip the codes and write the clean text to the file
384+
clean_line = ansi_escape.sub(b'', line)
385+
f.write(clean_line)
386+
f.flush()
387+
388+
process.wait()
389+
if process.returncode != 0:
390+
logging.warning(f"Phase {phase}: Tests failed with exit code {process.returncode}")
391+
state.tests_failed = True
392+
else:
393+
logging.info(f"Phase {phase}: Tests completed successfully")
372394
except subprocess.TimeoutExpired:
373395
logging.error(f"Phase {phase}: Tests timed out")
374396
state.tests_failed = True
375397
raise
398+
except Exception as e:
399+
logging.error(f"Phase {phase}: Tests failed: {e}")
400+
state.tests_failed = True
401+
raise
376402

377403

378404
def setup_config_files() -> None:

0 commit comments

Comments
 (0)