Skip to content

Commit 4e52cfa

Browse files
committed
feat(run-environment): add CircleCI provider for GitHub repositories
Support running benchmarks from CircleCI on GitHub-hosted repositories. The build runs on CircleCI while commits and pull requests live on GitHub, so the run reports against the GitHub commit and PR. Unlike GitHub Actions, CircleCI checks out the associated commit itself rather than a synthetic merge ref, so the default git HEAD read already yields CIRCLE_SHA1 and no commit hash override is needed. CircleCI exposes no base branch variable either: baseRef is left empty and CodSpeed resolves the base branch from the pull request. CircleCI also builds Bitbucket and GitLab repositories, so the domain of CIRCLE_REPOSITORY_URL is validated and anything but github.com is rejected with an explicit error. That domain is the only signal available at runtime: the explicit pipeline.project.type is a pipeline value, interpolated when the config is compiled, so it never reaches the job as a variable. Uploads authenticate with a static CODSPEED_TOKEN. Run part data is already reported, so runs group correctly once multi-part upload support lands: CIRCLE_WORKFLOW_ID is shared by every job and every parallel container of a workflow, while CIRCLE_JOB and CIRCLE_NODE_INDEX identify a single part. Refs COD-2977 Refs COD-2995 Refs COD-3262
1 parent 97a789a commit 4e52cfa

8 files changed

Lines changed: 571 additions & 1 deletion
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use console::style;
2+
use log::*;
3+
use simplelog::SharedLogger;
4+
use std::{env, io::Write};
5+
6+
use crate::{
7+
logger::{GroupEvent, get_announcement_event, get_group_event, get_json_event},
8+
run_environment::logger::should_provider_logger_handle_record,
9+
};
10+
11+
/// A logger that prints logs in the format expected by CircleCI
12+
///
13+
/// CircleCI has no collapsible section markers, so groups are printed as plain
14+
/// headers.
15+
pub struct CircleCILogger {
16+
log_level: LevelFilter,
17+
}
18+
19+
impl CircleCILogger {
20+
pub fn new() -> Self {
21+
// force activation of colors: CircleCI renders ANSI sequences in its UI, but
22+
// the output is not a TTY so colors would be disabled by default.
23+
console::set_colors_enabled(true);
24+
25+
let log_level = env::var("CODSPEED_LOG")
26+
.ok()
27+
.and_then(|log_level| log_level.parse::<log::LevelFilter>().ok())
28+
.unwrap_or(log::LevelFilter::Info);
29+
Self { log_level }
30+
}
31+
}
32+
33+
impl Log for CircleCILogger {
34+
fn enabled(&self, _metadata: &Metadata) -> bool {
35+
true
36+
}
37+
38+
fn log(&self, record: &Record) {
39+
if !should_provider_logger_handle_record(record) {
40+
return;
41+
}
42+
43+
let level = record.level();
44+
let message = record.args();
45+
46+
if let Some(group_event) = get_group_event(record) {
47+
match group_event {
48+
GroupEvent::Start(name) | GroupEvent::StartOpened(name) => {
49+
println!("{}", style(name).cyan().bold());
50+
}
51+
GroupEvent::End => {}
52+
}
53+
return;
54+
}
55+
56+
if get_json_event(record).is_some() {
57+
return;
58+
}
59+
60+
if let Some(announcement) = get_announcement_event(record) {
61+
println!("{}", style(announcement).green());
62+
return;
63+
}
64+
65+
if level > self.log_level {
66+
return;
67+
}
68+
69+
match level {
70+
Level::Error => {
71+
println!("{}", style(message).red());
72+
}
73+
Level::Warn => {
74+
println!("{}", style(message).yellow());
75+
}
76+
Level::Info => {
77+
println!("{message}");
78+
}
79+
Level::Debug => {
80+
println!("{}", style(message).cyan());
81+
}
82+
Level::Trace => {
83+
println!("{}", style(message).magenta());
84+
}
85+
}
86+
}
87+
88+
fn flush(&self) {
89+
std::io::stdout().flush().unwrap();
90+
}
91+
}
92+
93+
impl SharedLogger for CircleCILogger {
94+
fn level(&self) -> LevelFilter {
95+
self.log_level
96+
}
97+
98+
fn config(&self) -> Option<&simplelog::Config> {
99+
None
100+
}
101+
102+
fn as_log(self: Box<Self>) -> Box<dyn Log> {
103+
Box::new(*self)
104+
}
105+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
mod logger;
2+
mod provider;
3+
4+
pub use provider::CircleCIProvider;

0 commit comments

Comments
 (0)