summaryrefslogtreecommitdiff
path: root/makima/src/daemon/chain
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-05 00:48:38 +0000
committersoryu <soryu@soryu.co>2026-02-05 00:48:38 +0000
commit0302b4596e14210884df5d645df9a179d8f0c1c6 (patch)
tree46efe027dffa25a30e4eab87fd62de249c3075ad /makima/src/daemon/chain
parente16d49b52a393aa9a762edf57f93434a4bd7844e (diff)
downloadsoryu-0302b4596e14210884df5d645df9a179d8f0c1c6.tar.gz
soryu-0302b4596e14210884df5d645df9a179d8f0c1c6.zip
Add multi-repository support for chains
Chains can now have multiple repositories attached, with one marked as primary. Repositories are used by contracts created from chain definitions. Backend changes: - Add chain_repositories table migration - Add ChainRepository model with CRUD operations - Add API endpoints for listing, adding, deleting repositories - Add endpoint to set a repository as primary - Update Chain and ChainEditorData models to use repositories - Update chain parser to support repositories in YAML format - Remove deprecated repository_url/local_path from Chain Frontend changes: - Add ChainRepository interface and API functions - Add repository section to ChainEditor showing attached repos - Add modal for adding new repositories (remote or local) - Support setting primary repository and removing repositories Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'makima/src/daemon/chain')
-rw-r--r--makima/src/daemon/chain/parser.rs29
-rw-r--r--makima/src/daemon/chain/runner.rs24
2 files changed, 44 insertions, 9 deletions
diff --git a/makima/src/daemon/chain/parser.rs b/makima/src/daemon/chain/parser.rs
index 0f16710..3851d1f 100644
--- a/makima/src/daemon/chain/parser.rs
+++ b/makima/src/daemon/chain/parser.rs
@@ -20,6 +20,27 @@ pub enum ParseError {
ValidationError(String),
}
+/// Repository definition in a chain.
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct RepositoryDefinition {
+ /// Name of the repository
+ pub name: String,
+ /// Repository URL (for remote repos)
+ pub repository_url: Option<String>,
+ /// Local path (for local repos)
+ pub local_path: Option<String>,
+ /// Source type: remote, local, or managed
+ #[serde(default = "default_source_type")]
+ pub source_type: String,
+ /// Whether this is the primary repository
+ #[serde(default)]
+ pub is_primary: bool,
+}
+
+fn default_source_type() -> String {
+ "remote".to_string()
+}
+
/// Chain definition parsed from YAML.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChainDefinition {
@@ -27,11 +48,9 @@ pub struct ChainDefinition {
pub name: String,
/// Optional description
pub description: Option<String>,
- /// Repository URL (optional - contracts may have their own repos)
- #[serde(alias = "repo")]
- pub repository_url: Option<String>,
- /// Local path for repository
- pub local_path: Option<String>,
+ /// Repositories for this chain
+ #[serde(default)]
+ pub repositories: Vec<RepositoryDefinition>,
/// Contracts in this chain
pub contracts: Vec<ContractDefinition>,
/// Loop configuration
diff --git a/makima/src/daemon/chain/runner.rs b/makima/src/daemon/chain/runner.rs
index 9c6f6b4..dfbcfa7 100644
--- a/makima/src/daemon/chain/runner.rs
+++ b/makima/src/daemon/chain/runner.rs
@@ -14,8 +14,8 @@ use thiserror::Error;
use super::dag::{topological_sort, validate_dag, DagError};
use super::parser::{parse_chain_file, ChainDefinition, ParseError};
use crate::db::models::{
- CreateChainContractRequest, CreateChainDeliverableRequest, CreateChainRequest,
- CreateChainTaskRequest,
+ AddChainRepositoryRequest, CreateChainContractRequest, CreateChainDeliverableRequest,
+ CreateChainRequest, CreateChainTaskRequest,
};
/// Error type for chain runner operations.
@@ -100,11 +100,27 @@ impl ChainRunner {
None => (None, None, None),
};
+ // Convert repository definitions to API format
+ let repositories: Vec<AddChainRepositoryRequest> = chain
+ .repositories
+ .iter()
+ .map(|r| AddChainRepositoryRequest {
+ name: r.name.clone(),
+ repository_url: r.repository_url.clone(),
+ local_path: r.local_path.clone(),
+ source_type: r.source_type.clone(),
+ is_primary: r.is_primary,
+ })
+ .collect();
+
CreateChainRequest {
name: chain.name.clone(),
description: chain.description.clone(),
- repository_url: chain.repository_url.clone(),
- local_path: chain.local_path.clone(),
+ repositories: if repositories.is_empty() {
+ None
+ } else {
+ Some(repositories)
+ },
loop_enabled,
loop_max_iterations,
loop_progress_check,