feat: Don't advance next branch if the target commit message is invalid
Closes kemitix/git-next#33
This commit is contained in:
parent
cedaf16acf
commit
4e6a306a72
4 changed files with 82 additions and 15 deletions
|
@ -33,6 +33,9 @@ toml = "0.8"
|
||||||
# Secrets and Password
|
# Secrets and Password
|
||||||
secrecy = "0.8"
|
secrecy = "0.8"
|
||||||
|
|
||||||
|
# Conventional Commit check
|
||||||
|
git-conventional = "0.12"
|
||||||
|
|
||||||
# error handling
|
# error handling
|
||||||
terrors = "0.3"
|
terrors = "0.3"
|
||||||
|
|
||||||
|
|
|
@ -124,8 +124,10 @@ pub async fn advance_next(
|
||||||
warn!("No commits to advance next to");
|
warn!("No commits to advance next to");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
// TODO: (#33) get commit message for 'commit'
|
if let Some(problem) = validate_commit_message(commit.message()) {
|
||||||
// TODO: (#33) verify commit message is valid
|
warn!("Can't advance next to commit '{}': {}", commit, problem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
match reset(
|
match reset(
|
||||||
&repo_config.branches().next(),
|
&repo_config.branches().next(),
|
||||||
commit,
|
commit,
|
||||||
|
@ -144,6 +146,24 @@ pub async fn advance_next(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
fn validate_commit_message(message: &forge::Message) -> Option<String> {
|
||||||
|
let message = &message.to_string();
|
||||||
|
if message.to_ascii_lowercase().starts_with("wip") {
|
||||||
|
return Some("Is Work-In-Progress".to_string());
|
||||||
|
}
|
||||||
|
match git_conventional::Commit::parse(message) {
|
||||||
|
Ok(commit) => {
|
||||||
|
info!(?commit, "Pass");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!(?err, "Fail");
|
||||||
|
Some(err.kind().to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn find_next_commit_on_dev(
|
fn find_next_commit_on_dev(
|
||||||
next: forge::Commit,
|
next: forge::Commit,
|
||||||
dev_commit_history: Vec<forge::Commit>,
|
dev_commit_history: Vec<forge::Commit>,
|
||||||
|
@ -184,7 +204,7 @@ pub async fn advance_main(
|
||||||
pub struct GitRef(pub String);
|
pub struct GitRef(pub String);
|
||||||
impl From<forge::Commit> for GitRef {
|
impl From<forge::Commit> for GitRef {
|
||||||
fn from(value: forge::Commit) -> Self {
|
fn from(value: forge::Commit) -> Self {
|
||||||
Self(value.sha)
|
Self(value.sha().to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<BranchName> for GitRef {
|
impl From<BranchName> for GitRef {
|
||||||
|
@ -255,14 +275,15 @@ mod tests {
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_find_next_commit_on_dev() {
|
async fn test_find_next_commit_on_dev() {
|
||||||
let next = forge::Commit::new("current-next");
|
let next = forge::Commit::new("current-next", "foo");
|
||||||
|
let expected = forge::Commit::new("dev-next", "next-should-go-here");
|
||||||
let dev_commit_history = vec![
|
let dev_commit_history = vec![
|
||||||
forge::Commit::new("dev"),
|
forge::Commit::new("dev", "future"),
|
||||||
forge::Commit::new("dev-next"),
|
expected.clone(),
|
||||||
forge::Commit::new("current-next"),
|
next.clone(),
|
||||||
forge::Commit::new("current-main"),
|
forge::Commit::new("current-main", "history"),
|
||||||
];
|
];
|
||||||
let next_commit = find_next_commit_on_dev(next, dev_commit_history);
|
let next_commit = find_next_commit_on_dev(next, dev_commit_history);
|
||||||
assert_eq!(next_commit, Some(forge::Commit::new("dev-next")));
|
assert_eq!(next_commit, Some(expected));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,7 @@ async fn get_commit_history(
|
||||||
.response_body()
|
.response_body()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|commit| commit.sha)
|
.map(forge::Commit::from)
|
||||||
.map(|sha| forge::Commit { sha })
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let found = find_commits.is_empty()
|
let found = find_commits.is_empty()
|
||||||
|
@ -103,6 +102,17 @@ async fn get_commit_history(
|
||||||
#[derive(Debug, Default, serde::Deserialize)]
|
#[derive(Debug, Default, serde::Deserialize)]
|
||||||
struct Commit {
|
struct Commit {
|
||||||
sha: String,
|
sha: String,
|
||||||
|
commit: RepoCommit,
|
||||||
|
}
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug, Default, serde::Deserialize)]
|
||||||
|
struct RepoCommit {
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
impl From<Commit> for forge::Commit {
|
||||||
|
fn from(value: Commit) -> Self {
|
||||||
|
Self::new(&value.sha, &value.commit.message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_commit_status(
|
pub async fn get_commit_status(
|
||||||
|
|
|
@ -14,18 +14,51 @@ pub struct CommitHistories {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Commit {
|
pub struct Commit {
|
||||||
pub sha: String,
|
sha: Sha,
|
||||||
|
message: Message,
|
||||||
}
|
}
|
||||||
impl Commit {
|
impl Commit {
|
||||||
#[cfg(test)]
|
pub fn new(sha: &str, message: &str) -> Self {
|
||||||
pub fn new(sha: &str) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
sha: sha.to_string(),
|
sha: Sha::new(sha.to_string()),
|
||||||
|
message: Message::new(message.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub const fn sha(&self) -> &Sha {
|
||||||
|
&self.sha
|
||||||
|
}
|
||||||
|
pub const fn message(&self) -> &Message {
|
||||||
|
&self.message
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl Display for Commit {
|
impl Display for Commit {
|
||||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||||
write!(f, "{}", self.sha)
|
write!(f, "{}", self.sha)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Sha(String);
|
||||||
|
impl Sha {
|
||||||
|
pub const fn new(value: String) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Display for Sha {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Message(String);
|
||||||
|
impl Message {
|
||||||
|
pub const fn new(value: String) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Display for Message {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue