diff options
Diffstat (limited to 'vendor/ui_test/src/github_actions.rs')
-rw-r--r-- | vendor/ui_test/src/github_actions.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/vendor/ui_test/src/github_actions.rs b/vendor/ui_test/src/github_actions.rs new file mode 100644 index 000000000..01e1d3bb2 --- /dev/null +++ b/vendor/ui_test/src/github_actions.rs @@ -0,0 +1,96 @@ +//! An interface to github actions workflow commands. + +use std::{ + fmt::{Debug, Write}, + num::NonZeroUsize, +}; + +/// Shows an error message directly in a github diff view on drop. +pub struct Error { + file: String, + line: usize, + title: String, + message: String, +} +impl Error { + /// Set a line for this error. By default the message is shown at the top of the file. + pub fn line(mut self, line: NonZeroUsize) -> Self { + self.line = line.get(); + self + } +} + +/// Create an error to be shown for the given file and with the given title. +pub fn error(file: impl std::fmt::Display, title: impl Into<String>) -> Error { + Error { + file: file.to_string(), + line: 0, + title: title.into(), + message: String::new(), + } +} + +impl Write for Error { + fn write_str(&mut self, s: &str) -> std::fmt::Result { + self.message.write_str(s) + } +} + +impl Drop for Error { + fn drop(&mut self) { + if std::env::var_os("GITHUB_ACTION").is_some() { + let Error { + file, + line, + title, + message, + } = self; + let message = message.trim(); + let message = if message.is_empty() { + "::no message".into() + } else { + format!("::{}", github_action_multiline_escape(message)) + }; + println!("::error file={file},line={line},title={title}{message}"); + } + } +} + +/// Append to the summary file that will be shown for the entire CI run. +pub fn summary() -> Option<impl std::io::Write> { + let path = std::env::var_os("GITHUB_STEP_SUMMARY")?; + Some(std::fs::OpenOptions::new().append(true).open(path).unwrap()) +} + +fn github_action_multiline_escape(s: &str) -> String { + s.replace('%', "%25") + .replace('\n', "%0A") + .replace('\r', "%0D") +} + +/// All github actions log messages from this call to the Drop of the return value +/// will be grouped and hidden by default in logs. Note that nesting these does +/// not really work. +pub fn group(name: impl std::fmt::Display) -> Group { + if std::env::var_os("GITHUB_ACTION").is_some() { + println!("::group::{name}"); + } + Group(()) +} + +/// A guard that closes the current github actions log group on drop. +pub struct Group(()); + +impl Debug for Group { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("a handle that will close the github action group on drop") + } +} + +impl Drop for Group { + fn drop(&mut self) { + if std::env::var_os("GITHUB_ACTION").is_some() { + println!("::endgroup::"); + } + } +} |