summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Worthe <justin@jemstep.com>2020-03-04 15:34:40 +0200
committerJustin Worthe <justin@jemstep.com>2020-03-04 15:34:40 +0200
commit424163218c152e3bc5f5d00efd1ed10d2706a7ac (patch)
tree8b5862b50f708df53f2506dacbc4e30d4c1e2b47
parent9f792b1b2154dc4f0a2e54cabf7c75d7e700ce81 (diff)
PYKE-11910: Added checks for verifying code is rebased before merging into mainline
-rw-r--r--src/config.rs2
-rw-r--r--src/policies.rs56
-rw-r--r--tests/policies_test.rs1
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,
}