mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-31 21:48:19 +00:00
fix: make Actions log parser support multiple line message encoding (#38659)
fix #38652 UI part (`.log-msg`) uses "white-space: break-spaces;" so the new line can be correctly rendered. --------- Signed-off-by: silverwind <me@silverwind.io> Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
@@ -722,7 +722,7 @@ async function hashChangeListener() {
|
||||
|
||||
.job-step-logs .job-log-line .log-msg {
|
||||
flex: 1;
|
||||
white-space: break-spaces;
|
||||
white-space: break-spaces; /* decoded commands like "::error::foo%0Abar" contain "\n" */
|
||||
margin-left: 12px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,13 @@ test('LogLineMessage', () => {
|
||||
'##[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>',
|
||||
'::error::foo%0Abar': '<span class="log-msg log-cmd-error"><span class="log-msg-label">Error:</span><span> foo\nbar</span></span>',
|
||||
'::error::foo%0D%0Abar': '<span class="log-msg log-cmd-error"><span class="log-msg-label">Error:</span><span> foo\nbar</span></span>',
|
||||
'::error::100%25 done%250A': '<span class="log-msg log-cmd-error"><span class="log-msg-label">Error:</span><span> 100% done%0A</span></span>',
|
||||
'::error::keep%5Dsemi%3B': '<span class="log-msg log-cmd-error"><span class="log-msg-label">Error:</span><span> keep%5Dsemi%3B</span></span>',
|
||||
'::group::foo%0Abar': '<span class="log-msg log-cmd-group">foo\nbar</span>',
|
||||
'##[error]foo%0Abar%3B%5D': '<span class="log-msg log-cmd-error"><span class="log-msg-label">Error:</span><span> foo\nbar;]</span></span>',
|
||||
'##[command]foo%0Abar': '<span class="log-msg log-cmd-command">foo%0Abar</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>',
|
||||
|
||||
@@ -9,7 +9,8 @@ import {POST} from '../modules/fetch.ts';
|
||||
// * Workflow command outputs log commands like "::group::the-title", "::add-matcher::...."
|
||||
// * Workflow runner parses and processes the commands to "##[group]", apply "matchers", hide secrets, etc.
|
||||
// * The reported logs are the processed logs.
|
||||
// HOWEVER: Gitea runner does not completely process those commands. Many works are done by the frontend at the moment.
|
||||
// HOWEVER: Gitea cannot, a decoded message may contain newlines and FormatLog drops them,
|
||||
// so the commands arrive here still escaped and the frontend decodes them.
|
||||
const LogLinePrefixCommandMap: Record<string, LogLineCommandName> = {
|
||||
'::group::': 'group',
|
||||
'##[group]': 'group',
|
||||
@@ -67,14 +68,23 @@ const LogLineLabelMap: Partial<Record<LogLineCommandName, string>> = {
|
||||
'debug': 'Debug',
|
||||
};
|
||||
|
||||
function decodeLineMessage(line: LogLine, cmd: LogLineCommand | null): string {
|
||||
// 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)
|
||||
if (!cmd) return line.message;
|
||||
let msg = line.message.substring(cmd.prefix.length);
|
||||
if (cmd.name === 'command') return msg; // "command" is only an output tag, do not parse or escape it
|
||||
// "##[cmd]" also escapes ";" and "]" which delimit its header, "::cmd::" does not
|
||||
if (!cmd.prefix.startsWith('::')) msg = msg.replace(/%3B/g, ';').replace(/%5D/g, ']');
|
||||
// renderAnsiInto breaks a line per "\r", so "%0D%0A" is one break. "%25" last keeps "%250A" literal
|
||||
return msg.replace(/(?:%0D)?%0A/g, '\n').replace(/%0D/g, '\r').replace(/%25/g, '%');
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
// 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 msgContent = decodeLineMessage(line, cmd);
|
||||
const logMsg = createElementFromAttrs('span', logMsgAttrs);
|
||||
const label = cmd ? LogLineLabelMap[cmd.name] : null;
|
||||
if (label) {
|
||||
|
||||
Reference in New Issue
Block a user