1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
//! An interface to github actions workflow commands.
use std::fmt::{Debug, Write};
/// 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: usize) -> Self {
self.line = line;
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))
};
eprintln!("::error file={file},line={line},title={title}{message}");
eprintln!("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() {
eprintln!("::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() {
eprintln!("::endgroup::");
}
}
}
|