diff --git a/src/logger.rs b/src/logger.rs index 43bce1d4..cf0663c6 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -1,6 +1,7 @@ /// This target is used exclusively to handle group events. pub const GROUP_TARGET: &str = "codspeed::group"; pub const OPENED_GROUP_TARGET: &str = "codspeed::group::opened"; +pub const ANNOUNCEMENT_TARGET: &str = "codspeed::announcement"; #[macro_export] /// Start a new log group. All logs between this and the next `end_group!` will be grouped together. @@ -43,6 +44,15 @@ macro_rules! end_group { }; } +#[macro_export] +/// Logs at the announcement level. This is intended for important announcements like new features, +/// that do not require immediate user action. +macro_rules! announcement { + ($name:expr) => { + log::log!(target: $crate::logger::ANNOUNCEMENT_TARGET, log::Level::Info, "{}", $name); + }; +} + pub enum GroupEvent { Start(String), StartOpened(String), @@ -72,6 +82,14 @@ pub(super) fn get_group_event(record: &log::Record) -> Option { } } +pub(super) fn get_announcement_event(record: &log::Record) -> Option { + if record.target() != ANNOUNCEMENT_TARGET { + return None; + } + + Some(record.args().to_string()) +} + #[macro_export] /// Log a structured JSON output macro_rules! log_json { diff --git a/src/prelude.rs b/src/prelude.rs index 7f8254c9..2e8bb366 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,4 +1,4 @@ -pub use crate::{end_group, log_json, start_group, start_opened_group}; +pub use crate::{announcement, end_group, log_json, start_group, start_opened_group}; #[allow(unused_imports)] pub use anyhow::{Context, Error, Result, anyhow, bail, ensure}; pub use itertools::Itertools; diff --git a/src/run/run_environment/buildkite/logger.rs b/src/run/run_environment/buildkite/logger.rs index 64ec8957..69c6d459 100644 --- a/src/run/run_environment/buildkite/logger.rs +++ b/src/run/run_environment/buildkite/logger.rs @@ -1,5 +1,5 @@ use crate::{ - logger::{GroupEvent, get_group_event, get_json_event}, + logger::{GroupEvent, get_announcement_event, get_group_event, get_json_event}, run::run_environment::logger::should_provider_logger_handle_record, }; use log::*; @@ -53,6 +53,11 @@ impl Log for BuildkiteLogger { return; } + if let Some(announcement) = get_announcement_event(record) { + println!("[ANNOUNCEMENT] {announcement}"); + return; + } + if level > self.log_level { return; } diff --git a/src/run/run_environment/github_actions/logger.rs b/src/run/run_environment/github_actions/logger.rs index 9188314d..150b24ee 100644 --- a/src/run/run_environment/github_actions/logger.rs +++ b/src/run/run_environment/github_actions/logger.rs @@ -1,5 +1,5 @@ use crate::{ - logger::{GroupEvent, get_group_event, get_json_event}, + logger::{GroupEvent, get_announcement_event, get_group_event, get_json_event}, run::run_environment::logger::should_provider_logger_handle_record, }; use log::*; @@ -55,6 +55,14 @@ impl Log for GithubActionLogger { return; } + if let Some(announcement) = get_announcement_event(record) { + // properly escape newlines so that GitHub Actions interprets them correctly + // https://github.com/actions/toolkit/issues/193#issuecomment-605394935 + let escaped_announcement = announcement.replace('\n', "%0A"); + println!("::notice title=New CodSpeed Feature::{escaped_announcement}"); + return; + } + if get_json_event(record).is_some() { return; } @@ -70,10 +78,10 @@ impl Log for GithubActionLogger { Level::Debug => "::debug::", Level::Trace => "::debug::[TRACE]", }; - let message_string = message.to_string(); - let lines = message_string.lines(); - // ensure that all the lines of the message have the prefix, otherwise GitHub Actions will not recognize the command for the whole string - lines.for_each(|line| println!("{prefix}{line}")); + // properly escape newlines so that GitHub Actions interprets them correctly + // https://github.com/actions/toolkit/issues/193#issuecomment-605394935 + let message_string = message.to_string().replace('\n', "%0A"); + println!("{prefix}{message_string}"); } fn flush(&self) { diff --git a/src/run/run_environment/github_actions/provider.rs b/src/run/run_environment/github_actions/provider.rs index 609b2413..7b5b7c61 100644 --- a/src/run/run_environment/github_actions/provider.rs +++ b/src/run/run_environment/github_actions/provider.rs @@ -292,10 +292,10 @@ impl RunEnvironmentProvider for GitHubActionsProvider { fn check_oidc_configuration(&mut self, config: &Config) -> Result<()> { // Check if a static token is already set if config.token.is_some() { - info!( - "CodSpeed now supports OIDC tokens for authentication.\n\ - Benefit from enhanced security by adding the `id-token: write` permission to your workflow and removing the static token from your configuration.\n\ - Learn more at https://codspeed.io/docs/integrations/ci/github-actions/configuration#oidc-recommended" + announcement!( + "You can now authenticate your CI workflows using OpenID Connect (OIDC) tokens instead of `CODSPEED_TOKEN` secrets.\n\ + This makes integrating and authenticating jobs safer and simpler.\n\ + Learn more at https://codspeed.io/docs/integrations/ci/github-actions/configuration#oidc-recommended\n" ); return Ok(()); @@ -320,10 +320,10 @@ impl RunEnvironmentProvider for GitHubActionsProvider { ) } - info!( - "CodSpeed now supports OIDC tokens for authentication.\n\ - Benefit from enhanced security and faster processing times by adding the `id-token: write` permission to your workflow.\n\ - Learn more at https://codspeed.io/docs/integrations/ci/github-actions/configuration#oidc-recommended" + announcement!( + "You can now authenticate your CI workflows using OpenID Connect (OIDC).\n\ + This makes integrating and authenticating jobs safer and simpler.\n\ + Learn more at https://codspeed.io/docs/integrations/ci/github-actions/configuration#oidc-recommended\n" ); return Ok(()); diff --git a/src/run/run_environment/gitlab_ci/logger.rs b/src/run/run_environment/gitlab_ci/logger.rs index 03d55c89..35e2c36e 100644 --- a/src/run/run_environment/gitlab_ci/logger.rs +++ b/src/run/run_environment/gitlab_ci/logger.rs @@ -11,7 +11,7 @@ use std::{ }; use crate::{ - logger::{GroupEvent, get_group_event, get_json_event}, + logger::{GroupEvent, get_announcement_event, get_group_event, get_json_event}, run::run_environment::logger::should_provider_logger_handle_record, }; @@ -112,6 +112,11 @@ impl Log for GitLabCILogger { return; } + if let Some(announcement) = get_announcement_event(record) { + println!("{}", style(announcement).green()); + return; + } + if get_json_event(record).is_some() { return; }