feat: enable actual actions

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
2024-10-26 12:55:37 +02:00
parent 2d7a053ab0
commit 7804eaa667
7 changed files with 160 additions and 27 deletions

View File

@@ -1,6 +1,10 @@
use std::{
collections::BTreeMap,
future::{self, Future},
ops::Deref,
path::{Path, PathBuf},
pin::Pin,
sync::Arc,
};
use rust_builder::RustActionsBuilder;
@@ -16,6 +20,10 @@ pub mod rust_builder {
path::{Path, PathBuf},
};
use serde::Deserialize;
use crate::actions::CuddleActionsSchema;
use super::ExecutableActions;
pub struct RustActionsBuilder {
@@ -138,7 +146,7 @@ pub mod rust_builder {
.output()
.await?;
let actions: ExecutableActions = match serde_json::from_slice(&output.stdout) {
let actions: CuddleActionsSchema = match serde_json::from_slice(&output.stdout) {
Ok(output) => output,
Err(e) => {
let schema_output = std::str::from_utf8(&output.stdout)?;
@@ -151,7 +159,7 @@ pub mod rust_builder {
}
};
Ok(actions)
Ok(actions.to_executable(action_path)?)
}
}
}
@@ -180,7 +188,7 @@ impl Actions {
Ok(Some(Self { variants }))
}
pub async fn build(&mut self) -> anyhow::Result<Vec<ExecutableActions>> {
pub async fn build(&mut self) -> anyhow::Result<ExecutableActions> {
let mut executable_actions = Vec::default();
for variant in &mut self.variants {
@@ -194,25 +202,49 @@ impl Actions {
}
}
Ok(executable_actions)
let mut exec_actions = ExecutableActions::default();
for mut actions in executable_actions {
exec_actions.actions.append(&mut actions.actions);
}
Ok(exec_actions)
}
}
#[derive(Debug, Deserialize)]
struct CuddleActionsSchema {
actions: Vec<CuddleActionSchema>,
}
#[derive(Debug, Deserialize)]
struct CuddleActionSchema {
name: String,
}
pub enum ActionVariant {
Rust { root_path: PathBuf },
Docker,
}
#[derive(Default, Serialize, Deserialize)]
#[derive(Default)]
pub struct ExecutableActions {
actions: Vec<ExecutableAction>,
pub actions: Vec<ExecutableAction>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ExecutableAction {
name: String,
description: String,
flags: BTreeMap<String, ExecutableActionFlag>,
pub name: String,
pub description: String,
pub flags: BTreeMap<String, ExecutableActionFlag>,
call_fn: LazyResolve,
}
impl ExecutableAction {
pub async fn call(&self) -> anyhow::Result<()> {
// Bad hack until .call becomes stable
(self.call_fn.0)().await?;
Ok(())
}
}
#[derive(Debug, Serialize, Deserialize)]
@@ -220,3 +252,67 @@ pub enum ExecutableActionFlag {
String,
Bool,
}
impl CuddleActionsSchema {
fn to_executable(self, action_path: &Path) -> anyhow::Result<ExecutableActions> {
Ok(ExecutableActions {
actions: self
.actions
.into_iter()
.map(|a| {
let name = a.name.clone();
let action_path = action_path.to_string_lossy().to_string();
ExecutableAction {
name: a.name,
description: String::new(),
flags: BTreeMap::default(),
call_fn: LazyResolve::new(Box::new(move || {
let name = name.clone();
let action_path = action_path.clone();
Box::pin(async move {
tracing::debug!("calling: {}", name);
let mut cmd = tokio::process::Command::new(action_path);
cmd.args(["do", &name]);
let output = cmd.output().await?;
let stdout = std::str::from_utf8(&output.stdout)?;
for line in stdout.lines() {
println!("{}: {}", &name, line);
}
tracing::debug!("finished call for output: {}", &name);
Ok(())
})
})),
}
})
.collect(),
})
}
}
struct LazyResolve(
Arc<dyn Fn() -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send>> + Send + Sync>,
);
impl LazyResolve {
pub fn new(
func: Box<
dyn Fn() -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send>> + Send + Sync,
>,
) -> Self {
Self(Arc::new(func))
}
}
impl Deref for LazyResolve {
type Target =
Arc<dyn Fn() -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send>> + Send + Sync>;
fn deref(&self) -> &Self::Target {
&self.0
}
}