executable_stories/
collector.rs1use std::sync::Mutex;
2
3use crate::json_writer;
4use crate::types::{RawCIInfo, RawRun, RawTestCase};
5
6static COLLECTED: Mutex<Vec<RawTestCase>> = Mutex::new(Vec::new());
7static ORDER_SEQ: Mutex<u32> = Mutex::new(0);
8
9pub fn record(tc: RawTestCase) {
11 COLLECTED.lock().unwrap().push(tc);
12}
13
14pub fn next_order() -> u32 {
16 let mut seq = ORDER_SEQ.lock().unwrap();
17 let val = *seq;
18 *seq += 1;
19 val
20}
21
22pub fn get_all() -> Vec<RawTestCase> {
24 COLLECTED.lock().unwrap().clone()
25}
26
27fn detect_ci() -> Option<RawCIInfo> {
28 if std::env::var("GITHUB_ACTIONS").as_deref() == Ok("true") {
29 let url = match (
30 std::env::var("GITHUB_SERVER_URL"),
31 std::env::var("GITHUB_REPOSITORY"),
32 std::env::var("GITHUB_RUN_ID"),
33 ) {
34 (Ok(s), Ok(r), Ok(id)) => Some(format!("{s}/{r}/actions/runs/{id}")),
35 _ => None,
36 };
37 return Some(RawCIInfo {
38 name: "github".to_string(),
39 build_number: std::env::var("GITHUB_RUN_NUMBER").ok(),
40 url,
41 });
42 }
43 if std::env::var("CIRCLECI").as_deref() == Ok("true") {
44 return Some(RawCIInfo {
45 name: "circleci".to_string(),
46 build_number: std::env::var("CIRCLE_BUILD_NUM").ok(),
47 url: std::env::var("CIRCLE_BUILD_URL").ok(),
48 });
49 }
50 if std::env::var("JENKINS_URL").is_ok() {
51 return Some(RawCIInfo {
52 name: "jenkins".to_string(),
53 build_number: std::env::var("BUILD_NUMBER").ok(),
54 url: std::env::var("BUILD_URL").ok(),
55 });
56 }
57 if std::env::var("TRAVIS").as_deref() == Ok("true") {
58 return Some(RawCIInfo {
59 name: "travis".to_string(),
60 build_number: std::env::var("TRAVIS_BUILD_NUMBER").ok(),
61 url: std::env::var("TRAVIS_BUILD_WEB_URL").ok(),
62 });
63 }
64 if std::env::var("GITLAB_CI").as_deref() == Ok("true") {
65 return Some(RawCIInfo {
66 name: "gitlab".to_string(),
67 build_number: std::env::var("CI_PIPELINE_IID").ok(),
68 url: std::env::var("CI_PIPELINE_URL").ok(),
69 });
70 }
71 if std::env::var("CI").as_deref() == Ok("true") {
72 return Some(RawCIInfo { name: "ci".to_string(), build_number: None, url: None });
73 }
74 None
75}
76
77#[allow(clippy::missing_panics_doc)]
88pub fn write_results() {
89 let cases = get_all();
90 if cases.is_empty() {
91 return;
92 }
93
94 let output = std::env::var("EXECUTABLE_STORIES_OUTPUT")
95 .unwrap_or_else(|_| ".executable-stories/raw-run.json".to_string());
96
97 let cwd = std::env::current_dir().map(|p| p.to_string_lossy().to_string()).unwrap_or_default();
98
99 let run = RawRun {
100 schema_version: 1,
101 test_cases: cases,
102 project_root: cwd,
103 started_at_ms: None,
104 finished_at_ms: None,
105 ci: detect_ci(),
106 };
107
108 json_writer::write_raw_run(&run, &output).expect("Failed to write raw run JSON");
109}
110
111#[allow(dead_code)]
113pub fn reset() {
114 COLLECTED.lock().unwrap().clear();
115 *ORDER_SEQ.lock().unwrap() = 0;
116}