ci_selfcheck/
ci_selfcheck.rs1use std::fmt::Write as _;
9use std::path::PathBuf;
10use std::process::ExitCode;
11
12use actions_rs::{Annotation, AnnotationKind, AnnotationSpan, Summary, output};
13
14fn read_env_file(var: &str) -> Option<String> {
15 std::fs::read_to_string(PathBuf::from(std::env::var_os(var)?)).ok()
16}
17
18fn main() -> ExitCode {
19 let notice = Annotation::new()
20 .file("examples/ci_selfcheck.rs")
21 .span(AnnotationSpan::Line {
22 start: 18,
23 end: Some(24),
24 })
25 .title("ci_selfcheck")
26 .command(
27 AnnotationKind::Notice,
28 "actions-rs self-check ran in this job",
29 );
30 let warning = Annotation::new()
31 .file("src/summary.rs")
32 .span(AnnotationSpan::Column {
33 line: 112,
34 start: 5,
35 end: None,
36 })
37 .title("example warning")
38 .command(
39 AnnotationKind::Warning,
40 "ranged warning annotation covering Summary::code_block",
41 );
42 notice.issue();
43 warning.issue();
44
45 if let Err(e) = output::set_output("answer", "42\nwith newline") {
46 eprintln!("::error::set_output: {e}");
47 return ExitCode::FAILURE;
48 }
49 if let Err(e) = output::export_var("DEMO_FLAG", true)
50 && !matches!(
51 e,
52 actions_rs::Error::UnavailableFileCommand {
53 var: "GITHUB_ENV",
54 ..
55 }
56 )
57 {
58 eprintln!("::error::export_var: {e}");
59 return ExitCode::FAILURE;
60 }
61
62 let gh_output = read_env_file("GITHUB_OUTPUT").unwrap_or_else(|| "<local: unset>".into());
63 let gh_env = read_env_file("GITHUB_ENV").unwrap_or_else(|| "<local: unset>".into());
64
65 let mut report = String::new();
67 for (label, body) in [
68 ("workflow commands (stdout)", format!("{notice}\n{warning}")),
69 ("GITHUB_OUTPUT", gh_output.clone()),
70 ("GITHUB_ENV", gh_env.clone()),
71 ] {
72 let _ = write!(report, "===== {label} =====\n{body}\n");
73 }
74
75 print!("{report}");
77
78 let tmp = std::env::var_os("RUNNER_TEMP")
80 .map(PathBuf::from)
81 .unwrap_or_else(std::env::temp_dir)
82 .join("ci_selfcheck.report.txt");
83 if let Err(e) = std::fs::write(&tmp, &report) {
84 eprintln!("::error::tmpfile write: {e}");
85 return ExitCode::FAILURE;
86 }
87
88 let captured = match std::fs::read_to_string(&tmp) {
90 Ok(c) => c,
91 Err(e) => {
92 eprintln!("::error::tmpfile read: {e}");
93 return ExitCode::FAILURE;
94 }
95 };
96 let mut summary = Summary::new();
97 summary
98 .heading("actions-rs ci_selfcheck", 2)
99 .code_block(&captured, None);
100 if let Err(e) = summary.write_overwrite() {
101 eprintln!("::error::summary.write_overwrite: {e}");
102 return ExitCode::FAILURE;
103 }
104
105 let mut exit = ExitCode::SUCCESS;
107 if std::env::var_os("GITHUB_OUTPUT").is_some() {
108 for (var, needle, hay) in [
109 ("GITHUB_OUTPUT", "answer<<", &gh_output),
110 ("GITHUB_ENV", "DEMO_FLAG<<", &gh_env),
111 ] {
112 if !hay.contains(needle) {
113 eprintln!("::error::{var} missing {needle:?}");
114 exit = ExitCode::FAILURE;
115 }
116 }
117 }
118 exit
119}