Skip to content

Commit 68080d7

Browse files
committed
generate schema for all manifests
1 parent 8cdc0ae commit 68080d7

File tree

7 files changed

+804
-47
lines changed

7 files changed

+804
-47
lines changed

.github/workflows/checks.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ jobs:
160160
- name: Check for uncommitted changes
161161
run: |
162162
if [[ -n "$(git status --porcelain)" ]]; then
163-
echo "❌ The icp.yaml schema is not up to date"
163+
echo "❌ The schema docs are not up to date"
164164
echo ""
165165
echo " Run ./scripts/generate-config-schema.sh to update them"
166166
echo ""

crates/schema-gen/src/main.rs

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,52 @@
1-
use icp::manifest::project::ProjectManifest;
2-
use schemars::schema_for;
3-
4-
const ID: &str = "https://dfinity.org/schemas/icp-yaml/v1.0.0";
5-
const TITLE: &str = "ICP Project Configuration";
6-
const DESCRIPTION: &str = "Schema for icp.yaml project configuration files used by the ICP CLI";
7-
8-
/// Generate JSON Schema for icp.yaml configuration files
9-
fn main() -> Result<(), Box<dyn std::error::Error>> {
10-
// Generate schema for the main ProjectManifest type
11-
let schema = schema_for!(ProjectManifest);
12-
13-
// Add metadata to the schema
14-
let mut schema_json = serde_json::to_value(schema)?;
15-
16-
// Add custom schema metadata
17-
if let Some(schema_obj) = schema_json.as_object_mut() {
18-
schema_obj.insert(
19-
"$id".to_string(), // k
20-
serde_json::Value::String(ID.to_string()), // v
21-
);
22-
23-
schema_obj.insert(
24-
"title".to_string(),
25-
serde_json::Value::String(TITLE.to_string()),
26-
);
27-
28-
schema_obj.insert(
29-
"description".to_string(),
30-
serde_json::Value::String(DESCRIPTION.to_string()),
31-
);
32-
}
33-
34-
// Pretty print the JSON schema to stdout
35-
println!("{}", serde_json::to_string_pretty(&schema_json)?);
36-
37-
Ok(())
1+
use icp::manifest::{
2+
CanisterManifest, EnvironmentManifest, NetworkManifest, project::ProjectManifest,
3+
};
4+
5+
macro_rules! generate_schemas {
6+
($base:expr, $($t:ty => $filename:expr),+ $(,)?) => {{
7+
let base : icp::prelude::PathBuf = $base.into();
8+
9+
$(
10+
{
11+
let schema = schemars::schema_for!($t);
12+
let mut schema_json = serde_json::to_value(&schema).unwrap();
13+
14+
if let Some(obj) = schema_json.as_object_mut() {
15+
obj.insert("$id".to_string(), serde_json::Value::String(stringify!($t).to_string()));
16+
obj.insert("title".to_string(), serde_json::Value::String(stringify!($t).to_string()));
17+
obj.insert(
18+
"description".to_string(),
19+
serde_json::Value::String(format!("Schema for {}", stringify!($t))),
20+
);
21+
}
22+
23+
// Build the full path: base + filename
24+
let path = base.join($filename);
25+
if let Some(parent) = path.parent() {
26+
std::fs::create_dir_all(parent).expect("failed to create parent directories");
27+
}
28+
29+
let pretty = serde_json::to_string_pretty(&schema_json).unwrap();
30+
std::fs::write(&path, pretty).expect("failed to write schema file");
31+
32+
println!("✅ Wrote {} to {}", stringify!($t), path.to_string());
33+
}
34+
)+
35+
}};
36+
}
37+
38+
fn main() {
39+
// Take the base directory as the first command-line argument
40+
let base = std::env::args().nth(1).unwrap_or_else(|| {
41+
eprintln!("Usage: cargo run -- <base-path>");
42+
std::process::exit(1);
43+
});
44+
45+
generate_schemas!(
46+
&base,
47+
ProjectManifest => "icp-yaml-schema.json",
48+
CanisterManifest => "canister-yaml-schema.json",
49+
NetworkManifest => "network-yaml-schema.json",
50+
EnvironmentManifest => "environment-yaml-schema.json",
51+
);
3852
}

0 commit comments

Comments
 (0)