Compare commits
2 Commits
9a39ea00d6
...
0b4821137d
Author | SHA1 | Date |
---|---|---|
R Tyler Croy | 0b4821137d | |
R Tyler Croy | 127d3b7aa4 |
|
@ -1652,11 +1652,22 @@ dependencies = [
|
|||
name = "otto-parser"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"log",
|
||||
"otto-models",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"serde_json",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "otto-parser-service"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"log",
|
||||
"otto-models",
|
||||
"otto-parser",
|
||||
"pretty_env_logger 0.4.0",
|
||||
"serde_json",
|
||||
"tide 0.15.0",
|
||||
|
|
|
@ -6,6 +6,7 @@ members = [
|
|||
|
||||
"crates/agent",
|
||||
"crates/models",
|
||||
"crates/parser",
|
||||
|
||||
"services/auctioneer",
|
||||
"services/eventbus",
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
target/
|
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "otto-parser"
|
||||
version = "0.1.0"
|
||||
authors = ["R. Tyler Croy <rtyler@brokenco.de>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "~0.4.11"
|
||||
otto-models = { path = "../models" }
|
||||
pest = "~2.1.3"
|
||||
pest_derive = "~2.1.0"
|
||||
serde_json = "~1.0.59"
|
||||
uuid = { version = "~0.8.1", features = ["v4", "serde"]}
|
|
@ -0,0 +1,6 @@
|
|||
= Otto Parser
|
||||
|
||||
The Otto Parser service is basically a parser engine that speaks HTTP. In the
|
||||
`src/` directory you will find the `.pest` grammar definition which outlines
|
||||
the Otto Pipeline syntax.
|
||||
|
|
@ -9,6 +9,9 @@ use pest::iterators::{Pair, Pairs};
|
|||
use pest::Parser;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub use pest::error::ErrorVariant;
|
||||
pub use pest::error::LineColLocation;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[grammar = "pipeline.pest"]
|
||||
struct PipelineParser;
|
||||
|
@ -44,6 +47,12 @@ pub fn parse_pipeline_string(buffer: &str) -> Result<Pipeline, PestError<Rule>>
|
|||
contexts: vec![ctx],
|
||||
});
|
||||
}
|
||||
Rule::parallel => {
|
||||
pipeline.batches.push(Batch {
|
||||
mode: BatchMode::Parallel,
|
||||
contexts: parse_parallel(&mut parsed.into_inner()),
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +64,21 @@ pub fn parse_pipeline_string(buffer: &str) -> Result<Pipeline, PestError<Rule>>
|
|||
Ok(pipeline)
|
||||
}
|
||||
|
||||
fn parse_str(parser: &mut pest::iterators::Pair<Rule>) -> String {
|
||||
fn parse_parallel(parser: &mut Pairs<Rule>) -> Vec<Context> {
|
||||
let mut contexts = vec![];
|
||||
while let Some(parsed) = parser.next() {
|
||||
match parsed.as_rule() {
|
||||
Rule::stage => {
|
||||
let ctx = parse_stage(&mut parsed.into_inner());
|
||||
contexts.push(ctx);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
contexts
|
||||
}
|
||||
|
||||
fn parse_str(parser: &mut Pair<Rule>) -> String {
|
||||
// TODO: There's got to be a better way than cloning
|
||||
let mut parser = parser.clone().into_inner();
|
||||
while let Some(parsed) = parser.next() {
|
||||
|
@ -391,4 +414,27 @@ mod tests {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_parallel() {
|
||||
let buf = r#"
|
||||
pipeline {
|
||||
parallel {
|
||||
stage {
|
||||
name = 'Test'
|
||||
steps { sh 'ls' }
|
||||
}
|
||||
stage {
|
||||
name = 'UAT'
|
||||
steps { sh 'pwd' }
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
let pipeline = parse_pipeline_string(&buf).expect("Failed to parse");
|
||||
assert!(!pipeline.uuid.is_nil());
|
||||
assert_eq!(pipeline.batches.len(), 1);
|
||||
|
||||
let batch = &pipeline.batches[0];
|
||||
assert_eq!(batch.contexts.len(), 2);
|
||||
}
|
||||
}
|
|
@ -1,18 +1,27 @@
|
|||
// The pipeline PEG
|
||||
// The pipeline PEG
|
||||
|
||||
pipeline = _{ SOI ~ "pipeline" ~
|
||||
BLOCK_BEGIN ~
|
||||
execBlocks ~
|
||||
BLOCK_END ~ EOI }
|
||||
|
||||
execBlocks = { (stage | steps)* }
|
||||
execBlocks = { (stage
|
||||
| steps
|
||||
| parallel)* }
|
||||
|
||||
stage = { "stage" ~
|
||||
BLOCK_BEGIN ~
|
||||
BLOCK_BEGIN ~
|
||||
(property*) ~
|
||||
steps ~
|
||||
BLOCK_END }
|
||||
|
||||
// The parallel block can contain multiple stages which run in parallel
|
||||
//
|
||||
// inside the parser this should result in multiple contexts in the same batch
|
||||
parallel = { "parallel" ~
|
||||
BLOCK_BEGIN ~
|
||||
(stage)* ~
|
||||
BLOCK_END }
|
||||
|
||||
steps = { "steps" ~ BLOCK_BEGIN ~ step+ ~ BLOCK_END }
|
||||
step = { IDENT ~ (
|
|
@ -1,13 +1,9 @@
|
|||
[package]
|
||||
name = "otto-parser"
|
||||
name = "otto-parser-service"
|
||||
version = "0.1.0"
|
||||
authors = ["R. Tyler Croy <rtyler@brokenco.de>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "otto_parser"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "otto-parser"
|
||||
path = "src/main.rs"
|
||||
|
@ -16,8 +12,7 @@ path = "src/main.rs"
|
|||
async-std = { version = "1.6.5", features = ["attributes"]}
|
||||
log = "~0.4.11"
|
||||
otto-models = { path = "../../crates/models" }
|
||||
pest = "~2.1.3"
|
||||
pest_derive = "~2.1.0"
|
||||
otto-parser = { path = "../../crates/parser" }
|
||||
pretty_env_logger = "~0.4.0"
|
||||
serde_json = "~1.0.59"
|
||||
tide = "~0.15.0"
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
= Parser service
|
||||
|
||||
The Otto Parser service is basically a parser engine that speaks HTTP. In the
|
||||
`src/` directory you will find the `.pest` grammar definition which outlines
|
||||
the Otto Pipeline syntax.
|
||||
The Otto Parser Service presents the parser crate as an HTTP service.
|
||||
|
||||
The `apispec.yml` is an link:https://en.wikipedia.org/wiki/Open_API[OpenAPI]
|
||||
specification that describes the public HTTP endpoints that the parser service
|
||||
|
|
|
@ -16,7 +16,6 @@ async fn parse(mut req: Request<()>) -> tide::Result {
|
|||
|
||||
match parsed {
|
||||
Err(e) => {
|
||||
use pest::error::*;
|
||||
error!("Failed to parse: {:?}", e);
|
||||
|
||||
let variant = match e.variant {
|
||||
|
|
Loading…
Reference in New Issue