feat: support configurable way to retrieve recipes via github (#2400)

This commit is contained in:
Lifei Zhou
2025-05-06 09:54:35 +10:00
committed by GitHub
parent 3da7d2bfc8
commit 705a858cf2
8 changed files with 274 additions and 57 deletions
+17 -29
View File
@@ -1,8 +1,13 @@
use anyhow::{Context, Result};
use anyhow::Result;
use console::style;
use goose::recipe::Recipe;
use minijinja::UndefinedBehavior;
use std::{collections::HashMap, path::Path};
use serde_json::Value as JsonValue;
use serde_yaml::Value as YamlValue;
use std::collections::HashMap;
use crate::recipes::search_recipe::retrieve_recipe_file;
/// Loads and validates a recipe from a YAML or JSON file
///
@@ -23,46 +28,29 @@ use std::{collections::HashMap, path::Path};
/// - The file can't be read
/// - The YAML/JSON is invalid
/// - The required fields are missing
pub fn load_recipe<P: AsRef<Path>>(
path: P,
pub fn load_recipe(
recipe_name: &str,
log: bool,
params: Option<Vec<(String, String)>>,
) -> Result<Recipe> {
let path = path.as_ref();
let content = retrieve_recipe_file(recipe_name)?;
// Check if file exists
if !path.exists() {
return Err(anyhow::anyhow!("recipe file not found: {}", path.display()));
}
// Read file content
let content = std::fs::read_to_string(path)
.with_context(|| format!("Failed to read recipe file: {}", path.display()))?;
// Check if any parameters were provided
let rendered_content = match params {
None => content,
Some(params) => render_content_with_params(&content, &params)?,
};
// Determine file format based on extension and parse accordingly
let recipe: Recipe = if let Some(extension) = path.extension() {
match extension.to_str().unwrap_or("").to_lowercase().as_str() {
"json" => serde_json::from_str(&rendered_content)
.with_context(|| format!("Failed to parse JSON recipe file: {}", path.display()))?,
"yaml" => serde_yaml::from_str(&rendered_content)
.with_context(|| format!("Failed to parse YAML recipe file: {}", path.display()))?,
_ => {
return Err(anyhow::anyhow!(
"Unsupported file format for recipe file: {}. Expected .yaml or .json",
path.display()
))
}
}
let recipe: Recipe;
if serde_json::from_str::<JsonValue>(&rendered_content).is_ok() {
recipe = serde_json::from_str(&rendered_content)?
} else if serde_yaml::from_str::<YamlValue>(&rendered_content).is_ok() {
recipe = serde_yaml::from_str(&rendered_content)?
} else {
return Err(anyhow::anyhow!(
"File has no extension: {}. Expected .yaml or .json",
path.display()
"Unsupported file format for recipe file. Expected .yaml or .json"
));
};
}
if log {
// Display information about the loaded recipe