Skip to content
Open
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
30 changes: 23 additions & 7 deletions src/ownership/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,18 +208,34 @@ impl Error {

vec![messages.join("\n")]
}
Error::CodeownershipFileIsStale { executable_name: _, diff } => {
if diff.is_empty() {
vec![]
} else {
vec![format!("The following changes are required (- current, + expected):\n{diff}")]
}
}
// The diff is intentionally *not* rendered as part of the error. It is
// surfaced separately as an informational message (see `Errors::info_messages`)
// so that a long diff doesn't bury the actionable headline.
Error::CodeownershipFileIsStale { .. } => vec![],
Error::InvalidTeam { name, path } => vec![format!("- {} is referencing an invalid team - '{}'", path.to_string_lossy(), name)],
}
}
}

impl Errors {
/// Supplementary detail that explains *what* is wrong without itself being an error.
/// The stale-CODEOWNERS diff is surfaced here, as informational output, rather than
/// inline with the error so that a long diff doesn't bury the actionable headline in
/// CI logs (and so the wrapping `code_ownership` gem raises only the headline rather
/// than the entire diff).
pub fn info_messages(&self) -> Vec<String> {
self.0
.iter()
.filter_map(|error| match error {
Error::CodeownershipFileIsStale { diff, .. } if !diff.is_empty() => {
Some(format!("The following changes are required (- current, + expected):\n{diff}"))
}
_ => None,
})
.collect()
}
}

impl Display for Errors {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let grouped_errors = self.0.iter().into_group_map_by(|error| error.category());
Expand Down
3 changes: 3 additions & 0 deletions src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ impl Runner {
match self.ownership.validate() {
Ok(_) => RunResult::default(),
Err(err) => RunResult {
// The stale-CODEOWNERS diff (if any) rides along as informational output,
// printed ahead of the errors, so the actionable headline isn't buried.
info_messages: err.info_messages(),
validation_errors: vec![format!("{}", err)],
..Default::default()
},
Expand Down
8 changes: 4 additions & 4 deletions tests/executable_name_config_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ fn test_custom_executable_name_full_error_message() -> Result<(), Box<dyn Error>
false,
OutputStream::Stdout,
predicate::eq(indoc! {r#"

CODEOWNERS out of date. Run `bin/codeownership validate` to update the CODEOWNERS file
The following changes are required (- current, + expected):
-# Outdated content to trigger validation error
-/app/old.rb @FooTeam
Expand All @@ -57,6 +55,8 @@ fn test_custom_executable_name_full_error_message() -> Result<(), Box<dyn Error>
+/config/teams/foo.yml @FooTeam
+/config/teams/payments.yml @PaymentTeam

CODEOWNERS out of date. Run `bin/codeownership validate` to update the CODEOWNERS file

"#}),
)?;
Ok(())
Expand All @@ -71,8 +71,6 @@ fn test_default_executable_name_full_error_message() -> Result<(), Box<dyn Error
false,
OutputStream::Stdout,
predicate::eq(indoc! {r#"

CODEOWNERS out of date. Run `codeowners generate` to update the CODEOWNERS file
The following changes are required (- current, + expected):
-# Outdated content to trigger validation error
-/app/old.rb @BarTeam
Expand All @@ -82,6 +80,8 @@ fn test_default_executable_name_full_error_message() -> Result<(), Box<dyn Error
+# Team YML ownership
+/config/teams/bar.yml @BarTeam

CODEOWNERS out of date. Run `codeowners generate` to update the CODEOWNERS file

"#}),
)?;
Ok(())
Expand Down
4 changes: 2 additions & 2 deletions tests/invalid_project_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ fn test_validate() -> Result<(), Box<dyn Error>> {
false,
OutputStream::Stdout,
predicate::eq(indoc! {"

CODEOWNERS out of date. Run `codeowners generate` to update the CODEOWNERS file
The following changes are required (- current, + expected):
+# STOP! - DO NOT EDIT THIS FILE MANUALLY
+# This file was automatically generated by \"bin/codeownership validate\".
Expand Down Expand Up @@ -47,6 +45,8 @@ fn test_validate() -> Result<(), Box<dyn Error>> {
+# Team owned gems
+/gems/payroll_calculator/**/** @PayrollTeam

CODEOWNERS out of date. Run `codeowners generate` to update the CODEOWNERS file

Code ownership should only be defined for each file in one way. The following files have declared ownership in multiple ways

gems/payroll_calculator/calculator.rb
Expand Down
Loading