feat: plans in workspace now works

This commit is contained in:
Kasper Juul Hermansen 2025-03-23 22:20:43 +01:00
parent 1fda414e05
commit e9e80abad0
Signed by: kjuulh
SSH Key Fingerprint: SHA256:RjXh0p7U6opxnfd3ga/Y9TCo18FYlHFdSpRIV72S/QM
7 changed files with 68 additions and 15 deletions

View File

@ -116,17 +116,27 @@ pub async fn execute() -> anyhow::Result<()> {
let mut member_contexts = Vec::new();
for (member_path, member) in workspace_members {
for (member_path, member) in &workspace_members {
match member {
WorkspaceProject::Plan(plan) => {
WorkspaceProject::Plan(_plan) => {
tracing::warn!("skipping reconcile for plans for now")
}
WorkspaceProject::Project(project) => {
let plan = if let Some(plan_file_path) = PlanReconciler::new()
.reconcile(&project, &project_path)
.reconcile(
project,
member_path,
Some(workspace_members.as_ref()),
Some(&project_path),
)
.await?
{
let plan_file = tokio::fs::read_to_string(&plan_file_path).await?;
let plan_file = tokio::fs::read_to_string(&plan_file_path)
.await
.context(format!(
"failed to read file at: {}",
project_path.to_string_lossy()
))?;
let plan_doc: KdlDocument = plan_file.parse()?;
let plan: Plan = plan_doc.try_into()?;
@ -137,7 +147,10 @@ pub async fn execute() -> anyhow::Result<()> {
None
};
let context = Context { project, plan };
let context = Context {
project: project.clone(),
plan,
};
member_contexts.push((member_path, context));
}
}
@ -177,12 +190,8 @@ pub async fn execute() -> anyhow::Result<()> {
.expect("to be able to get a subcommand (todo: might not work)");
for (member_path, context) in member_contexts {
run::Run::execute_command_if_exists(
all_cmd,
&member_path,
&context,
)
.await?;
run::Run::execute_command_if_exists(all_cmd, member_path, &context)
.await?;
}
}
_ => {
@ -252,7 +261,7 @@ pub async fn execute() -> anyhow::Result<()> {
tracing::trace!("found a project name: {}", project.name);
let plan = if let Some(plan_file_path) = PlanReconciler::new()
.reconcile(&project, &project_path)
.reconcile(&project, &project_path, None, None)
.await?
{
let plan_file = tokio::fs::read_to_string(&plan_file_path).await?;

View File

@ -1,6 +1,5 @@
use std::{collections::BTreeMap, fmt::Debug, path::PathBuf};
use colored_json::Paint;
use kdl::{KdlDocument, KdlNode, KdlValue};
use serde::Serialize;
@ -57,6 +56,7 @@ impl TryFrom<KdlDocument> for Plan {
pub enum ProjectPlan {
Local { path: PathBuf },
Git { url: String, path: Option<PathBuf> },
Workspace { name: String },
NoPlan,
}
@ -96,6 +96,17 @@ impl TryFrom<&KdlNode> for ProjectPlan {
});
}
if let Some(workspace) = children.get_arg("workspace") {
return Ok(Self::Workspace {
name: workspace
.as_string()
.map(|w| w.to_string())
.ok_or(anyhow::anyhow!(
"workspace requires a project name in the same project"
))?,
});
}
Ok(Self::NoPlan)
}
}

View File

@ -2,7 +2,7 @@ use std::path::{Path, PathBuf};
use anyhow::Context;
use crate::model::{ForestFile, Project};
use crate::model::{ForestFile, Project, Workspace, WorkspaceProject};
pub mod git;
pub mod local;
@ -21,6 +21,8 @@ impl PlanReconciler {
&self,
project: &Project,
destination: &Path,
workspace_members: Option<&Vec<(PathBuf, WorkspaceProject)>>,
workspace_root: Option<&Path>,
) -> anyhow::Result<Option<PathBuf>> {
tracing::info!("reconciling project");
if project.plan.is_none() {
@ -55,6 +57,21 @@ impl PlanReconciler {
crate::model::ProjectPlan::Git { url, path } => {
git::reconcile(url, path, &plan_dir).await?;
}
crate::model::ProjectPlan::Workspace { name } => {
let workspace_root = workspace_root.expect("to have workspace root available");
if let Some(workspace_members) = workspace_members {
for (member_path, member) in workspace_members {
if let WorkspaceProject::Plan(plan) = member {
if &plan.name == name {
tracing::debug!("found workspace project: {}", name);
local::reconcile(&workspace_root.join(member_path), &plan_dir)
.await?;
}
}
}
}
}
crate::model::ProjectPlan::NoPlan => {
tracing::debug!("no plan, returning");
return Ok(None);

View File

@ -29,7 +29,7 @@ impl ShellExecutor {
}
let mut cmd = tokio::process::Command::new(&script_path);
let cmd = cmd.current_dir(path);
let cmd = cmd.current_dir(&self.root.project_path);
cmd.stdin(Stdio::inherit());
cmd.stdout(Stdio::inherit());
cmd.stderr(Stdio::inherit());
@ -53,6 +53,7 @@ impl ShellExecutor {
fn get_path(&self) -> PathBuf {
match self.ty {
//ShellType::Plan => self.root.project_path.join(".forest").join("plan"),
ShellType::Plan => self.root.project_path.join(".forest").join("plan"),
ShellType::Project => self.root.project_path.clone(),
}

View File

@ -1,3 +1,7 @@
plan {
name a
scripts {
hello_plan type=shell {}
}
}

View File

@ -0,0 +1,7 @@
#!/usr/bin/env zsh
set -e
echo "hello from plan"
echo "i am here: $PWD"

View File

@ -1,6 +1,10 @@
project {
name a
plan {
workspace a
}
scripts {
hello type=shell {}
}