Sync
This commit is contained in:
parent
b624dc3b34
commit
39399f93db
|
@ -60,7 +60,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arkham"
|
name = "arkham"
|
||||||
version = "0.1.1"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"console",
|
"console",
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::collections::HashMap;
|
||||||
#[derive(Serialize, Deserialize, Default)]
|
#[derive(Serialize, Deserialize, Default)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Project {
|
pub struct Project {
|
||||||
pub components: Vec<Component>,
|
pub components: HashMap<String, Component>,
|
||||||
pub groups: Vec<Group>,
|
pub groups: Vec<Group>,
|
||||||
pub env: HashMap<String, String>,
|
pub env: HashMap<String, String>,
|
||||||
pub tasks: Vec<TaskDefinition>,
|
pub tasks: Vec<TaskDefinition>,
|
||||||
|
@ -30,13 +30,13 @@ impl Project {
|
||||||
Jobs::new(jobs)
|
Jobs::new(jobs)
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.components.iter().find_map(|component| {
|
self.components.iter().find_map(|(c_name, component)| {
|
||||||
component
|
component
|
||||||
.tasks
|
.tasks
|
||||||
.iter()
|
.iter()
|
||||||
.find(|t| format!("{}:{}", component.name, t.name) == name)
|
.find(|t| format!("{}:{}", c_name, t.name) == name)
|
||||||
.map(|task| {
|
.map(|task| {
|
||||||
let job = self.build_component_task_job(component, task);
|
let job = self.build_component_task_job(c_name, component, task);
|
||||||
let mut jobs = task
|
let mut jobs = task
|
||||||
.before
|
.before
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -53,13 +53,13 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_relative_task(&self, task_name: &str, component_name: &str) -> Option<Jobs> {
|
fn get_relative_task(&self, task_name: &str, component_name: &str) -> Option<Jobs> {
|
||||||
if let Some(component) = self.components.iter().find(|c| c.name == component_name) {
|
if let Some(component) = self.components.get(component_name) {
|
||||||
component
|
component
|
||||||
.tasks
|
.tasks
|
||||||
.iter()
|
.iter()
|
||||||
.find(|t| t.name == task_name)
|
.find(|t| t.name == task_name)
|
||||||
.map(|task| {
|
.map(|task| {
|
||||||
let job = self.build_component_task_job(component, task);
|
let job = self.build_component_task_job(component_name, component, task);
|
||||||
let mut jobs = task
|
let mut jobs = task
|
||||||
.before
|
.before
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -76,9 +76,9 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_component(&self, name: &str) -> Option<Jobs> {
|
fn get_component(&self, component_name: &str) -> Option<Jobs> {
|
||||||
self.components.iter().find(|c| c.name == name).map(|c| {
|
self.components.get(component_name).map(|c| {
|
||||||
let component_job = self.build_component_job(c);
|
let component_job = self.build_component_job(component_name, c);
|
||||||
let mut absolute_tasks = c
|
let mut absolute_tasks = c
|
||||||
.before
|
.before
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -90,7 +90,7 @@ impl Project {
|
||||||
let mut relative_tasks = c
|
let mut relative_tasks = c
|
||||||
.before
|
.before
|
||||||
.iter()
|
.iter()
|
||||||
.map(|name| self.get_relative_task(name, &c.name))
|
.map(|task_name| self.get_relative_task(task_name, &component_name))
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|jobs| jobs.to_vec())
|
.map(|jobs| jobs.to_vec())
|
||||||
.flatten()
|
.flatten()
|
||||||
|
@ -102,11 +102,22 @@ impl Project {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_component_job(&self, c: &Component) -> Job {
|
fn get_group(&self, name: &str) -> Option<Vec<Jobs>> {
|
||||||
|
self.groups.iter().find(|g| g.name == name).map(|group| {
|
||||||
|
group
|
||||||
|
.components
|
||||||
|
.iter()
|
||||||
|
.map(|name| self.get_by_name(&name))
|
||||||
|
.flatten()
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_component_job(&self, name: &str, c: &Component) -> Job {
|
||||||
let mut env = self.env.clone();
|
let mut env = self.env.clone();
|
||||||
env.extend(c.env.clone());
|
env.extend(c.env.clone());
|
||||||
Job {
|
Job {
|
||||||
name: c.name.clone(),
|
name: name.to_string(),
|
||||||
env,
|
env,
|
||||||
..Job::default()
|
..Job::default()
|
||||||
}
|
}
|
||||||
|
@ -121,12 +132,17 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_component_task_job(&self, component: &Component, task: &TaskDefinition) -> Job {
|
fn build_component_task_job(
|
||||||
|
&self,
|
||||||
|
cmp_name: &str,
|
||||||
|
component: &Component,
|
||||||
|
task: &TaskDefinition,
|
||||||
|
) -> Job {
|
||||||
let mut env = self.env.clone();
|
let mut env = self.env.clone();
|
||||||
env.extend(component.env.clone());
|
env.extend(component.env.clone());
|
||||||
env.extend(task.env.clone());
|
env.extend(task.env.clone());
|
||||||
Job {
|
Job {
|
||||||
name: format!("{}:{}", component.name.clone(), task.name.clone()),
|
name: format!("{}:{}", cmp_name.to_string(), task.name.clone()),
|
||||||
env,
|
env,
|
||||||
..Job::default()
|
..Job::default()
|
||||||
}
|
}
|
||||||
|
@ -135,6 +151,15 @@ impl Project {
|
||||||
pub fn get_by_name(&self, name: &str) -> Option<Jobs> {
|
pub fn get_by_name(&self, name: &str) -> Option<Jobs> {
|
||||||
self.get_component(name)
|
self.get_component(name)
|
||||||
.or_else(|| self.get_absolute_task(name))
|
.or_else(|| self.get_absolute_task(name))
|
||||||
|
.or_else(|| {
|
||||||
|
self.get_group(name).map(|v| {
|
||||||
|
v.iter()
|
||||||
|
.map(|jobs| jobs.to_vec())
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into()
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_str(s: &str) -> Self {
|
pub fn from_str(s: &str) -> Self {
|
||||||
|
@ -146,15 +171,13 @@ impl Project {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Group {
|
pub struct Group {
|
||||||
name: String,
|
name: String,
|
||||||
components: Vec<Component>,
|
components: Vec<String>,
|
||||||
env: HashMap<String, String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Component {
|
pub struct Component {
|
||||||
pub env: HashMap<String, String>,
|
pub env: HashMap<String, String>,
|
||||||
pub name: String,
|
|
||||||
pub command: String,
|
pub command: String,
|
||||||
pub path: Option<String>,
|
pub path: Option<String>,
|
||||||
pub retry: bool,
|
pub retry: bool,
|
||||||
|
@ -168,7 +191,6 @@ impl Default for Component {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
env: HashMap::new(),
|
env: HashMap::new(),
|
||||||
name: "UNNAMED".to_string(),
|
|
||||||
command: String::new(),
|
command: String::new(),
|
||||||
path: None,
|
path: None,
|
||||||
retry: false,
|
retry: false,
|
||||||
|
@ -202,7 +224,7 @@ mod tests {
|
||||||
let project = Project::from_str(
|
let project = Project::from_str(
|
||||||
r#"
|
r#"
|
||||||
components:
|
components:
|
||||||
- name: test-component
|
test-component: {}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -228,9 +250,9 @@ mod tests {
|
||||||
let project = Project::from_str(
|
let project = Project::from_str(
|
||||||
r#"
|
r#"
|
||||||
components:
|
components:
|
||||||
- name: c1
|
c1:
|
||||||
tasks:
|
tasks:
|
||||||
- name: task1
|
- name: task1
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -243,11 +265,11 @@ mod tests {
|
||||||
let project = Project::from_str(
|
let project = Project::from_str(
|
||||||
r#"
|
r#"
|
||||||
components:
|
components:
|
||||||
- name: main-cmp
|
main-cmp:
|
||||||
before:
|
before:
|
||||||
- main-cmp:sub-task
|
- main-cmp:sub-task
|
||||||
tasks:
|
tasks:
|
||||||
- name: sub-task
|
- name: sub-task
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -257,15 +279,15 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn component_dependent_relative_component_task() {
|
fn component_dependent_relative() {
|
||||||
let project = Project::from_str(
|
let project = Project::from_str(
|
||||||
r#"
|
r#"
|
||||||
components:
|
components:
|
||||||
- name: main-cmp
|
main-cmp:
|
||||||
before:
|
before:
|
||||||
- sub-task
|
- sub-task
|
||||||
tasks:
|
tasks:
|
||||||
- name: sub-task
|
- name: sub-task
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -279,19 +301,19 @@ mod tests {
|
||||||
let project = Project::from_str(
|
let project = Project::from_str(
|
||||||
r#"
|
r#"
|
||||||
components:
|
components:
|
||||||
- name: ui
|
ui:
|
||||||
before:
|
|
||||||
- build-ui
|
|
||||||
tasks:
|
|
||||||
- name: build-ui
|
|
||||||
- name: server
|
|
||||||
before:
|
|
||||||
- setup
|
|
||||||
tasks:
|
|
||||||
- name: setup
|
|
||||||
- name: build
|
|
||||||
before:
|
before:
|
||||||
- server:setup
|
- build-ui
|
||||||
|
tasks:
|
||||||
|
- name: build-ui
|
||||||
|
server:
|
||||||
|
before:
|
||||||
|
- setup
|
||||||
|
tasks:
|
||||||
|
- name: setup
|
||||||
|
- name: build
|
||||||
|
before:
|
||||||
|
- server:setup
|
||||||
tasks:
|
tasks:
|
||||||
- name: build
|
- name: build
|
||||||
before:
|
before:
|
||||||
|
@ -316,9 +338,9 @@ mod tests {
|
||||||
foo: one
|
foo: one
|
||||||
sub: two
|
sub: two
|
||||||
components:
|
components:
|
||||||
- name: main-cmp
|
main-cmp:
|
||||||
env:
|
env:
|
||||||
sub: three
|
sub: three
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -337,13 +359,13 @@ mod tests {
|
||||||
foo: one
|
foo: one
|
||||||
sub: two
|
sub: two
|
||||||
components:
|
components:
|
||||||
- name: main-cmp
|
main-cmp:
|
||||||
env:
|
env:
|
||||||
sub: three
|
sub: three
|
||||||
tasks:
|
tasks:
|
||||||
- name: t
|
- name: t
|
||||||
env:
|
env:
|
||||||
foo: four
|
foo: four
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -353,4 +375,43 @@ mod tests {
|
||||||
assert_eq!(job.env.get("sub"), Some(&String::from("three")));
|
assert_eq!(job.env.get("sub"), Some(&String::from("three")));
|
||||||
assert_eq!(job.env.get("root"), Some(&String::from("ten")));
|
assert_eq!(job.env.get("root"), Some(&String::from("ten")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn group() {
|
||||||
|
let project = Project::from_str(
|
||||||
|
r#"
|
||||||
|
groups:
|
||||||
|
- name: all
|
||||||
|
components:
|
||||||
|
- ui
|
||||||
|
- server
|
||||||
|
components:
|
||||||
|
ui:
|
||||||
|
before:
|
||||||
|
- build-ui
|
||||||
|
tasks:
|
||||||
|
- name: build-ui
|
||||||
|
server:
|
||||||
|
before:
|
||||||
|
- setup
|
||||||
|
tasks:
|
||||||
|
- name: setup
|
||||||
|
- name: build
|
||||||
|
before:
|
||||||
|
- server:setup
|
||||||
|
tasks:
|
||||||
|
- name: build
|
||||||
|
before:
|
||||||
|
- ui:build-ui
|
||||||
|
- server:build
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
let jobs = project.get_by_name("all").unwrap();
|
||||||
|
println!("{:?}", jobs);
|
||||||
|
assert_eq!(jobs.get(0).unwrap().name, "ui:build-ui");
|
||||||
|
assert_eq!(jobs.get(1).unwrap().name, "ui");
|
||||||
|
assert_eq!(jobs.get(2).unwrap().name, "server:setup");
|
||||||
|
assert_eq!(jobs.get(3).unwrap().name, "server");
|
||||||
|
assert_eq!(jobs.len(), 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,12 @@ impl DerefMut for Jobs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Vec<Job>> for Jobs {
|
||||||
|
fn from(fr: Vec<Job>) -> Self {
|
||||||
|
Jobs::new(fr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Message)]
|
#[derive(Clone, Debug, Message)]
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
pub struct Job {
|
pub struct Job {
|
||||||
|
|
28
src/main.rs
28
src/main.rs
|
@ -1,6 +1,9 @@
|
||||||
use crate::definition::Project;
|
use crate::definition::Project;
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
|
use arkham::{App, Command};
|
||||||
use runner::Manager;
|
use runner::Manager;
|
||||||
|
use std::env;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
mod definition;
|
mod definition;
|
||||||
mod job;
|
mod job;
|
||||||
|
@ -23,7 +26,32 @@ async fn main() {
|
||||||
let manager = Manager::new().start();
|
let manager = Manager::new().start();
|
||||||
manager.do_send(jobs);
|
manager.do_send(jobs);
|
||||||
|
|
||||||
|
find_config("conductor.yml");
|
||||||
|
|
||||||
actix_rt::signal::ctrl_c()
|
actix_rt::signal::ctrl_c()
|
||||||
.await
|
.await
|
||||||
.expect("failed to listen for event");
|
.expect("failed to listen for event");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_config(config: &str) -> Option<PathBuf> {
|
||||||
|
env::current_dir()
|
||||||
|
.map(|dir| find_file(&dir, config))
|
||||||
|
.unwrap_or(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_file(starting_directory: &Path, filename: &str) -> Option<PathBuf> {
|
||||||
|
let mut path: PathBuf = starting_directory.into();
|
||||||
|
let file = Path::new(&filename);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
path.push(file);
|
||||||
|
|
||||||
|
if path.is_file() {
|
||||||
|
break Some(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(path.pop() && path.pop()) {
|
||||||
|
break None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue