2023-11-27 13:42:13 +01:00
|
|
|
use std::sync::Arc;
|
2023-11-25 23:09:49 +01:00
|
|
|
|
|
|
|
use async_trait::async_trait;
|
2023-11-27 19:14:31 +01:00
|
|
|
use tokio::sync::Mutex;
|
2023-11-25 23:09:49 +01:00
|
|
|
|
|
|
|
pub struct CuddleCI {
|
2023-12-29 19:43:04 +01:00
|
|
|
pr_action: Vec<Arc<Mutex<dyn PullRequestAction + Send + Sync>>>,
|
|
|
|
main_action: Vec<Arc<Mutex<dyn MainAction + Send + Sync>>>,
|
|
|
|
release_action: Vec<Arc<Mutex<dyn ReleaseAction + Send + Sync>>>,
|
2023-11-25 23:09:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl CuddleCI {
|
|
|
|
pub fn new(
|
2023-11-27 19:14:31 +01:00
|
|
|
pr: Arc<Mutex<dyn PullRequestAction + Send + Sync>>,
|
|
|
|
main: Arc<Mutex<dyn MainAction + Send + Sync>>,
|
|
|
|
release: Arc<Mutex<dyn ReleaseAction + Send + Sync>>,
|
2023-11-25 23:09:49 +01:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
2023-12-29 19:43:04 +01:00
|
|
|
pr_action: vec![pr],
|
|
|
|
main_action: vec![main],
|
|
|
|
release_action: vec![release],
|
2023-11-25 23:09:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-27 19:14:31 +01:00
|
|
|
pub fn with_pull_request(
|
|
|
|
&mut self,
|
|
|
|
pr: Arc<Mutex<dyn PullRequestAction + Send + Sync>>,
|
|
|
|
) -> &mut Self {
|
2023-12-29 19:43:04 +01:00
|
|
|
self.pr_action.push(pr);
|
2023-11-25 23:09:49 +01:00
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2023-11-27 19:14:31 +01:00
|
|
|
pub fn with_main(&mut self, main: Arc<Mutex<dyn MainAction + Send + Sync>>) -> &mut Self {
|
2023-12-29 19:43:04 +01:00
|
|
|
self.main_action.push(main);
|
2023-11-25 23:09:49 +01:00
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2023-11-27 19:14:31 +01:00
|
|
|
pub fn with_release(
|
|
|
|
&mut self,
|
|
|
|
release: Arc<Mutex<dyn ReleaseAction + Send + Sync>>,
|
|
|
|
) -> &mut Self {
|
2023-12-29 19:43:04 +01:00
|
|
|
self.release_action.push(release);
|
2023-11-25 23:09:49 +01:00
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2023-11-27 20:19:50 +01:00
|
|
|
pub async fn execute(
|
|
|
|
&mut self,
|
|
|
|
args: impl IntoIterator<Item = impl Into<String>>,
|
|
|
|
) -> eyre::Result<()> {
|
2023-11-25 23:09:49 +01:00
|
|
|
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)
|
2023-11-27 20:19:50 +01:00
|
|
|
.try_get_matches_from(args.into_iter().map(|a| a.into()).collect::<Vec<String>>())?;
|
2023-11-25 23:09:49 +01:00
|
|
|
|
|
|
|
match matches.subcommand() {
|
|
|
|
Some((name, args)) => match (name, args) {
|
2023-11-25 23:14:38 +01:00
|
|
|
("pr", _args) => {
|
2023-11-25 23:09:49 +01:00
|
|
|
eprintln!("starting pr validate");
|
2023-12-29 19:43:04 +01:00
|
|
|
for pr_action in self.pr_action.iter() {
|
|
|
|
pr_action.lock().await.execute_pull_request().await?;
|
|
|
|
}
|
2023-11-25 23:09:49 +01:00
|
|
|
eprintln!("finished pr validate");
|
|
|
|
}
|
2023-11-25 23:14:38 +01:00
|
|
|
("main", _args) => {
|
2023-11-25 23:09:49 +01:00
|
|
|
eprintln!("starting main validate");
|
2023-12-29 19:43:04 +01:00
|
|
|
for main_action in self.main_action.iter() {
|
|
|
|
main_action.lock().await.execute_main().await?;
|
|
|
|
}
|
2023-11-25 23:09:49 +01:00
|
|
|
eprintln!("finished main validate");
|
|
|
|
}
|
2023-11-25 23:14:38 +01:00
|
|
|
("release", _args) => {
|
2023-11-25 23:09:49 +01:00
|
|
|
eprintln!("starting release validate");
|
2023-12-29 19:43:04 +01:00
|
|
|
for release_action in self.release_action.iter() {
|
|
|
|
release_action.lock().await.execute_release().await?;
|
|
|
|
}
|
2023-11-25 23:09:49 +01:00
|
|
|
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(
|
2023-11-27 19:14:31 +01:00
|
|
|
Arc::new(Mutex::new(DefaultPullRequestAction {})),
|
|
|
|
Arc::new(Mutex::new(DefaultMainAction {})),
|
|
|
|
Arc::new(Mutex::new(DefaultReleaseAction {})),
|
2023-11-25 23:09:49 +01:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
pub trait PullRequestAction {
|
|
|
|
async fn execute_pull_request(&self) -> eyre::Result<()> {
|
|
|
|
eprintln!("validate pull request: noop");
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct DefaultPullRequestAction {}
|
|
|
|
#[async_trait]
|
|
|
|
impl PullRequestAction for DefaultPullRequestAction {}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
pub trait MainAction {
|
2023-12-29 19:43:04 +01:00
|
|
|
async fn execute_main(&self) -> eyre::Result<()>;
|
2023-11-25 23:09:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct DefaultMainAction {}
|
|
|
|
#[async_trait]
|
2023-12-29 19:43:04 +01:00
|
|
|
impl MainAction for DefaultMainAction {
|
|
|
|
async fn execute_main(&self) -> eyre::Result<()> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
2023-11-25 23:09:49 +01:00
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
pub trait ReleaseAction {
|
|
|
|
async fn execute_release(&self) -> eyre::Result<()> {
|
|
|
|
eprintln!("validate release: noop");
|
|
|
|
|
|
|
|
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(())
|
|
|
|
}
|
|
|
|
}
|