actions_github/logger.rs
1//! Logging methods for the output
2use std::fmt::{Display, Formatter};
3use std::io::Write;
4use std::{env, io};
5
6use crate::util::EOL;
7
8const LOG_DEBUG_ENV: &str = "LOG_DEBUG";
9const LOG_WRITE_ENV: &str = "LOG_DEBUG_WRITE";
10
11#[derive(Debug)]
12/// Struct which contains the parameters used for custom annotations.
13///
14/// This is used in the [notice_log], [warn_log] and [error_log]
15///
16/// ## Example use case
17/// ```rust
18/// # std::env::set_var("LOG_DEBUG", "true");
19/// use actions_github::logger::{LogParameters, notice_log};
20/// let params = LogParameters {
21/// title: String::from("My example"),
22/// file: String::from("src/lib.rs"),
23/// line: 1,
24/// end_line: 3
25/// };
26///
27/// notice_log("There is a problem in the file", Some(params));
28/// # assert_eq!(std::env::var("LOG_DEBUG_WRITE").unwrap(),
29/// # "::notice file=src/lib.rs,line=1,endLine=3,title=My example::There is a problem in the file");
30/// ```
31pub struct LogParameters {
32 /// Custom title
33 pub title: String,
34 /// Filename
35 pub file: String,
36 /// Line number, starting at 1
37 pub line: u16,
38 /// End line number
39 pub end_line: u16,
40}
41
42impl Display for LogParameters {
43 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
44 write!(
45 f,
46 "file={},line={},endLine={},title={}",
47 self.file, self.line, self.end_line, self.title
48 )
49 }
50}
51
52impl Default for LogParameters {
53 fn default() -> Self {
54 LogParameters {
55 title: String::from(""),
56 file: String::from(".github"),
57 line: 1,
58 end_line: 1,
59 }
60 }
61}
62
63fn issue_command(command: &str, msg: &str, parameters: Option<LogParameters>) {
64 let message = match parameters {
65 None => format!("::{}::{}", command, msg),
66 Some(params) => format!("::{} {}::{}", command, params, msg),
67 };
68 match env::var(LOG_DEBUG_ENV) {
69 Ok(_) => env::set_var(LOG_WRITE_ENV, message),
70 Err(_) => io::stdout()
71 .write_all((message + EOL).as_bytes())
72 .expect("Failed to write message"),
73 }
74}
75
76/// Prints a debug message to the log.
77///
78/// Only visible if [debug logging is enabled](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging)
79///
80/// GitHub's documentation: [Setting a debug message](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-debug-message)
81///
82/// ## Example usage
83///
84/// ```rust
85/// # std::env::set_var("LOG_DEBUG", "true");
86/// use actions_github::logger;
87/// logger::debug_log("Initializing the project");
88/// # assert_eq!(std::env::var("LOG_DEBUG_WRITE").unwrap(), "::debug::Initializing the project")
89/// ```
90pub fn debug_log(msg: &str) {
91 let message = format!("::debug::{}", msg);
92
93 match env::var(LOG_DEBUG_ENV) {
94 Ok(_) => env::set_var(LOG_WRITE_ENV, message),
95 Err(_) => io::stdout()
96 .write_all((message + EOL).as_bytes())
97 .expect("Failed to write debug message"),
98 }
99}
100
101/// Logs regular information message
102///
103/// ## Example usage
104///
105/// ```rust
106/// # std::env::set_var("LOG_DEBUG", "true");
107/// use actions_github::logger;
108/// logger::info(format!("Finished analyzing {}", "project").as_str());
109/// # assert_eq!(std::env::var("LOG_DEBUG_WRITE").unwrap(), "Finished analyzing project")
110/// ```
111pub fn info(msg: &str) {
112 match env::var(LOG_DEBUG_ENV) {
113 Ok(_) => env::set_var(LOG_WRITE_ENV, msg),
114 Err(_) => io::stdout()
115 .write_all((msg.to_owned() + EOL).as_bytes())
116 .expect("Failed to write info message"),
117 }
118}
119
120/// Creates a warning message and prints the message to the log.
121///
122/// This message will create an annotation.
123///
124/// GitHub's documentation: [Setting a warning message](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-warning-message)
125///
126/// ## Example usage
127///
128/// ```rust
129/// # std::env::set_var("LOG_DEBUG", "true");
130/// use actions_github::logger;
131/// logger::warn_log("Missing name of project", None);
132/// # assert_eq!(std::env::var("LOG_DEBUG_WRITE").unwrap(), "::warning::Missing name of project")
133/// ```
134///
135/// ## Custom annotations
136///
137/// You can also set custom annotations to mention a specific line in a file.
138/// See [LogParameters] for more info.
139/// ```rust
140/// # std::env::set_var("LOG_DEBUG", "true");
141/// use actions_github::logger;
142/// logger::warn_log("Missing name of project", Some(logger::LogParameters {
143/// title: String::from("Missing name"),
144/// file: String::from("src/lib.rs"),
145/// line: 1,
146/// end_line: 3
147/// }));
148/// # assert_eq!(std::env::var("LOG_DEBUG_WRITE").unwrap(),
149/// # "::warning file=src/lib.rs,line=1,endLine=3,title=Missing name::Missing name of project")
150/// ```
151pub fn warn_log(msg: &str, parameters: Option<LogParameters>) {
152 issue_command("warning", msg, parameters);
153}
154
155/// Creates an error message and prints the message to the log.
156///
157/// This message will create an annotation.
158///
159/// GitHub's documentation: [Setting an error message](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message)
160///
161/// ## Example usage
162///
163/// ```rust
164/// # std::env::set_var("LOG_DEBUG", "true");
165/// use actions_github::logger;
166/// logger::error_log("Did not find library", None);
167/// # assert_eq!(std::env::var("LOG_DEBUG_WRITE").unwrap(), "::error::Did not find library");
168/// ```
169///
170/// ### Custom annotations
171///
172/// You can also set custom annotations to mention a specific line in a file.
173/// See [LogParameters] for more info.
174/// ```rust
175/// # std::env::set_var("LOG_DEBUG", "true");
176/// use actions_github::logger;
177/// logger::error_log("Did not find library", Some(logger::LogParameters {
178/// title: String::from("Library missing"),
179/// file: String::from("Cargo.toml"),
180/// line: 4,
181/// end_line: 7
182/// }));
183/// # assert_eq!(std::env::var("LOG_DEBUG_WRITE").unwrap(),
184/// # "::error file=Cargo.toml,line=4,endLine=7,title=Library missing::Did not find library")
185/// ```
186pub fn error_log(msg: &str, parameters: Option<LogParameters>) {
187 issue_command("error", msg, parameters);
188}
189
190/// Creates a notice message and prints the message to the log.
191///
192/// This message will create an annotation.
193///
194/// GitHub's Documentation: [Setting a notice message](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-notice-message)
195///
196/// ## Example usage
197///
198/// ```rust
199/// # std::env::set_var("LOG_DEBUG", "true");
200/// use actions_github::logger;
201/// logger::notice_log("Step one is finished", None);
202/// # assert_eq!(std::env::var("LOG_DEBUG_WRITE").unwrap(), "::notice::Step one is finished")
203/// ```
204///
205/// ## Custom annotations
206///
207/// You can also set custom annotations to mention a specific line in a file.
208/// See [LogParameters] for more info.
209/// ```rust
210/// # std::env::set_var("LOG_DEBUG", "true");
211/// use actions_github::logger;
212/// logger::notice_log("Step one is finished", Some(logger::LogParameters {
213/// title: String::from("Step completed"),
214/// file: String::from(".github/workflows/test.yml"),
215/// line: 24,
216/// end_line: 27
217/// }));
218/// # assert_eq!(std::env::var("LOG_DEBUG_WRITE").unwrap(),
219/// # "::notice file=.github/workflows/test.yml,line=24,endLine=27,title=Step completed::Step one is finished")
220/// ```
221pub fn notice_log(msg: &str, parameters: Option<LogParameters>) {
222 issue_command("notice", msg, parameters);
223}
224
225/// Returns if it's running on a debug runner.
226///
227/// If the `RUNNER_DEBUG` variable is not defined, it'll always return true
228///
229/// ```rust
230/// use actions_github::logger::is_debug;
231/// assert!(is_debug());
232/// std::env::set_var("RUNNER_DEBUG", "0");
233/// assert!(!is_debug());
234/// ```
235pub fn is_debug() -> bool {
236 match env::var("RUNNER_DEBUG") {
237 Ok(value) => value == "1",
238 Err(_) => true,
239 }
240}