diff --git a/homestar-invocation/src/task/instruction/nonce.rs b/homestar-invocation/src/task/instruction/nonce.rs index a821a111..6022edf2 100644 --- a/homestar-invocation/src/task/instruction/nonce.rs +++ b/homestar-invocation/src/task/instruction/nonce.rs @@ -2,7 +2,7 @@ //! //! [Instruction]: super::Instruction -use crate::{Error, Unit}; +use crate::{ipld::schema, Error, Unit}; use const_format::formatcp; use enum_as_inner::EnumAsInner; use generic_array::{ @@ -16,6 +16,7 @@ use schemars::{ JsonSchema, }; use serde::{Deserialize, Serialize}; +use serde_json::json; use std::{borrow::Cow, fmt, module_path}; use uuid::Uuid; @@ -103,17 +104,29 @@ impl JsonSchema for Nonce { Cow::Borrowed(formatcp!("{}::Nonce", module_path!())) } - fn json_schema(_gen: &mut SchemaGenerator) -> Schema { - let schema = SchemaObject { - instance_type: Some(SingleOrVec::Single(InstanceType::String.into())), + fn json_schema(gen: &mut SchemaGenerator) -> Schema { + let mut schema = SchemaObject { + instance_type: None, metadata: Some(Box::new(Metadata { description: Some( - "A 12-byte or 16-byte nonce. Use empty string for no nonce.".to_string(), + "A 12-byte or 16-byte nonce encoded as IPLD bytes. Use empty string for no nonce.".to_string(), ), ..Default::default() })), ..Default::default() }; + + let empty_string = SchemaObject { + instance_type: Some(SingleOrVec::Single(InstanceType::String.into())), + const_value: Some(json!("")), + ..Default::default() + }; + + schema.subschemas().one_of = Some(vec![ + gen.subschema_for::(), + Schema::Object(empty_string), + ]); + schema.into() } } diff --git a/homestar-runtime/src/runner/file.rs b/homestar-runtime/src/runner/file.rs index 43361555..2a946b7e 100644 --- a/homestar-runtime/src/runner/file.rs +++ b/homestar-runtime/src/runner/file.rs @@ -116,4 +116,26 @@ mod test { workflow_file.validate_and_parse().await.unwrap(); assert_eq!(workflow, newly_validated_workflow); } + + #[tokio::test] + async fn validate_and_parse_workflow_with_nonce() { + let path = PathBuf::from("./fixtures/test_nonce.json"); + let config = Resources::default(); + let (instruction, _) = test_utils::wasm_instruction_with_nonce::(); + + let task = Task::new( + RunInstruction::Expanded(instruction.clone()), + config.clone().into(), + UcanPrf::default(), + ); + + let workflow = Workflow::new(vec![task]); + + workflow.to_file(path.display().to_string()).unwrap(); + let workflow_file = ReadWorkflow { file: path.clone() }; + + let (validated_workflow, _settings) = workflow_file.validate_and_parse().await.unwrap(); + + assert_eq!(workflow, validated_workflow); + } }