summaryrefslogtreecommitdiffstats
path: root/vendor/ui_test-0.20.0/src/github_actions.rs
blob: 01e1d3bb224f681a2e86aca64fde7bebad91f060 (plain)
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
95
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::");
        }
    }
}