mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-25 16:08:46 +09:00
Improve severity labels in Actions logs and tweak colors (#36993)
Add support for error, warning, notice, and debug log commands with bold label prefixes and colored backgrounds matching GitHub's style. Parse both `##[cmd]` and `::cmd args::` formats. Also improved the severity colors globally and added a devtest page for these. --------- Co-authored-by: Claude (claude-opus-4-6) <noreply@anthropic.com>
This commit is contained in:
@@ -229,7 +229,8 @@ function createLogLine(stepIndex: number, startTime: number, line: LogLine, cmd:
|
||||
toggleElem(logTimeStamp, timeVisible.value['log-time-stamp']);
|
||||
toggleElem(logTimeSeconds, timeVisible.value['log-time-seconds']);
|
||||
|
||||
return createElementFromAttrs('div', {id: `jobstep-${stepIndex}-${line.index}`, class: 'job-log-line'},
|
||||
const lineClass = cmd?.name ? `job-log-line log-line-${cmd.name}` : 'job-log-line';
|
||||
return createElementFromAttrs('div', {id: `jobstep-${stepIndex}-${line.index}`, class: lineClass},
|
||||
lineNum, logTimeStamp, logMsg, logTimeSeconds,
|
||||
);
|
||||
}
|
||||
@@ -650,8 +651,28 @@ async function hashChangeListener() {
|
||||
color: var(--color-ansi-blue);
|
||||
}
|
||||
|
||||
.job-step-logs .job-log-line .log-cmd-error {
|
||||
color: var(--color-ansi-red);
|
||||
.job-step-logs .log-msg-label {
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
.job-step-logs .log-line-error {
|
||||
background: var(--color-error-bg);
|
||||
}
|
||||
|
||||
.job-step-logs .log-line-warning {
|
||||
background: var(--color-warning-bg);
|
||||
}
|
||||
|
||||
.job-step-logs .log-cmd-error > .log-msg-label {
|
||||
color: var(--color-error-text);
|
||||
}
|
||||
|
||||
.job-step-logs .log-cmd-warning > .log-msg-label {
|
||||
color: var(--color-warning-text);
|
||||
}
|
||||
|
||||
.job-step-logs .log-cmd-debug {
|
||||
color: var(--color-violet);
|
||||
}
|
||||
|
||||
/* selectors here are intentionally exact to only match fullscreen */
|
||||
|
||||
@@ -8,8 +8,14 @@ test('LogLineMessage', () => {
|
||||
'##[endgroup]': '<span class="log-msg log-cmd-endgroup"></span>',
|
||||
'::endgroup::': '<span class="log-msg log-cmd-endgroup"></span>',
|
||||
|
||||
// parser shouldn't do any trim, keep origin output as-is
|
||||
'##[error] foo': '<span class="log-msg log-cmd-error"> foo</span>',
|
||||
'##[error] foo': '<span class="log-msg log-cmd-error"><span class="log-msg-label">Error:</span><span> foo</span></span>',
|
||||
'##[warning] foo': '<span class="log-msg log-cmd-warning"><span class="log-msg-label">Warning:</span><span> foo</span></span>',
|
||||
'##[notice] foo': '<span class="log-msg log-cmd-notice"><span class="log-msg-label">Notice:</span><span> foo</span></span>',
|
||||
'##[debug] foo': '<span class="log-msg log-cmd-debug"><span class="log-msg-label">Debug:</span><span> foo</span></span>',
|
||||
'::error::foo': '<span class="log-msg log-cmd-error"><span class="log-msg-label">Error:</span><span> foo</span></span>',
|
||||
'::warning file=test.js,line=1::foo': '<span class="log-msg log-cmd-warning"><span class="log-msg-label">Warning:</span><span> foo</span></span>',
|
||||
'::notice::foo': '<span class="log-msg log-cmd-notice"><span class="log-msg-label">Notice:</span><span> foo</span></span>',
|
||||
'::debug::foo': '<span class="log-msg log-cmd-debug"><span class="log-msg-label">Debug:</span><span> foo</span></span>',
|
||||
'[command] foo': '<span class="log-msg log-cmd-command"> foo</span>',
|
||||
|
||||
// hidden is special, it is actually skipped before creating
|
||||
|
||||
@@ -17,6 +17,9 @@ const LogLinePrefixCommandMap: Record<string, LogLineCommandName> = {
|
||||
'##[endgroup]': 'endgroup',
|
||||
|
||||
'##[error]': 'error',
|
||||
'##[warning]': 'warning',
|
||||
'##[notice]': 'notice',
|
||||
'##[debug]': 'debug',
|
||||
'[command]': 'command',
|
||||
|
||||
// https://github.com/actions/toolkit/blob/master/docs/commands.md
|
||||
@@ -26,13 +29,16 @@ const LogLinePrefixCommandMap: Record<string, LogLineCommandName> = {
|
||||
'::remove-matcher': 'hidden', // it has arguments
|
||||
};
|
||||
|
||||
// Pattern for ::cmd:: and ::cmd args:: format (args are stripped for display)
|
||||
const LogLineCmdPattern = /^::(error|warning|notice|debug)(?:\s[^:]*)?::/;
|
||||
|
||||
export type LogLine = {
|
||||
index: number;
|
||||
timestamp: number;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type LogLineCommandName = 'group' | 'endgroup' | 'command' | 'error' | 'hidden';
|
||||
export type LogLineCommandName = 'group' | 'endgroup' | 'command' | 'error' | 'warning' | 'notice' | 'debug' | 'hidden';
|
||||
export type LogLineCommand = {
|
||||
name: LogLineCommandName,
|
||||
prefix: string,
|
||||
@@ -45,19 +51,39 @@ export function parseLogLineCommand(line: LogLine): LogLineCommand | null {
|
||||
return {name: LogLinePrefixCommandMap[prefix], prefix};
|
||||
}
|
||||
}
|
||||
// Handle ::cmd:: and ::cmd args:: format (runner may pass these through raw)
|
||||
const match = LogLineCmdPattern.exec(line.message);
|
||||
if (match) {
|
||||
return {name: match[1] as LogLineCommandName, prefix: match[0]};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const LogLineLabelMap: Partial<Record<LogLineCommandName, string>> = {
|
||||
'error': 'Error',
|
||||
'warning': 'Warning',
|
||||
'notice': 'Notice',
|
||||
'debug': 'Debug',
|
||||
};
|
||||
|
||||
export function createLogLineMessage(line: LogLine, cmd: LogLineCommand | null) {
|
||||
const logMsgAttrs = {class: 'log-msg'};
|
||||
if (cmd?.name) logMsgAttrs.class += ` log-cmd-${cmd?.name}`; // make it easier to add styles to some commands like "error"
|
||||
if (cmd?.name) logMsgAttrs.class += ` log-cmd-${cmd.name}`; // make it easier to add styles to some commands like "error"
|
||||
|
||||
// TODO: for some commands (::group::), the "prefix removal" works well, for some commands with "arguments" (::remove-matcher ...::),
|
||||
// it needs to do further processing in the future (fortunately, at the moment we don't need to handle these commands)
|
||||
const msgContent = cmd ? line.message.substring(cmd.prefix.length) : line.message;
|
||||
|
||||
const logMsg = createElementFromAttrs('span', logMsgAttrs);
|
||||
logMsg.innerHTML = renderAnsi(msgContent);
|
||||
const label = cmd ? LogLineLabelMap[cmd.name] : null;
|
||||
if (label) {
|
||||
logMsg.append(createElementFromAttrs('span', {class: 'log-msg-label'}, `${label}:`));
|
||||
const msgSpan = document.createElement('span');
|
||||
msgSpan.innerHTML = ` ${renderAnsi(msgContent.trimStart())}`;
|
||||
logMsg.append(msgSpan);
|
||||
} else {
|
||||
logMsg.innerHTML = renderAnsi(msgContent);
|
||||
}
|
||||
return logMsg;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user