feat: with git client
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
0b66de6daf
commit
b5e8c78c89
86
Cargo.lock
generated
86
Cargo.lock
generated
@ -253,10 +253,12 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"conventional_commit_parser",
|
"conventional_commit_parser",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"pretty_assertions",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"semver",
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
|
"tempdir",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@ -264,6 +266,12 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diff"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.7"
|
version = "0.10.7"
|
||||||
@ -352,6 +360,12 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-cprng"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.28"
|
version = "0.3.28"
|
||||||
@ -861,6 +875,16 @@ version = "0.3.27"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pretty_assertions"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
|
||||||
|
dependencies = [
|
||||||
|
"diff",
|
||||||
|
"yansi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.66"
|
version = "1.0.66"
|
||||||
@ -879,6 +903,43 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||||
|
dependencies = [
|
||||||
|
"fuchsia-cprng",
|
||||||
|
"libc",
|
||||||
|
"rand_core 0.3.1",
|
||||||
|
"rdrand",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.4.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rdrand"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.3.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
@ -932,6 +993,15 @@ version = "0.7.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "remove_dir_all"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.18"
|
version = "0.11.18"
|
||||||
@ -1176,6 +1246,16 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempdir"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
||||||
|
dependencies = [
|
||||||
|
"rand",
|
||||||
|
"remove_dir_all",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.7.0"
|
version = "3.7.0"
|
||||||
@ -1648,3 +1728,9 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yansi"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||||
|
@ -17,7 +17,8 @@ serde_yaml = {version = "*"}
|
|||||||
serde = {version = "*", features = ["derive"]}
|
serde = {version = "*", features = ["derive"]}
|
||||||
semver = "1.0.18"
|
semver = "1.0.18"
|
||||||
conventional_commit_parser = "0.9.4"
|
conventional_commit_parser = "0.9.4"
|
||||||
|
tempdir = "*"
|
||||||
reqwest = {version = "*"}
|
reqwest = {version = "*"}
|
||||||
|
|
||||||
tracing-test = "*"
|
tracing-test = "*"
|
||||||
|
pretty_assertions = "*"
|
@ -16,7 +16,9 @@ reqwest = {workspace = true, features = ["blocking", "json"]}
|
|||||||
url.workspace = true
|
url.workspace = true
|
||||||
semver.workspace = true
|
semver.workspace = true
|
||||||
conventional_commit_parser.workspace = true
|
conventional_commit_parser.workspace = true
|
||||||
|
tempdir.workspace = true
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tracing-test = {workspace = true, features = ["no-env-filter"]}
|
tracing-test = {workspace = true, features = ["no-env-filter"]}
|
||||||
|
pretty_assertions.workspace = true
|
@ -10,6 +10,7 @@ impl VcsClient {
|
|||||||
pub fn new_noop() -> VcsClient {
|
pub fn new_noop() -> VcsClient {
|
||||||
Self::Noop {}
|
Self::Noop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_git(path: &Path) -> anyhow::Result<VcsClient> {
|
pub fn new_git(path: &Path) -> anyhow::Result<VcsClient> {
|
||||||
if !path.to_path_buf().join(".git").exists() {
|
if !path.to_path_buf().join(".git").exists() {
|
||||||
anyhow::bail!("git directory not found in: {}", path.display().to_string())
|
anyhow::bail!("git directory not found in: {}", path.display().to_string())
|
||||||
@ -19,4 +20,57 @@ impl VcsClient {
|
|||||||
source: path.to_path_buf(),
|
source: path.to_path_buf(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn checkout_branch(&self) -> anyhow::Result<()> {
|
||||||
|
match self {
|
||||||
|
VcsClient::Noop {} => {}
|
||||||
|
VcsClient::Git { .. } => {
|
||||||
|
if let Err(e) = self.exec_git(&["branch", "-D", "cuddle-please/release"]) {
|
||||||
|
tracing::debug!("failed to cleaned up local branch for force-push, this may be because it didn't exist before running this command");
|
||||||
|
}
|
||||||
|
self.exec_git(&["checkout", "-b", "cuddle-please/release"])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exec_git(&self, args: &[&str]) -> anyhow::Result<()> {
|
||||||
|
match self {
|
||||||
|
VcsClient::Noop {} => {}
|
||||||
|
VcsClient::Git { source } => {
|
||||||
|
let checkout_branch = std::process::Command::new("git")
|
||||||
|
.current_dir(source.as_path())
|
||||||
|
.args(args)
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
let stdout = std::str::from_utf8(&checkout_branch.stdout)?;
|
||||||
|
let stderr = std::str::from_utf8(&checkout_branch.stderr)?;
|
||||||
|
tracing::debug!(stdout = stdout, stderr = stderr, "git {}", args.join(" "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn commit_and_push(&self, version: impl Into<String>, dry_run: bool) -> anyhow::Result<()> {
|
||||||
|
match self {
|
||||||
|
VcsClient::Noop {} => {}
|
||||||
|
VcsClient::Git { .. } => {
|
||||||
|
self.exec_git(&["add", "."])?;
|
||||||
|
self.exec_git(&[
|
||||||
|
"commit",
|
||||||
|
"-m",
|
||||||
|
&format!("chore(release): {}", version.into()),
|
||||||
|
])?;
|
||||||
|
|
||||||
|
tracing::trace!("git push -u -f origin cuddle-please/release");
|
||||||
|
if !dry_run {
|
||||||
|
self.exec_git(&["push", "-u", "-f", "origin", "cuddle-please/release"])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
182
crates/cuddle-please/tests/git.rs
Normal file
182
crates/cuddle-please/tests/git.rs
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use cuddle_please::git_client::VcsClient;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use tracing_test::traced_test;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[traced_test]
|
||||||
|
fn exec_git_into_branch() {
|
||||||
|
let tempdir = tempdir::TempDir::new("exec_git_into_branch").unwrap();
|
||||||
|
|
||||||
|
setup_git(tempdir.path()).unwrap();
|
||||||
|
|
||||||
|
add_commit(tempdir.path(), "first").unwrap();
|
||||||
|
add_tag(tempdir.path(), "1.0.0").unwrap();
|
||||||
|
|
||||||
|
add_commit(tempdir.path(), "second").unwrap();
|
||||||
|
add_tag(tempdir.path(), "1.0.1").unwrap();
|
||||||
|
|
||||||
|
let vcs = VcsClient::new_git(tempdir.path()).unwrap();
|
||||||
|
vcs.checkout_branch().unwrap();
|
||||||
|
|
||||||
|
let output = std::process::Command::new("git")
|
||||||
|
.arg("branch")
|
||||||
|
.current_dir(tempdir.path())
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let stdout = std::str::from_utf8(&output.stdout).unwrap();
|
||||||
|
let stderr = std::str::from_utf8(&output.stderr).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
"* cuddle-please/release
|
||||||
|
main
|
||||||
|
",
|
||||||
|
stdout
|
||||||
|
);
|
||||||
|
assert_eq!("", stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[traced_test]
|
||||||
|
fn add_files_to_commit() {
|
||||||
|
let tempdir = tempdir::TempDir::new("add_files_to_commit").unwrap();
|
||||||
|
|
||||||
|
setup_git(tempdir.path()).unwrap();
|
||||||
|
|
||||||
|
add_commit(tempdir.path(), "first").unwrap();
|
||||||
|
add_tag(tempdir.path(), "1.0.0").unwrap();
|
||||||
|
|
||||||
|
let vcs = VcsClient::new_git(tempdir.path()).unwrap();
|
||||||
|
vcs.checkout_branch().unwrap();
|
||||||
|
|
||||||
|
std::fs::File::create(tempdir.path().join("changelog")).unwrap();
|
||||||
|
vcs.commit_and_push("with some file", true).unwrap();
|
||||||
|
|
||||||
|
let output = std::process::Command::new("git")
|
||||||
|
.arg("log")
|
||||||
|
.current_dir(tempdir.path())
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let stdout = std::str::from_utf8(&output.stdout).unwrap();
|
||||||
|
let stderr = std::str::from_utf8(&output.stderr).unwrap();
|
||||||
|
|
||||||
|
assert!(stdout.contains("chore(release): with some file"));
|
||||||
|
assert_eq!("", stderr);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
#[traced_test]
|
||||||
|
fn reset_branch() {
|
||||||
|
let tempdir = tempdir::TempDir::new("add_files_to_commit").unwrap();
|
||||||
|
|
||||||
|
setup_git(tempdir.path()).unwrap();
|
||||||
|
|
||||||
|
add_commit(tempdir.path(), "first").unwrap();
|
||||||
|
add_tag(tempdir.path(), "1.0.0").unwrap();
|
||||||
|
|
||||||
|
let vcs = VcsClient::new_git(tempdir.path()).unwrap();
|
||||||
|
vcs.checkout_branch().unwrap();
|
||||||
|
|
||||||
|
std::fs::File::create(tempdir.path().join("changelog-first")).unwrap();
|
||||||
|
vcs.commit_and_push("v1.0.0", true).unwrap();
|
||||||
|
|
||||||
|
exec_git(tempdir.path(), &["checkout", "main"]).unwrap();
|
||||||
|
vcs.checkout_branch().unwrap();
|
||||||
|
|
||||||
|
std::fs::File::create(tempdir.path().join("changelog-second")).unwrap();
|
||||||
|
vcs.commit_and_push("v1.0.1", true).unwrap();
|
||||||
|
|
||||||
|
let output = std::process::Command::new("git")
|
||||||
|
.arg("log")
|
||||||
|
.current_dir(tempdir.path())
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let stdout = std::str::from_utf8(&output.stdout).unwrap();
|
||||||
|
let stderr = std::str::from_utf8(&output.stderr).unwrap();
|
||||||
|
|
||||||
|
assert!(stdout.contains("chore(release): v1.0.1"));
|
||||||
|
assert!(!stdout.contains("chore(release): v1.0.0"));
|
||||||
|
assert_eq!("", stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_tag(path: &Path, arg: &str) -> anyhow::Result<()> {
|
||||||
|
add_everything(path)?;
|
||||||
|
|
||||||
|
let output = std::process::Command::new("git")
|
||||||
|
.arg("tag")
|
||||||
|
.arg("-a")
|
||||||
|
.arg(arg)
|
||||||
|
.arg("-m")
|
||||||
|
.arg(arg)
|
||||||
|
.current_dir(path)
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
let stdout = std::str::from_utf8(&output.stdout)?;
|
||||||
|
let stderr = std::str::from_utf8(&output.stderr)?;
|
||||||
|
tracing::debug!(stdout = stdout, stderr = stderr, "git init");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_commit(path: &Path, arg: &str) -> anyhow::Result<()> {
|
||||||
|
std::fs::File::create(path.join(arg))?;
|
||||||
|
|
||||||
|
add_everything(path)?;
|
||||||
|
|
||||||
|
let output = std::process::Command::new("git")
|
||||||
|
.arg("commit")
|
||||||
|
.arg("-m")
|
||||||
|
.arg(arg)
|
||||||
|
.current_dir(path)
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
let stdout = std::str::from_utf8(&output.stdout)?;
|
||||||
|
let stderr = std::str::from_utf8(&output.stderr)?;
|
||||||
|
tracing::debug!(stdout = stdout, stderr = stderr, "git init");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_everything(path: &Path) -> anyhow::Result<()> {
|
||||||
|
let output = std::process::Command::new("git")
|
||||||
|
.arg("add")
|
||||||
|
.arg(".")
|
||||||
|
.current_dir(path)
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
let stdout = std::str::from_utf8(&output.stdout)?;
|
||||||
|
let stderr = std::str::from_utf8(&output.stderr)?;
|
||||||
|
tracing::debug!(stdout = stdout, stderr = stderr, "git add .");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_git(path: &Path) -> anyhow::Result<()> {
|
||||||
|
let output = std::process::Command::new("git")
|
||||||
|
.arg("init")
|
||||||
|
.arg(".")
|
||||||
|
.current_dir(path)
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
let stdout = std::str::from_utf8(&output.stdout)?;
|
||||||
|
let stderr = std::str::from_utf8(&output.stderr)?;
|
||||||
|
tracing::debug!(stdout = stdout, stderr = stderr, "git init");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exec_git(path: &Path, args: &[&str]) -> anyhow::Result<()> {
|
||||||
|
let checkout_branch = std::process::Command::new("git")
|
||||||
|
.current_dir(path)
|
||||||
|
.args(args)
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
let stdout = std::str::from_utf8(&checkout_branch.stdout)?;
|
||||||
|
let stderr = std::str::from_utf8(&checkout_branch.stderr)?;
|
||||||
|
tracing::debug!(stdout = stdout, stderr = stderr, "git {}", args.join(" "));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user