feat: add cuddle ci draft
All checks were successful
continuous-integration/drone/push Build is passing

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2023-11-25 21:41:17 +01:00
parent e29615cb05
commit 8cf148726a
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
4 changed files with 186 additions and 0 deletions

11
Cargo.lock generated
View File

@ -320,6 +320,17 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "cuddle-ci"
version = "0.2.0"
dependencies = [
"async-trait",
"clap",
"dagger-sdk",
"eyre",
"tokio",
]
[[package]] [[package]]
name = "cuddle-components" name = "cuddle-components"
version = "0.1.0" version = "0.1.0"

View File

@ -23,3 +23,7 @@ eyre = "0.6.9"
tokio = "1.34.0" tokio = "1.34.0"
dotenv = "0.15.0" dotenv = "0.15.0"
async-trait = "0.1.74" async-trait = "0.1.74"
color-eyre = "*"
clap = {version = "4", features = ["derive"]}
futures = "0.3.28"
async-scoped = { version = "0.7.1", features = ["tokio", "use-tokio"] }

View File

@ -0,0 +1,19 @@
[package]
name = "cuddle-ci"
version.workspace = true
edition.workspace = true
license.workspace = true
authors.workspace = true
readme.workspace = true
repository.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dagger-sdk.workspace = true
eyre.workspace = true
clap.workspace = true
async-trait.workspace = true
[dev-dependencies]
tokio.workspace = true

152
crates/cuddle-ci/src/lib.rs Normal file
View File

@ -0,0 +1,152 @@
use std::{env::Args, sync::Arc};
use async_trait::async_trait;
pub struct CuddleCI {
pr_action: Arc<dyn PullRequestAction + Send + Sync>,
main_action: Arc<dyn MainAction + Send + Sync>,
release_action: Arc<dyn ReleaseAction + Send + Sync>,
}
impl CuddleCI {
pub fn new(
pr: Arc<dyn PullRequestAction + Send + Sync>,
main: Arc<dyn MainAction + Send + Sync>,
release: Arc<dyn ReleaseAction + Send + Sync>,
) -> Self {
Self {
pr_action: pr,
main_action: main,
release_action: release,
}
}
pub fn with_pull_request(&mut self, pr: Arc<dyn PullRequestAction + Send + Sync>) -> &mut Self {
self.pr_action = pr;
self
}
pub fn with_main(&mut self, main: Arc<dyn MainAction + Send + Sync>) -> &mut Self {
self.main_action = main;
self
}
pub fn with_release(&mut self, release: Arc<dyn ReleaseAction + Send + Sync>) -> &mut Self {
self.release_action = release;
self
}
pub async fn execute(&mut self, args: impl IntoIterator<Item = &str>) -> eyre::Result<()> {
let matches = clap::Command::new("cuddle-ci")
.about("is a wrapper around common CI actions")
.subcommand(clap::Command::new("pr"))
.subcommand(clap::Command::new("main"))
.subcommand(clap::Command::new("release"))
.subcommand_required(true)
.try_get_matches_from(args.into_iter())?;
match matches.subcommand() {
Some((name, args)) => match (name, args) {
("pr", args) => {
eprintln!("starting pr validate");
self.pr_action.validate().await?;
eprintln!("finished pr validate");
}
("main", args) => {
eprintln!("starting main validate");
self.main_action.validate().await?;
eprintln!("finished main validate");
}
("release", args) => {
eprintln!("starting release validate");
self.release_action.validate().await?;
eprintln!("finished release validate");
}
(command_name, _) => {
eyre::bail!("command is not recognized: {}", command_name)
}
},
None => eyre::bail!("command required a subcommand [pr, main, release] etc."),
}
Ok(())
}
}
impl Default for CuddleCI {
fn default() -> Self {
Self::new(
Arc::new(DefaultPullRequestAction {}),
Arc::new(DefaultMainAction {}),
Arc::new(DefaultReleaseAction {}),
)
}
}
#[async_trait]
pub trait PullRequestAction {
async fn validate(&self) -> eyre::Result<()> {
Ok(())
}
}
pub struct DefaultPullRequestAction {}
#[async_trait]
impl PullRequestAction for DefaultPullRequestAction {}
#[async_trait]
pub trait MainAction {
async fn validate(&self) -> eyre::Result<()> {
Ok(())
}
}
pub struct DefaultMainAction {}
#[async_trait]
impl MainAction for DefaultMainAction {}
#[async_trait]
pub trait ReleaseAction {
async fn validate(&self) -> eyre::Result<()> {
Ok(())
}
}
pub struct DefaultReleaseAction {}
#[async_trait]
impl ReleaseAction for DefaultReleaseAction {}
#[cfg(test)]
mod test {
use super::*;
#[tokio::test]
async fn test_can_call_default() -> eyre::Result<()> {
CuddleCI::default().execute(["cuddle-ci", "pr"]).await?;
Ok(())
}
#[tokio::test]
async fn test_fails_on_no_command() -> eyre::Result<()> {
let res = CuddleCI::default().execute(["cuddle-ci"]).await;
assert!(res.is_err());
Ok(())
}
#[tokio::test]
async fn test_fails_on_wrong_command() -> eyre::Result<()> {
let res = CuddleCI::default()
.execute(["cuddle-ci", "something"])
.await;
assert!(res.is_err());
Ok(())
}
}