Skip to content

Commit

Permalink
feat(gitlab): implement gitlab ci provider
Browse files Browse the repository at this point in the history
  • Loading branch information
fargito committed Nov 6, 2024
1 parent 358e68c commit 9ce6a78
Show file tree
Hide file tree
Showing 16 changed files with 541 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/run/ci_provider/buildkite/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ impl CIProvider for BuildkiteProvider {
ref_: self.ref_.clone(),
repository_root_path: self.repository_root_path.clone(),
gh_data: None,
gl_data: None,
sender: None,
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ expression: provider_metadata
"event": "pull_request",
"sender": null,
"ghData": null,
"glData": null,
"repositoryRootPath": "/buildkite/builds/7b10eca7600b-1/my-org/buildkite-test/"
}
1 change: 1 addition & 0 deletions src/run/ci_provider/github_actions/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ impl CIProvider for GitHubActionsProvider {
head_ref: self.head_ref.clone(),
event: self.event.clone(),
gh_data: Some(self.gh_data.clone()),
gl_data: None,
sender: self.sender.clone(),
owner: self.owner.clone(),
repository: self.repository.clone(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ expression: provider_metadata
"runId": "6957110437",
"job": "log-env"
},
"glData": null,
"repositoryRootPath": "/home/runner/work/adrien-python-test/adrien-python-test/"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ expression: provider_metadata
"runId": "6957110437",
"job": "log-env"
},
"glData": null,
"repositoryRootPath": "/home/runner/work/adrien-python-test/adrien-python-test/"
}
152 changes: 152 additions & 0 deletions src/run/ci_provider/gitlab_ci/logger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
use console::style;
use lazy_static::lazy_static;
use log::{Level, LevelFilter, Log};
use regex::Regex;
use simplelog::SharedLogger;
use std::{
env,
io::Write,
sync::Mutex,
time::{SystemTime, UNIX_EPOCH},
};

use crate::{
logger::{get_group_event, GroupEvent},
run::ci_provider::logger::should_provider_logger_handle_record,
};

lazy_static! {
static ref GITLAB_SECTION_ID_SANITIZE_REGEX: Regex =
Regex::new(r"[^\d\w\-_]").expect("Failed to compile GitLab SectionId regex");
}

/// Unicode Escape character
///
/// https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#general-ascii-codes
const U_ESC: char = '\x1B';

/// Unicode Carriage Return character
///
/// https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#general-ascii-codes
const U_CR: char = '\x0D';

/// Reset color mode
///
/// https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#colors--graphics-mode
const COLOR_RESET: &str = "\x1B[0m";

/// Erase cursor till end of line
///
/// https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#erase-functions
const ERASE_CURSOR: &str = "\x1B[0K";

/// A logger that prints log in the format expected by GitLab CI
///
/// See https://docs.gitlab.com/ee/ci/yaml/script.html
pub struct GitLabCILogger {
log_level: LevelFilter,
section_id: Mutex<Option<String>>,
}

impl GitLabCILogger {
pub fn new() -> Self {
// force activation of colors, because GitlabCI does not
// respect the CLICOLORS spec.
// https://gitlab.com/gitlab-org/gitlab/-/issues/28598
console::set_colors_enabled(true);

let log_level = env::var("CODSPEED_LOG")
.ok()
.and_then(|log_level| log_level.parse::<log::LevelFilter>().ok())
.unwrap_or(log::LevelFilter::Info);
Self {
log_level,
section_id: Mutex::new(None),
}
}
}

impl Log for GitLabCILogger {
fn enabled(&self, _metadata: &log::Metadata) -> bool {
true
}

fn log(&self, record: &log::Record) {
if !should_provider_logger_handle_record(record) {
return;
}

let level = record.level();
let message = record.args();

if let Some(group_event) = get_group_event(record) {
let now = SystemTime::now();
let timestamp = now.duration_since(UNIX_EPOCH).unwrap().as_secs();
let mut section_id = self.section_id.lock().unwrap();

match group_event {
GroupEvent::Start(name) | GroupEvent::StartOpened(name) => {
let new_section_id = GITLAB_SECTION_ID_SANITIZE_REGEX
.replace_all(&name, "_")
.to_ascii_lowercase();

*section_id = Some(new_section_id.to_string());

// https://docs.gitlab.com/ee/ci/yaml/script.html#custom-collapsible-sections
println!("{ERASE_CURSOR}section_start:{timestamp}:{new_section_id}{U_CR}{ERASE_CURSOR}{U_ESC}[36;1m{name}{COLOR_RESET}");
}
GroupEvent::End => {
// do not fail if there is no current section
let current_section_id = section_id.clone().unwrap_or("".to_string());

// https://docs.gitlab.com/ee/ci/yaml/script.html#custom-collapsible-sections
println!("{ERASE_CURSOR}section_end:{timestamp}:{current_section_id}{U_CR}{ERASE_CURSOR}");

*section_id = None;
}
}
return;
}

if level > self.log_level {
return;
}

// set log colors. See https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#colors--graphics-mode
match level {
Level::Error => {
println!("{}", style(message).red());
}
Level::Warn => {
println!("{}", style(message).yellow());
}
Level::Info => {
println!("{message}");
}
Level::Debug => {
println!("{}", style(message).cyan());
}
Level::Trace => {
println!("{}", style(message).magenta());
}
};
}

fn flush(&self) {
std::io::stdout().flush().unwrap();
}
}

impl SharedLogger for GitLabCILogger {
fn level(&self) -> LevelFilter {
self.log_level
}

fn config(&self) -> Option<&simplelog::Config> {
None
}

fn as_log(self: Box<Self>) -> Box<dyn Log> {
Box::new(*self)
}
}
4 changes: 4 additions & 0 deletions src/run/ci_provider/gitlab_ci/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod logger;
mod provider;

pub use provider::GitLabCIProvider;
Loading

0 comments on commit 9ce6a78

Please sign in to comment.