diff --git a/dco2/src/dco/mod.rs b/dco2/src/dco/mod.rs index a2dea86..101c10e 100644 --- a/dco2/src/dco/mod.rs +++ b/dco2/src/dco/mod.rs @@ -140,19 +140,23 @@ pub fn check(input: &CheckInput) -> CheckOutput { } // Validate author and committer emails - if let Err(errs) = validate_emails(commit) { - commit_output.errors.extend(errs); - } + let emails_are_valid = match validate_emails(commit) { + Ok(()) => true, + Err(errors) => { + commit_output.errors.extend(errors); + false + } + }; // Check if sign-off is present let signoffs = get_signoffs(commit); if signoffs.is_empty() { commit_output.errors.push(CommitError::SignOffNotFound); - } else { - // Check if any of the sign-offs matches the author's or committer's email - if !signoffs_match(&signoffs, commit) { - commit_output.errors.push(CommitError::SignOffMismatch); - } + } + + // Check if any of the sign-offs matches the author's or committer's email + if emails_are_valid && !signoffs.is_empty() && !signoffs_match(&signoffs, commit) { + commit_output.errors.push(CommitError::SignOffMismatch); } // Track commit if it has errors diff --git a/dco2/src/dco/tests.rs b/dco2/src/dco/tests.rs index 6f101d0..b5c87d0 100644 --- a/dco2/src/dco/tests.rs +++ b/dco2/src/dco/tests.rs @@ -1,5 +1,10 @@ +use std::vec; + use super::{check, CheckInput}; -use crate::github::{Commit, GitUser}; +use crate::{ + dco::{CommitCheckOutput, CommitError}, + github::{Commit, GitUser}, +}; use indoc::indoc; #[test] @@ -206,3 +211,197 @@ fn check_valid_signoff_single_commit_email_contains_plus_alias() { assert!(output.commits_with_errors.is_empty()); } + +#[test] +fn check_invalid_author_email_single_commit() { + let commit1 = Commit { + author: Some(GitUser { + name: "user1".to_string(), + email: "invalid".to_string(), + ..Default::default() + }), + message: indoc! {r" + Test commit message + + Signed-off-by: user1 + "} + .to_string(), + ..Default::default() + }; + + let input = CheckInput { + commits: vec![commit1.clone()], + }; + let output = check(&input); + + assert_eq!( + output.commits_with_errors, + vec![CommitCheckOutput { + commit: commit1, + errors: vec![CommitError::InvalidAuthorEmail], + }] + ); +} + +#[test] +fn check_invalid_author_email_and_no_signoff_single_commit() { + let commit1 = Commit { + author: Some(GitUser { + name: "user1".to_string(), + email: "invalid".to_string(), + ..Default::default() + }), + message: "Test commit message".to_string(), + ..Default::default() + }; + + let input = CheckInput { + commits: vec![commit1.clone()], + }; + let output = check(&input); + + assert_eq!( + output.commits_with_errors, + vec![CommitCheckOutput { + commit: commit1, + errors: vec![CommitError::InvalidAuthorEmail, CommitError::SignOffNotFound], + }] + ); +} + +#[test] +fn check_invalid_committer_email_single_commit() { + let commit1 = Commit { + committer: Some(GitUser { + name: "user1".to_string(), + email: "invalid".to_string(), + ..Default::default() + }), + message: indoc! {r" + Test commit message + + Signed-off-by: user1 + "} + .to_string(), + ..Default::default() + }; + + let input = CheckInput { + commits: vec![commit1.clone()], + }; + let output = check(&input); + + assert_eq!( + output.commits_with_errors, + vec![CommitCheckOutput { + commit: commit1, + errors: vec![CommitError::InvalidCommitterEmail], + }] + ); +} + +#[test] +fn check_invalid_author_and_committer_email_single_commit_same_email() { + let commit1 = Commit { + author: Some(GitUser { + name: "user1".to_string(), + email: "invalid".to_string(), + ..Default::default() + }), + committer: Some(GitUser { + name: "user1".to_string(), + email: "invalid".to_string(), + ..Default::default() + }), + message: indoc! {r" + Test commit message + + Signed-off-by: user1 + "} + .to_string(), + ..Default::default() + }; + + let input = CheckInput { + commits: vec![commit1.clone()], + }; + let output = check(&input); + + assert_eq!( + output.commits_with_errors, + vec![CommitCheckOutput { + commit: commit1, + errors: vec![CommitError::InvalidCommitterEmail], + }] + ); +} + +#[test] +fn check_invalid_author_and_committer_email_single_commit_different_emails() { + let commit1 = Commit { + author: Some(GitUser { + name: "user1".to_string(), + email: "invalid".to_string(), + ..Default::default() + }), + committer: Some(GitUser { + name: "user1".to_string(), + email: "invalid2".to_string(), + ..Default::default() + }), + message: indoc! {r" + Test commit message + + Signed-off-by: user1 + "} + .to_string(), + ..Default::default() + }; + + let input = CheckInput { + commits: vec![commit1.clone()], + }; + let output = check(&input); + + assert_eq!( + output.commits_with_errors, + vec![CommitCheckOutput { + commit: commit1, + errors: vec![ + CommitError::InvalidCommitterEmail, + CommitError::InvalidAuthorEmail + ], + }] + ); +} + +#[test] +fn check_signoff_not_found_single_commit() { + let commit1 = Commit { + author: Some(GitUser { + name: "user1".to_string(), + email: "user1@email.test".to_string(), + ..Default::default() + }), + committer: Some(GitUser { + name: "user1".to_string(), + email: "user1@email.test".to_string(), + ..Default::default() + }), + message: "Test commit message".to_string(), + ..Default::default() + }; + + let input = CheckInput { + commits: vec![commit1.clone()], + }; + let output = check(&input); + + assert_eq!( + output.commits_with_errors, + vec![CommitCheckOutput { + commit: commit1, + errors: vec![CommitError::SignOffNotFound], + }] + ); +}