Skip to content

Commit f1b7f52

Browse files
committed
When configuring fails in Github Actions, print folded logs
A common, and challenging, issue in CI runners is debugging issues when you know the information you want to check, but it's in the log file which you don't have because remote CI machines. There are various edge cases where this is especially hard to solve, such as inside of `pip install` where the build directory with the log file is automatically cleaned up. But it's never really *easy* when you don't expect it, and the best case scenario is your iteration time gets cut in half as you hurriedly go add some `cat`s to your CI scripts. Meson can, at least sometimes, detect platforms where text can be emitted inside of "folds", which are auto-collapsed and don't obscure the general output, but when clicked will expand the logfile contents. Hook this up. We start off with a Github Actions implementation. We had some internal code used by our own project tests runner, which can be utilized. Also permit forcing it via an environment variable, in case autodetection fails and you just want to force *something*, especially when meson is called a couple layers deep inside some other tool. (cherry picked from commit 2b80d4c)
1 parent c726ca4 commit f1b7f52

File tree

3 files changed

+36
-9
lines changed

3 files changed

+36
-9
lines changed

mesonbuild/mesonmain.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ def errorhandler(e: Exception, command: str) -> int:
2727
logfile = mlog.shutdown()
2828
if logfile is not None:
2929
mlog.log("\nA full log can be found at", mlog.bold(logfile))
30+
contents = mlog.ci_fold_file(logfile, f'CI platform detected, click here for {os.path.basename(logfile)} contents.')
31+
if contents:
32+
print(contents)
3033
if os.environ.get('MESON_FORCE_BACKTRACE'):
3134
raise e
3235
return 1

mesonbuild/mlog.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222
from pathlib import Path
2323

2424
if T.TYPE_CHECKING:
25-
from ._typing import StringProtocol, SizedStringProtocol
25+
from typing_extensions import Literal
2626

27+
from ._typing import StringProtocol, SizedStringProtocol
2728
from .mparser import BaseNode
2829

2930
TV_Loggable = T.Union[str, 'AnsiDecorator', StringProtocol]
@@ -75,6 +76,7 @@ def setup_console() -> None:
7576
pass
7677

7778
_in_ci = 'CI' in os.environ
79+
_ci_is_github = 'GITHUB_ACTIONS' in os.environ
7880

7981

8082
class _Severity(enum.Enum):
@@ -540,3 +542,30 @@ def code_line(text: str, line: str, colno: int) -> str:
540542
:return: A formatted string of the text, line, and a caret
541543
"""
542544
return f'{text}\n{line}\n{" " * colno}^'
545+
546+
@T.overload
547+
def ci_fold_file(fname: T.Union[str, os.PathLike], banner: str, force: Literal[True] = True) -> str: ...
548+
549+
@T.overload
550+
def ci_fold_file(fname: T.Union[str, os.PathLike], banner: str, force: Literal[False] = False) -> T.Optional[str]: ...
551+
552+
def ci_fold_file(fname: T.Union[str, os.PathLike], banner: str, force: bool = False) -> T.Optional[str]:
553+
if not _in_ci and not force:
554+
return None
555+
556+
if _ci_is_github:
557+
header = f'::group::==== {banner} ===='
558+
footer = '::endgroup::'
559+
elif force:
560+
header = banner
561+
footer = ''
562+
elif 'MESON_FORCE_SHOW_LOGS' in os.environ:
563+
header = f'==== Forcing display of logs for {os.path.basename(fname)} ===='
564+
footer = ''
565+
else:
566+
# only github is implemented
567+
return None
568+
569+
with open(fname, 'r', encoding='utf-8') as f:
570+
data = f.read()
571+
return f'{header}\n{data}\n{footer}\n'

run_project_tests.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,6 @@ def __lt__(self, other: object) -> bool:
305305
failing_logs: T.List[str] = []
306306
print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ
307307
under_ci = 'CI' in os.environ
308-
ci_is_github = 'GITHUB_ACTIONS' in os.environ
309308
raw_ci_jobname = os.environ.get('MESON_CI_JOBNAME', None)
310309
ci_jobname = raw_ci_jobname if raw_ci_jobname != 'thirdparty' else None
311310
do_debug = under_ci or print_debug
@@ -437,16 +436,12 @@ def log_text_file(logfile: T.TextIO, testdir: Path, result: TestResult) -> None:
437436

438437

439438
def _run_ci_include(args: T.List[str]) -> str:
440-
header = f'Included file {args[0]}:'
441-
footer = ''
442-
if ci_is_github:
443-
header = f'::group::==== {header} ===='
444-
footer = '::endgroup::'
445439
if not args:
446440
return 'At least one parameter required'
441+
442+
header = f'Included file {args[0]}:'
447443
try:
448-
data = Path(args[0]).read_text(errors='ignore', encoding='utf-8')
449-
return f'{header}\n{data}\n{footer}\n'
444+
return mlog.ci_fold_file(args[0], header, force=True)
450445
except Exception:
451446
return 'Failed to open {}\n'.format(args[0])
452447

0 commit comments

Comments
 (0)