Skip to content

Commit 94b3e6a

Browse files
committed
feat!: add support for multiple version of specification of cdevents
- link as git submodule several versions of cdevents specs - add version into module name of subject's content - generate a module per specs with alias to the versionned subejct's content module - generate a module `latest` with alias to the latest version of each subject's content module - ignore subject'content with modifier in their version - update tests to load every json schema and test it (selection based on `context.type` FIX #16 Signed-off-by: David Bernard <david.bernard.31@gmail.com>
1 parent c95687a commit 94b3e6a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+969
-614
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ clean:
6666
cargo clean
6767

6868
generate:
69-
cargo run -p generator -- --templates-dir "generator/templates" --jsonschema-dir "cdevents-specs/spec-v0.3/schemas" --dest "cdevents-sdk/src/generated"
69+
cargo run -p generator -- --templates-dir "generator/templates" --jsonschemas "cdevents-specs/*/schemas/*.json" --dest "cdevents-sdk/src/generated"
7070

7171
test:
7272
cargo nextest run --all-features

README.md

Lines changed: 1 addition & 1 deletion

cdevents-sdk/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ time = { version = "0.3", features = ["serde-human-readable"] }
2222
[dev-dependencies]
2323
assert-json-diff = "2.0"
2424
boon = "0.5"
25+
glob = "0.3"
2526
proptest = "1"
2627
rstest = "0.18"
2728

cdevents-sdk/examples/pipelinerun_finished.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::error::Error;
22

3-
use cdevents_sdk::{CDEvent, Subject, pipelinerun_finished};
3+
use cdevents_sdk::{CDEvent, Subject, latest::pipelinerun_finished};
44
use cloudevents::{Event, AttributesReader};
55

66
fn main() -> Result<(), Box<dyn Error>> {

cdevents-sdk/src/cloudevents.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ mod tests {
6767
#[test]
6868
fn test_into_cloudevent() -> Result<(), Box<dyn std::error::Error>> {
6969
let cdevent = CDEvent::from(
70-
Subject::from(build_queued::Content{})
70+
Subject::from(latest::build_queued::Content{})
7171
.with_id("subject123".try_into()?)
7272
.with_source("/event/source/123".try_into()?)
7373
)

cdevents-sdk/src/generated/artifact_signed.rs renamed to cdevents-sdk/src/generated/artifact_signed_0_1_0.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use serde::{Serialize, Deserialize};
99
#[serde(deny_unknown_fields)]
1010
pub struct Content {
1111
#[serde(rename = "signature",)]
12-
pub signature: String,
12+
pub signature: crate::NonEmptyString,
1313
}
1414

1515
#[cfg(test)]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// @generated
2+
// by cdevents/sdk-rust/generator (subject.hbs)
3+
4+
#[cfg(feature = "testkit")] use proptest_derive::Arbitrary;
5+
use serde::{Serialize, Deserialize};
6+
7+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
8+
#[cfg_attr(feature = "testkit", derive(Arbitrary))]
9+
#[serde(deny_unknown_fields)]
10+
pub struct Content {
11+
#[serde(rename = "description", default, skip_serializing_if = "Option::is_none",)]
12+
pub description: Option<crate::NonEmptyString>,
13+
#[serde(rename = "repository", default, skip_serializing_if = "Option::is_none",)]
14+
pub repository: Option<ContentRepository>,
15+
}
16+
17+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
18+
#[cfg_attr(feature = "testkit", derive(Arbitrary))]
19+
#[serde(deny_unknown_fields)]
20+
pub struct ContentRepository {
21+
#[serde(rename = "id",)]
22+
pub id: crate::Id,
23+
#[serde(rename = "source", default, skip_serializing_if = "Option::is_none",)]
24+
pub source: Option<crate::UriReference>,
25+
}
26+
27+
#[cfg(test)]
28+
mod tests {
29+
use proptest::prelude::*;
30+
use super::*;
31+
32+
proptest! {
33+
#[test]
34+
#[cfg(feature = "testkit")]
35+
fn arbitraries_are_json_valid(s in any::<Content>()) {
36+
let json_str = serde_json::to_string(&s).unwrap();
37+
let actual = serde_json::from_str::<Content>(&json_str).unwrap();
38+
assert_eq!(s, actual);
39+
}
40+
}
41+
}

cdevents-sdk/src/generated/mod.rs

Lines changed: 687 additions & 548 deletions
Large diffs are not rendered by default.

cdevents-sdk/src/generated/repository_created.rs renamed to cdevents-sdk/src/generated/repository_created_0_1_1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub struct Content {
1313
#[serde(rename = "owner", default, skip_serializing_if = "Option::is_none",)]
1414
pub owner: Option<String>,
1515
#[serde(rename = "url",)]
16-
pub url: String,
16+
pub url: crate::Uri,
1717
#[serde(rename = "viewUrl", default, skip_serializing_if = "Option::is_none",)]
1818
pub view_url: Option<String>,
1919
}

cdevents-sdk/tests/specs.rs

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,58 @@
11
use assert_json_diff::assert_json_eq;
22
use cdevents_sdk::CDEvent;
3-
use rstest::rstest;
4-
use std::fs;
3+
use rstest::*;
4+
use std::{collections::HashMap, fs};
55
use std::path::PathBuf;
66
use proptest::prelude::*;
7-
use boon::{Schemas, Compiler};
7+
use boon::{Schemas, Compiler, SchemaIndex};
8+
use glob::glob;
9+
use std::sync::OnceLock;
10+
11+
struct EventsSchemas {
12+
schemas: Schemas,
13+
mapping: HashMap<String, SchemaIndex>,
14+
}
15+
16+
impl EventsSchemas {
17+
fn load() -> Self {
18+
let mut schemas = Schemas::new();
19+
let mut compiler = Compiler::new();
20+
let mut mapping = HashMap::new();
21+
for entry in glob("../cdevents-specs/*/schemas/*.json").expect("Failed to read glob pattern") {
22+
let schemapath = entry.unwrap();
23+
//TODO avoid to read the schema twice (as json, then as jsonschema)
24+
let jsonschema: serde_json::Value = serde_json::from_str(&std::fs::read_to_string(&schemapath).unwrap()).unwrap();
25+
let ty = jsonschema["properties"]["context"]["properties"]["type"]["default"].as_str()
26+
.unwrap_or_default()
27+
.to_string();
28+
if !mapping.contains_key(&ty) {
29+
let sch_index = compiler.compile(&schemapath.to_string_lossy(), &mut schemas);
30+
if let Err(err) = sch_index {
31+
panic!("{err:#}"); //like a assert(false,...)
32+
}
33+
let sch_index = sch_index.unwrap();
34+
mapping.insert(ty, sch_index);
35+
}
36+
}
37+
Self {
38+
schemas, mapping
39+
}
40+
}
41+
42+
fn check_against_schema(&self, json: &serde_json::Value, ty: &str) {
43+
let sch_index = self.mapping.get(ty).expect(&format!("to have schema for {ty}"));
44+
let result = self.schemas.validate(json, sch_index.clone());
45+
if let Err(err) = result {
46+
panic!("{err}");
47+
}
48+
}
49+
}
50+
51+
static EVENTS_SCHEMA_CELL: OnceLock<EventsSchemas> = OnceLock::new();
52+
53+
fn events_schemas() -> &'static EventsSchemas {
54+
EVENTS_SCHEMA_CELL.get_or_init(|| EventsSchemas::load())
55+
}
856

957
#[rstest]
1058
fn for_each_example(#[files("../cdevents-specs/spec-v0.3/examples/*.json")] path: PathBuf) {
@@ -30,37 +78,22 @@ fn for_each_example(#[files("../cdevents-specs/spec-v0.3/examples/*.json")] path
3078
assert_json_eq!(example_json, cdevent_json);
3179
}
3280

33-
fn check_against_schema(json: &serde_json::Value, ty: &str) {
34-
let (subject, predicate) = cdevents_sdk::extract_subject_predicate(ty).expect("valid type: {ty}");
35-
let schemapath = format!("../cdevents-specs/spec-v0.3/schemas/{subject}{predicate}.json").to_lowercase();
36-
//TODO optimize to not recompile a previously read schema
37-
let mut schemas = Schemas::new();
38-
let mut compiler = Compiler::new();
39-
let sch_index = compiler.compile(&schemapath, &mut schemas);
40-
if let Err(err) = sch_index {
41-
panic!("{err:#}"); //like a assert(false,...)
42-
}
43-
let sch_index = sch_index.unwrap();
44-
let result = schemas.validate(json, sch_index);
45-
if let Err(err) = result {
46-
panic!("{err}");
47-
}
48-
}
49-
5081
#[rstest]
5182
fn validate_example_against_schema(#[files("../cdevents-specs/spec-v0.3/examples/*.json")] path: PathBuf) {
83+
let events_schemas = events_schemas();
5284
let example_txt = fs::read_to_string(path).expect("to read file as string");
5385
let example_json: serde_json::Value =
5486
serde_json::from_str(&example_txt).expect("to parse as json");
5587
let ty = example_json["context"]["type"].as_str().expect("valid context.type in json");
56-
check_against_schema(&example_json, ty);
88+
events_schemas.check_against_schema(&example_json, ty);
5789
}
5890

5991
proptest! {
6092
#[test]
6193
#[cfg(feature = "testkit")]
6294
fn arbitraries_check_jsonschema(s in any::<CDEvent>()) {
95+
let events_schemas = events_schemas();
6396
let json = serde_json::to_value(&s).unwrap();
64-
check_against_schema(&json, s.ty());
97+
events_schemas.check_against_schema(&json, s.ty());
6598
}
6699
}

generator/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ description = "generate cdevents type from json schema on cdevents-spec"
1313
anyhow = "1.0"
1414
clap = { version = "4", features = ["derive"] }
1515
cruet = "0.14"
16+
glob = "0.3"
1617
handlebars = { version = "5", features = ["dir_source"] }
1718
handlebars_misc_helpers = { version = "0.15", default-features = false, features = [
1819
"string",
1920
"json",
2021
] }
22+
indexmap = "2.2"
2123
serde = { version = "1.0", features = ["derive"] }
2224
serde_json = "1.0"
2325
url = "2.5"

0 commit comments

Comments
 (0)