diff options
author | Justin Worthe <justin@jemstep.com> | 2020-03-04 15:34:40 +0200 |
---|---|---|
committer | Justin Worthe <justin@jemstep.com> | 2020-03-04 15:34:40 +0200 |
commit | 424163218c152e3bc5f5d00efd1ed10d2706a7ac (patch) | |
tree | 8b5862b50f708df53f2506dacbc4e30d4c1e2b47 | |
parent | 9f792b1b2154dc4f0a2e54cabf7c75d7e700ce81 (diff) |
PYKE-11910: Added checks for verifying code is rebased before merging into mainline
-rw-r--r-- | src/config.rs | 2 | ||||
-rw-r--r-- | src/policies.rs | 56 | ||||
-rw-r--r-- | tests/policies_test.rs | 1 |
3 files changed, 59 insertions, 0 deletions
diff --git a/src/config.rs b/src/config.rs index e2a983e..07ca998 100644 --- a/src/config.rs +++ b/src/config.rs @@ -38,6 +38,8 @@ pub struct VerifyGitCommitsConfig { #[serde(default = "default_false")] pub verify_different_authors: bool, + #[serde(default = "default_false")] + pub verify_rebased: bool, #[serde(default)] pub override_tag_pattern: Option<String>, diff --git a/src/policies.rs b/src/policies.rs index b3a6fdb..863f394 100644 --- a/src/policies.rs +++ b/src/policies.rs @@ -25,6 +25,7 @@ pub enum PolicyResult { MissingAuthorEmail(Oid), InvalidCommitterEmail(Oid, String), MissingCommitterEmail(Oid), + NotRebased(Oid), } impl PolicyResult { @@ -58,6 +59,7 @@ impl fmt::Display for PolicyResult { MissingAuthorEmail(id) => write!(f, "Commit does not have an author email: {}", id), InvalidCommitterEmail(id, email) => write!(f, "Commit has an invalid committer email ({}): {}", email, id), MissingCommitterEmail(id) => write!(f, "Commit does not have a committer email: {}", id), + NotRebased(id) => write!(f, "Merge commit needs to be rebased on the mainline before it can be merged: {}", id) } } } @@ -157,6 +159,16 @@ pub fn verify_git_commits<G: Git, P: Gpg>( ref_name, )?); } + + if config.verify_rebased { + policy_result = policy_result.and(verify_rebased::<G>( + &all_commits, + git, + old_commit_id, + new_commit_id, + ref_name, + )?); + } } info!( @@ -355,6 +367,50 @@ fn verify_different_authors<G: Git>( } } +fn verify_rebased<G: Git>( + commits: &[Commit], + git: &G, + old_commit_id: Oid, + new_commit_id: Oid, + ref_name: &str, +) -> Result<PolicyResult, Box<dyn Error>> { + let new_branch = old_commit_id.is_zero(); + let is_merge = git.is_merge_commit(new_commit_id); + let is_mainline = git.is_mainline(ref_name)?; + + if !is_mainline { + info!( + "Rebase verification passed for {}: Not updating a mainline branch", + new_commit_id + ); + Ok(PolicyResult::Ok) + } else if !is_merge { + info!("Rebase verification passed for {}: Not a merge commit, does not require multiple authors", new_commit_id); + Ok(PolicyResult::Ok) + } else if new_branch { + info!("Rebase verification passed for {}: New branch does not require multiple authors for a merge commit", new_commit_id); + Ok(PolicyResult::Ok) + } else if commits.len() == 0 { + info!("Rebase verification passed for {}: No new commits pushed, does not require multiple authors", new_commit_id); + Ok(PolicyResult::Ok) + } else { + let new_commit_is_identical_tree_to_parent = commits + .iter() + .find(|commit| commit.id == new_commit_id && commit.is_identical_tree_to_any_parent) + .is_some(); + if new_commit_is_identical_tree_to_parent { + info!( + "Rebase verification passed for {}: Branch is up to date rebased", + new_commit_id + ); + Ok(PolicyResult::Ok) + } else { + error!("Rebase verification failed for {}: branch must be rebased before it can be merged into the mainline", new_commit_id); + Ok(PolicyResult::NotRebased(new_commit_id)) + } + } +} + fn verify_email_addresses( author_domain: &str, committer_domain: &str, diff --git a/tests/policies_test.rs b/tests/policies_test.rs index bff0834..31e9e78 100644 --- a/tests/policies_test.rs +++ b/tests/policies_test.rs @@ -54,6 +54,7 @@ fn verify_commits_config() -> VerifyGitCommitsConfig { verify_email_addresses: true, verify_commit_signatures: true, verify_different_authors: true, + verify_rebased: false, override_tag_pattern: Some("capn-override-*".to_string()), override_tags_required: 1, } |