diff --git a/README.md b/README.md index 3402d3d8b8..23ba143c9f 100644 --- a/README.md +++ b/README.md @@ -1465,7 +1465,7 @@ line-length = 120 #### [`format`](#format) The style in which violation messages should be formatted: `"text"` (default), `"grouped"` -(group messages by file), `"json"` (machine-readable), or `"junit"` (machine-readable XML). +(group messages by file), `"json"` (machine-readable), `"junit"` (machine-readable XML), or `"github"` (GitHub Actions annotations). **Default value**: `"text"` diff --git a/src/commands.rs b/src/commands.rs index 9f5624c762..645358c52d 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -64,6 +64,9 @@ pub fn explain(code: &CheckCode, format: SerializationFormat) -> Result<()> { SerializationFormat::Junit => { bail!("`--explain` does not support junit format") } + SerializationFormat::Github => { + bail!("`--explain` does not support GitHub format") + } }; Ok(()) } diff --git a/src/printer.rs b/src/printer.rs index 271bb38adf..7414b4a974 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -192,6 +192,25 @@ impl<'a> Printer<'a> { self.post_text(num_fixable); } + SerializationFormat::Github => { + self.pre_text(diagnostics); + + // Generate error workflow command in GitHub Actions format + // https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + diagnostics.messages.iter().for_each(|message| { + println!( + "::notice title=Ruff,file={},line={},col={},endLine={},endColumn={}::({}) \ + {}", + relativize_path(Path::new(&message.filename)), + message.location.row(), + message.location.column(), + message.end_location.row(), + message.end_location.column(), + message.kind.code(), + message.kind.body(), + ); + }); + } } Ok(()) diff --git a/src/settings/configuration.rs b/src/settings/configuration.rs index 6c0c9ce888..b07966087d 100644 --- a/src/settings/configuration.rs +++ b/src/settings/configuration.rs @@ -123,7 +123,7 @@ impl Configuration { fix: options.fix.unwrap_or_default(), fixable: options.fixable.unwrap_or_else(|| CATEGORIES.to_vec()), unfixable: options.unfixable.unwrap_or_default(), - format: options.format.unwrap_or(SerializationFormat::Text), + format: options.format.unwrap_or_default(), ignore: options.ignore.unwrap_or_default(), line_length: options.line_length.unwrap_or(88), per_file_ignores: options diff --git a/src/settings/types.rs b/src/settings/types.rs index d32a6f5ea3..fbe4099b5f 100644 --- a/src/settings/types.rs +++ b/src/settings/types.rs @@ -1,4 +1,5 @@ use std::collections::BTreeSet; +use std::env; use std::hash::Hash; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -150,4 +151,16 @@ pub enum SerializationFormat { Json, Junit, Grouped, + Github, +} + +impl Default for SerializationFormat { + fn default() -> Self { + if let Ok(github_actions) = env::var("GITHUB_ACTIONS") { + if github_actions == "true" { + return Self::Github; + } + } + Self::Text + } }