diff --git a/templates/devtest/severity-colors.tmpl b/templates/devtest/severity-colors.tmpl new file mode 100644 index 0000000000..9f86b864ea --- /dev/null +++ b/templates/devtest/severity-colors.tmpl @@ -0,0 +1,80 @@ +{{template "devtest/devtest-header"}} +
+

Severity Colors

+ +

Messages

+
+
Error Message
+

This is an error message using --color-error-* variables.

+
+
+
Warning Message
+

This is a warning message using --color-warning-* variables.

+
+
+
Success Message
+

This is a success message using --color-success-* variables.

+
+
+
Info Message
+

This is an info message using --color-info-* variables.

+
+ +

Form Fields

+
+
+ + +
+
+ +

Labels

+
+
Red
+
Orange
+
Yellow
+
Green
+
Blue
+
Violet
+
Purple
+
+ +

Color Swatches

+

Error

+
+
+
Text
+ error-bg +
+
+
Hover
+ error-bg-hover +
+
+
Active
+ error-bg-active +
+
+

Warning

+
+
+
Text
+ warning-bg +
+
+

Success

+
+
+
Text
+ success-bg +
+
+

Info

+
+
+
Text
+ info-bg +
+
+
+{{template "devtest/devtest-footer"}} diff --git a/web_src/css/base.css b/web_src/css/base.css index 2c7bd7395a..b4139c0e72 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -393,12 +393,6 @@ img.ui.avatar, aspect-ratio: 1; } -.ui.error.message .header, -.ui.warning.message .header { - color: inherit; - filter: saturate(2); -} - .full.height { flex-grow: 1; padding-bottom: var(--page-space-bottom); diff --git a/web_src/css/modules/message.css b/web_src/css/modules/message.css index 7e8a2cf744..ce997c4350 100644 --- a/web_src/css/modules/message.css +++ b/web_src/css/modules/message.css @@ -41,9 +41,9 @@ margin-bottom: 1em; } -.ui.info.message .header, -.ui.blue.message .header { - color: var(--color-blue); +.ui.message .header { + color: inherit; + filter: saturate(2); } .ui.info.message, @@ -55,12 +55,6 @@ border-color: var(--color-info-border); } -.ui.success.message .header, -.ui.positive.message .header, -.ui.green.message .header { - color: var(--color-green); -} - .ui.success.message, .ui.attached.success.message, .ui.positive.message, @@ -70,12 +64,6 @@ border-color: var(--color-success-border); } -.ui.error.message .header, -.ui.negative.message .header, -.ui.red.message .header { - color: var(--color-red); -} - .ui.error.message, .ui.attached.error.message, .ui.red.message, @@ -87,11 +75,6 @@ border-color: var(--color-error-border); } -.ui.warning.message .header, -.ui.yellow.message .header { - color: var(--color-yellow); -} - .ui.warning.message, .ui.attached.warning.message, .ui.yellow.message, diff --git a/web_src/css/themes/theme-gitea-dark.css b/web_src/css/themes/theme-gitea-dark.css index c62c20f93a..fbdef1e2fb 100644 --- a/web_src/css/themes/theme-gitea-dark.css +++ b/web_src/css/themes/theme-gitea-dark.css @@ -162,20 +162,20 @@ gitea-theme-meta-info { --color-diff-removed-row-border: #634343; --color-diff-removed-word-bg: #6f3333; --color-diff-inactive: #22282d; - --color-error-border: #a04141; - --color-error-bg: #522; - --color-error-bg-active: #744; - --color-error-bg-hover: #633; - --color-error-text: #f9cbcb; + --color-error-border: #da3633; + --color-error-bg: #3c2425; + --color-error-bg-active: #5a3637; + --color-error-bg-hover: #4c2d2e; + --color-error-text: #f5817c; --color-success-border: #458a57; --color-success-bg: #284034; - --color-success-text: #6cc664; - --color-warning-border: #bb9d00; - --color-warning-bg: #3a3a30; - --color-warning-text: #fbbd08; + --color-success-text: #69be61; + --color-warning-border: #9e6a03; + --color-warning-bg: #2f2a1b; + --color-warning-text: #d29922; --color-info-border: #306090; --color-info-bg: #26354c; - --color-info-text: #38a8e8; + --color-info-text: #48b7f8; --color-red-badge: #db2828; --color-red-badge-bg: #db28281a; --color-red-badge-hover-bg: #db28284d; diff --git a/web_src/css/themes/theme-gitea-light.css b/web_src/css/themes/theme-gitea-light.css index 5f437c5a6c..761cb18da0 100644 --- a/web_src/css/themes/theme-gitea-light.css +++ b/web_src/css/themes/theme-gitea-light.css @@ -162,20 +162,20 @@ gitea-theme-meta-info { --color-diff-removed-row-border: #f1c0c0; --color-diff-removed-word-bg: #fdb8c0; --color-diff-inactive: #f0f2f4; - --color-error-border: #e0b4b4; - --color-error-bg: #fff6f6; - --color-error-bg-active: #fbb; - --color-error-bg-hover: #fdd; - --color-error-text: #9f3a38; - --color-success-border: #a3c293; - --color-success-bg: #fcfff5; - --color-success-text: #2c662d; - --color-warning-border: #c9ba9b; - --color-warning-bg: #fffaf3; - --color-warning-text: #573a08; - --color-info-border: #a9d5de; - --color-info-bg: #f8ffff; - --color-info-text: #276f86; + --color-error-border: #d63333; + --color-error-bg: #ffebeb; + --color-error-bg-active: #fdd; + --color-error-bg-hover: #fee; + --color-error-text: #8a3231; + --color-success-border: #49842b; + --color-success-bg: #eef6e4; + --color-success-text: #2f6e30; + --color-warning-border: #bf8700; + --color-warning-bg: #fff8e1; + --color-warning-text: #744500; + --color-info-border: #2d8fa8; + --color-info-bg: #e8f4fd; + --color-info-text: #216078; --color-red-badge: #db2828; --color-red-badge-bg: #db28281a; --color-red-badge-hover-bg: #db28284d; diff --git a/web_src/js/components/ActionRunJobView.vue b/web_src/js/components/ActionRunJobView.vue index 747889d04c..fba78917c9 100644 --- a/web_src/js/components/ActionRunJobView.vue +++ b/web_src/js/components/ActionRunJobView.vue @@ -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 */ diff --git a/web_src/js/components/ActionRunView.test.ts b/web_src/js/components/ActionRunView.test.ts index f0e3fa090a..1f972b73c0 100644 --- a/web_src/js/components/ActionRunView.test.ts +++ b/web_src/js/components/ActionRunView.test.ts @@ -8,8 +8,14 @@ test('LogLineMessage', () => { '##[endgroup]': '', '::endgroup::': '', - // parser shouldn't do any trim, keep origin output as-is - '##[error] foo': ' foo', + '##[error] foo': 'Error: foo', + '##[warning] foo': 'Warning: foo', + '##[notice] foo': 'Notice: foo', + '##[debug] foo': 'Debug: foo', + '::error::foo': 'Error: foo', + '::warning file=test.js,line=1::foo': 'Warning: foo', + '::notice::foo': 'Notice: foo', + '::debug::foo': 'Debug: foo', '[command] foo': ' foo', // hidden is special, it is actually skipped before creating diff --git a/web_src/js/components/ActionRunView.ts b/web_src/js/components/ActionRunView.ts index 6ae09a46fe..250f39e811 100644 --- a/web_src/js/components/ActionRunView.ts +++ b/web_src/js/components/ActionRunView.ts @@ -17,6 +17,9 @@ const LogLinePrefixCommandMap: Record = { '##[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 = { '::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> = { + '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; }