feat: startup git clone for template repo + pass config through
- ensure_repo_ready() at startup: clone if missing, fetch if exists - TemplateRepoConfig gains local_path field - list_all_templates/select_template/extract_repo_template accept repo config - Remove hardcoded repo_dir(), use config.local_path
This commit is contained in:
@@ -2,6 +2,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::TemplateRepoConfig;
|
||||
use crate::llm::{ChatMessage, LlmClient};
|
||||
use crate::tools::ExternalToolManager;
|
||||
|
||||
@@ -46,7 +47,7 @@ fn builtin_dir() -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
fn repo_dir() -> &'static str {
|
||||
fn default_repo_dir() -> &'static str {
|
||||
if Path::new("/app/oseng-templates").is_dir() {
|
||||
"/app/oseng-templates"
|
||||
} else {
|
||||
@@ -133,8 +134,45 @@ async fn scan_examples_git(repo: &Path, ref_name: &str, template_path: &str) ->
|
||||
examples
|
||||
}
|
||||
|
||||
/// Ensure the template repo is a git clone; clone or fetch as needed.
|
||||
/// Called at startup (before serve) so readiness probe can gate on it.
|
||||
pub async fn ensure_repo_ready(cfg: &TemplateRepoConfig) {
|
||||
let repo = Path::new(&cfg.local_path);
|
||||
if repo.join(".git").is_dir() {
|
||||
tracing::info!("Template repo already cloned at {}, fetching...", repo.display());
|
||||
let _ = tokio::process::Command::new("git")
|
||||
.args(["fetch", "--all", "--prune", "-q"])
|
||||
.current_dir(repo)
|
||||
.env("GIT_SSL_NO_VERIFY", "true")
|
||||
.output()
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
// Not a git repo — remove stale dir (e.g. COPY'd without .git) and clone
|
||||
let url = format!("{}/{}/{}.git", cfg.gitea_url, cfg.owner, cfg.repo);
|
||||
tracing::info!("Cloning template repo {} → {}", url, repo.display());
|
||||
let _ = tokio::fs::remove_dir_all(repo).await;
|
||||
let output = tokio::process::Command::new("git")
|
||||
.args(["clone", &url, &repo.to_string_lossy()])
|
||||
.env("GIT_SSL_NO_VERIFY", "true")
|
||||
.output()
|
||||
.await;
|
||||
match output {
|
||||
Ok(o) if o.status.success() => {
|
||||
tracing::info!("Template repo cloned successfully");
|
||||
}
|
||||
Ok(o) => {
|
||||
tracing::error!("git clone failed: {}", String::from_utf8_lossy(&o.stderr));
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("git clone error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// List all templates from both built-in and repo (all branches).
|
||||
pub async fn list_all_templates() -> Vec<TemplateListItem> {
|
||||
pub async fn list_all_templates(repo_cfg: Option<&TemplateRepoConfig>) -> Vec<TemplateListItem> {
|
||||
let mut items = Vec::new();
|
||||
|
||||
// 1. Built-in templates (flat: each top-level dir with template.json)
|
||||
@@ -164,8 +202,11 @@ pub async fn list_all_templates() -> Vec<TemplateListItem> {
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Repo templates (all branches, find INSTRUCTIONS.md via git ls-tree)
|
||||
let repo = Path::new(repo_dir());
|
||||
// 2. Repo templates (all branches, cloned at startup)
|
||||
let repo_path = repo_cfg
|
||||
.map(|c| c.local_path.as_str())
|
||||
.unwrap_or_else(|| default_repo_dir());
|
||||
let repo = Path::new(repo_path);
|
||||
if repo.join(".git").is_dir() {
|
||||
items.extend(scan_repo_all_branches(repo).await);
|
||||
}
|
||||
@@ -284,8 +325,11 @@ async fn read_git_file_json(
|
||||
|
||||
/// Extract a template from a git branch to a local directory.
|
||||
/// Uses `git archive` to extract the template subtree.
|
||||
pub async fn extract_repo_template(template_id: &str) -> anyhow::Result<PathBuf> {
|
||||
let repo = Path::new(repo_dir());
|
||||
pub async fn extract_repo_template(template_id: &str, repo_cfg: Option<&TemplateRepoConfig>) -> anyhow::Result<PathBuf> {
|
||||
let repo_path = repo_cfg
|
||||
.map(|c| c.local_path.as_str())
|
||||
.unwrap_or_else(|| default_repo_dir());
|
||||
let repo = Path::new(repo_path);
|
||||
let dest = PathBuf::from("/tmp/tori-repo-templates").join(template_id);
|
||||
let _ = tokio::fs::remove_dir_all(&dest).await;
|
||||
tokio::fs::create_dir_all(&dest).await?;
|
||||
@@ -402,8 +446,8 @@ pub fn is_repo_template(template_id: &str) -> bool {
|
||||
|
||||
// --- LLM template selection ---
|
||||
|
||||
pub async fn select_template(llm: &LlmClient, requirement: &str) -> Option<String> {
|
||||
let all = list_all_templates().await;
|
||||
pub async fn select_template(llm: &LlmClient, requirement: &str, repo_cfg: Option<&TemplateRepoConfig>) -> Option<String> {
|
||||
let all = list_all_templates(repo_cfg).await;
|
||||
if all.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user