这是indexloc提供的服务,不要输入任何密码
Skip to content

feat: GitLab VendorBehavior #8300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/turborepo-ci/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ license = "MIT"
workspace = true

[dependencies]
chrono = { workspace = true }
tracing = { workspace = true }

[dev-dependencies]
Expand Down
5 changes: 4 additions & 1 deletion crates/turborepo-ci/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ mod vendors;
use std::{env, sync::OnceLock};

use crate::vendors::get_vendors;
pub use crate::{vendor_behavior::VendorBehavior, vendors::Vendor};
pub use crate::{
vendor_behavior::{GroupPrefixFn, VendorBehavior},
vendors::Vendor,
};

static IS_CI: OnceLock<bool> = OnceLock::new();
static VENDOR: OnceLock<Option<&'static Vendor>> = OnceLock::new();
Expand Down
23 changes: 16 additions & 7 deletions crates/turborepo-ci/src/vendor_behavior.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
type GroupPrefixFn = fn(group_name: &str) -> String;
use std::sync::Arc;

use chrono::{DateTime, Utc};

pub type GroupPrefixFn = Arc<dyn Fn(DateTime<Utc>) -> String + Send + Sync>;
type GroupPrefixFnFactory = fn(group_name: String) -> GroupPrefixFn;

#[derive(Clone, Debug, PartialEq)]
pub struct VendorBehavior {
pub group_prefix: GroupPrefixFn,
pub group_suffix: GroupPrefixFn,
pub error_group_prefix: Option<GroupPrefixFn>,
pub error_group_suffix: Option<GroupPrefixFn>,
pub group_prefix: GroupPrefixFnFactory,
pub group_suffix: GroupPrefixFnFactory,
pub error_group_prefix: Option<GroupPrefixFnFactory>,
pub error_group_suffix: Option<GroupPrefixFnFactory>,
}

impl VendorBehavior {
pub fn new(prefix: GroupPrefixFn, suffix: GroupPrefixFn) -> Self {
pub fn new(prefix: GroupPrefixFnFactory, suffix: GroupPrefixFnFactory) -> Self {
Self {
group_prefix: prefix,
group_suffix: suffix,
Expand All @@ -18,7 +23,11 @@ impl VendorBehavior {
}
}

pub fn with_error(mut self, prefix: GroupPrefixFn, suffix: GroupPrefixFn) -> Self {
pub fn with_error(
mut self,
prefix: GroupPrefixFnFactory,
suffix: GroupPrefixFnFactory,
) -> Self {
self.error_group_prefix = Some(prefix);
self.error_group_suffix = Some(suffix);
self
Expand Down
57 changes: 45 additions & 12 deletions crates/turborepo-ci/src/vendors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::{collections::HashMap, fmt::Debug, sync::OnceLock};
use std::{
collections::HashMap,
fmt::Debug,
sync::{Arc, OnceLock},
};

use crate::vendor_behavior::VendorBehavior;

Expand Down Expand Up @@ -78,8 +82,8 @@ pub(crate) fn get_vendors() -> &'static [Vendor] {
branch_env_var: None,
username_env_var: None,
behavior: Some(VendorBehavior::new(
|group_name| format!("##[group]{group_name}\r\n"),
|_| String::from("##[endgroup]\r\n"),
|group_name| Arc::new(move |_| format!("##[group]{group_name}\r\n")),
|_| Arc::new(|_| String::from("##[endgroup]\r\n")),
)),
},
Vendor {
Expand Down Expand Up @@ -268,12 +272,14 @@ pub(crate) fn get_vendors() -> &'static [Vendor] {
username_env_var: Some("GITHUB_ACTOR"),
behavior: Some(
VendorBehavior::new(
|group_name| format!("::group::{group_name}\n"),
|_| String::from("::endgroup::\n"),
|group_name| Arc::new(move |_| format!("::group::{group_name}\n")),
|_| Arc::new(move |_| String::from("::endgroup::\n")),
)
.with_error(
|group_name| format!("\x1B[;31m{group_name}\x1B[;0m\n"),
|_| String::new(),
|group_name| {
Arc::new(move |_| format!("\x1B[;31m{group_name}\x1B[;0m\n"))
},
|_| Arc::new(|_| String::new()),
),
),
},
Expand All @@ -288,7 +294,24 @@ pub(crate) fn get_vendors() -> &'static [Vendor] {
sha_env_var: None,
branch_env_var: None,
username_env_var: None,
behavior: None,
// https://docs.gitlab.com/ee/ci/jobs/#custom-collapsible-sections
behavior: Some(VendorBehavior::new(
|group_name| {
Arc::new(move |start_time| {
let timestamp = start_time.timestamp();
format!(
"\\e[0Ksection_start:{timestamp}:{group_name}\\r\\
e[0K{group_name}"
)
})
},
|group_name| {
Arc::new(move |end_time| {
let timestamp = end_time.timestamp();
format!("\\e[0Ksection_end:{timestamp}:{group_name}\\r\\e[0K")
})
},
)),
},
Vendor {
name: "GoCD",
Expand Down Expand Up @@ -553,8 +576,16 @@ pub(crate) fn get_vendors() -> &'static [Vendor] {
branch_env_var: None,
username_env_var: None,
behavior: Some(VendorBehavior::new(
|group_name| format!("##teamcity[blockOpened name='{group_name}']"),
|group_name| format!("##teamcity[blockClosed name='{group_name}']"),
|group_name| {
Arc::new(move |_| {
format!("##teamcity[blockOpened name='{group_name}']")
})
},
|group_name| {
Arc::new(move |_| {
format!("##teamcity[blockClosed name='{group_name}']")
})
},
)),
},
Vendor {
Expand All @@ -569,8 +600,10 @@ pub(crate) fn get_vendors() -> &'static [Vendor] {
branch_env_var: None,
username_env_var: None,
behavior: Some(VendorBehavior::new(
|group_name| format!("travis_fold:start:{group_name}\r\n"),
|group_name| format!("travis_fold:end:{group_name}\r\n"),
|group_name| {
Arc::new(move |_| format!("travis_fold:start:{group_name}\r\n"))
},
|group_name| Arc::new(move |_| format!("travis_fold:end:{group_name}\r\n")),
)),
},
Vendor {
Expand Down
18 changes: 11 additions & 7 deletions crates/turborepo-lib/src/task_graph/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,15 +402,19 @@ impl<'a> Visitor<'a> {
} else {
format!("{}:{}", task_id.package(), task_id.task())
};
let (header, footer) = (
(vendor_behavior.group_prefix)(&group_name),
(vendor_behavior.group_suffix)(&group_name),
);
logger.with_header_footer(Some(header), Some(footer));

let header_factory = (vendor_behavior.group_prefix)(group_name.to_owned());
let footer_factory = (vendor_behavior.group_suffix)(group_name.to_owned());

logger.with_header_footer(Some(header_factory), Some(footer_factory));

let (error_header, error_footer) = (
vendor_behavior.error_group_prefix.map(|f| f(&group_name)),
vendor_behavior.error_group_suffix.map(|f| f(&group_name)),
vendor_behavior
.error_group_prefix
.map(|f| f(group_name.to_owned())),
vendor_behavior
.error_group_suffix
.map(|f| f(group_name.to_owned())),
);
logger.with_error_header_footer(error_header, error_footer);
}
Expand Down
2 changes: 2 additions & 0 deletions crates/turborepo-ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ workspace = true

[dependencies]
atty = { workspace = true }
chrono = { workspace = true }
console = { workspace = true }
crossterm = "0.27.0"
dialoguer = { workspace = true }
Expand All @@ -27,5 +28,6 @@ thiserror = { workspace = true }
tracing = { workspace = true }
tui-term = { workspace = true }
turbopath = { workspace = true }
turborepo-ci = { workspace = true }
turborepo-vt100 = { workspace = true }
winapi = "0.3.9"
42 changes: 30 additions & 12 deletions crates/turborepo-ui/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use std::{
sync::{Arc, Mutex, RwLock},
};

use turborepo_ci::GroupPrefixFn;

/// OutputSink represent a sink for outputs that can be written to from multiple
/// threads through the use of Loggers.
pub struct OutputSink<W> {
Expand All @@ -28,8 +30,8 @@ pub struct OutputClient<W> {

#[derive(Default)]
struct Marginals {
header: Option<String>,
footer: Option<String>,
header: Option<GroupPrefixFn>,
footer: Option<GroupPrefixFn>,
}

pub struct OutputWriter<'a, W> {
Expand Down Expand Up @@ -95,11 +97,19 @@ impl<W: Write> OutputSink<W> {
}

impl<W: Write> OutputClient<W> {
pub fn with_header_footer(&mut self, header: Option<String>, footer: Option<String>) {
pub fn with_header_footer(
&mut self,
header: Option<GroupPrefixFn>,
footer: Option<GroupPrefixFn>,
) {
self.primary = Marginals { header, footer };
}

pub fn with_error_header_footer(&mut self, header: Option<String>, footer: Option<String>) {
pub fn with_error_header_footer(
&mut self,
header: Option<GroupPrefixFn>,
footer: Option<GroupPrefixFn>,
) {
self.error = Marginals { header, footer };
}

Expand Down Expand Up @@ -151,7 +161,8 @@ impl<W: Write> OutputClient<W> {
// to ensure that the bytes aren't interspersed.
let mut writers = writers.lock().expect("lock poisoned");
if let Some(prefix) = header {
writers.out.write_all(prefix.as_bytes())?;
let start_time = chrono::Utc::now();
writers.out.write_all(prefix(start_time).as_bytes())?;
}
for SinkBytes {
buffer,
Expand All @@ -165,7 +176,8 @@ impl<W: Write> OutputClient<W> {
writer.write_all(buffer)?;
}
if let Some(suffix) = footer {
writers.out.write_all(suffix.as_bytes())?;
let end_time = chrono::Utc::now();
writers.out.write_all(suffix(end_time).as_bytes())?;
}
}

Expand Down Expand Up @@ -381,13 +393,19 @@ mod test {
fn test_marginals() -> io::Result<()> {
let sink = OutputSink::new(Vec::new(), Vec::new());
let mut group1_logger = sink.logger(OutputClientBehavior::Grouped);
group1_logger
.with_header_footer(Some("good header\n".into()), Some("good footer\n".into()));
group1_logger
.with_error_header_footer(Some("bad header\n".into()), Some("bad footer\n".into()));
group1_logger.with_header_footer(
Some(Arc::new(|_| "good header\n".into())),
Some(Arc::new(|_| "good footer\n".into())),
);
group1_logger.with_error_header_footer(
Some(Arc::new(|_| "bad header\n".into())),
Some(Arc::new(|_| "bad footer\n".into())),
);
let mut group2_logger = sink.logger(OutputClientBehavior::Grouped);
group2_logger
.with_header_footer(Some("good header\n".into()), Some("good footer\n".into()));
group2_logger.with_header_footer(
Some(Arc::new(|_| "good header\n".into())),
Some(Arc::new(|_| "good footer\n".into())),
);

let mut group1_out = group1_logger.stdout();
let mut group2_out = group2_logger.stdout();
Expand Down
Loading