Skip to content

Commit

Permalink
new: Generate JSON schemas. (#1541)
Browse files Browse the repository at this point in the history
* Move to new crate.

* Wrap in feature.

* Update actions.

* Rename function.

* Update report.

* Add command.
  • Loading branch information
milesj committed Jul 9, 2024
1 parent ea8e39d commit e7c55ea
Show file tree
Hide file tree
Showing 25 changed files with 501 additions and 333 deletions.
23 changes: 15 additions & 8 deletions .yarn/versions/42cf3f6e.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
releases:
"@moonrepo/cli": minor
"@moonrepo/core-linux-arm64-gnu": minor
"@moonrepo/core-linux-arm64-musl": minor
"@moonrepo/core-linux-x64-gnu": minor
"@moonrepo/core-linux-x64-musl": minor
"@moonrepo/core-macos-arm64": minor
"@moonrepo/core-macos-x64": minor
"@moonrepo/core-windows-x64-msvc": minor
'@moonrepo/cli': minor
'@moonrepo/core-linux-arm64-gnu': minor
'@moonrepo/core-linux-arm64-musl': minor
'@moonrepo/core-linux-x64-gnu': minor
'@moonrepo/core-linux-x64-musl': minor
'@moonrepo/core-macos-arm64': minor
'@moonrepo/core-macos-x64': minor
'@moonrepo/core-windows-x64-msvc': minor
'@moonrepo/report': patch
'@moonrepo/types': minor

declined:
- '@moonrepo/nx-compat'
- '@moonrepo/runtime'
- website
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/actions/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ moon_cache_item = { path = "../cache-item" }
moon_codeowners = { path = "../codeowners" }
moon_common = { path = "../common" }
moon_config = { path = "../config" }
moon_config_schema = { path = "../config-schema" }
moon_hash = { path = "../hash" }
moon_project = { path = "../project" }
moon_project_graph = { path = "../project-graph" }
moon_task_runner = { path = "../task-runner" }
Expand Down
17 changes: 16 additions & 1 deletion crates/actions/src/actions/sync_workspace.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::operations::{sync_codeowners, sync_vcs_hooks};
use crate::operations::{sync_codeowners, sync_config_schemas, sync_vcs_hooks};
use crate::utils::should_skip_action;
use miette::IntoDiagnostic;
use moon_action::{Action, ActionStatus, Operation};
Expand Down Expand Up @@ -37,6 +37,21 @@ pub async fn sync_workspace(
// Run operations in parallel
let mut futures = vec![];

{
debug!("Syncing config schemas");

let app_context = Arc::clone(&app_context);

futures.push(task::spawn(async move {
Operation::sync_operation("Config schemas")
.track_async_with_check(
|| sync_config_schemas(&app_context, false),
|result| result,
)
.await
}));
}

if app_context.workspace_config.codeowners.sync_on_run {
debug!(
"Syncing code owners ({} enabled)",
Expand Down
2 changes: 2 additions & 0 deletions crates/actions/src/operations/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod sync_codeowners;
mod sync_config_schemas;
mod sync_vcs_hooks;

pub use sync_codeowners::*;
pub use sync_config_schemas::*;
pub use sync_vcs_hooks::*;
41 changes: 41 additions & 0 deletions crates/actions/src/operations/sync_config_schemas.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use moon_app_context::AppContext;
use moon_common::color;
use moon_config::Version;
use moon_config_schema::json_schemas::generate_json_schemas;
use moon_hash::hash_content;
use tracing::{instrument, warn};

hash_content!(
pub struct ConfigSchemaHash<'cfg> {
moon_version: &'cfg Version,
}
);

#[instrument(skip_all)]
pub async fn sync_config_schemas(app_context: &AppContext, force: bool) -> miette::Result<bool> {
let out_dir = app_context.cache_engine.cache_dir.join("schemas");

if let Err(error) = if force {
generate_json_schemas(out_dir).map(|_| true)
} else {
app_context
.cache_engine
.execute_if_changed(
"configSchemas.json",
ConfigSchemaHash {
moon_version: &app_context.cli_version,
},
|| async { generate_json_schemas(out_dir) },
)
.await
} {
warn!(
"Failed to generate schemas for configuration: {}",
color::muted_light(error.to_string())
);

return Ok(false);
}

Ok(true)
}
4 changes: 3 additions & 1 deletion crates/app-context/src/app_context.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use moon_cache::CacheEngine;
use moon_config::{ToolchainConfig, WorkspaceConfig};
use moon_config::{ToolchainConfig, Version, WorkspaceConfig};
use moon_console::Console;
use moon_vcs::BoxedVcs;
use std::path::PathBuf;
use std::sync::Arc;

#[derive(Clone)]
pub struct AppContext {
pub cli_version: Version,

// Components
pub cache_engine: Arc<CacheEngine>,
pub console: Arc<Console>,
Expand Down
7 changes: 7 additions & 0 deletions crates/app/src/commands/sync.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::syncs::codeowners::SyncCodeownersArgs;
use super::syncs::config_schemas::SyncConfigSchemasArgs;
use super::syncs::hooks::SyncHooksArgs;
use crate::session::CliSession;
use clap::Subcommand;
Expand All @@ -14,6 +15,12 @@ pub enum SyncCommands {
)]
Codeowners(SyncCodeownersArgs),

#[command(
name = "config-schemas",
about = "Generate and sync configuration JSON schemas for use within editors."
)]
ConfigSchemas(SyncConfigSchemasArgs),

#[command(
name = "hooks",
about = "Generate and sync hook scripts for the workspace configured VCS."
Expand Down
25 changes: 25 additions & 0 deletions crates/app/src/commands/syncs/config_schemas.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::helpers::create_progress_bar;
use crate::session::CliSession;
use clap::Args;
use moon_actions::operations::sync_config_schemas;
use starbase::AppResult;
use tracing::instrument;

#[derive(Args, Clone, Debug)]
pub struct SyncConfigSchemasArgs {
#[arg(long, help = "Bypass cache and force create schemas")]
force: bool,
}

#[instrument(skip_all)]
pub async fn sync(session: CliSession, args: SyncConfigSchemasArgs) -> AppResult {
let done = create_progress_bar("Generating configuration schemas...");

let context = session.get_app_context()?;

sync_config_schemas(&context, args.force).await?;

done("Successfully generated schemas", true);

Ok(())
}
1 change: 1 addition & 0 deletions crates/app/src/commands/syncs/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod codeowners;
pub mod config_schemas;
pub mod hooks;
pub mod projects;
1 change: 1 addition & 0 deletions crates/app/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ impl CliSession {

pub fn get_app_context(&self) -> AppResult<Arc<AppContext>> {
Ok(Arc::new(AppContext {
cli_version: self.cli_version.clone(),
cache_engine: self.get_cache_engine()?,
console: Arc::new(self.console.clone()),
vcs: self.get_vcs_adapter()?,
Expand Down
3 changes: 3 additions & 0 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ async fn main() -> MainResult {
Some(SyncCommands::Codeowners(args)) => {
commands::syncs::codeowners::sync(session, args).await
}
Some(SyncCommands::ConfigSchemas(args)) => {
commands::syncs::config_schemas::sync(session, args).await
}
Some(SyncCommands::Hooks(args)) => {
commands::syncs::hooks::sync(session, args).await
}
Expand Down
20 changes: 20 additions & 0 deletions crates/cli/tests/sync_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,26 @@ mod sync_codeowners {
}
}

mod sync_config_schemas {
use super::*;

#[test]
fn creates_schemas_dir() {
let (workspace_config, _, _) = get_cases_fixture_configs();
let sandbox = create_sandbox_with_config("cases", Some(workspace_config), None, None);

assert!(!sandbox.path().join(".moon/cache/schemas").exists());

sandbox
.run_moon(|cmd| {
cmd.arg("sync").arg("config-schemas");
})
.success();

assert!(sandbox.path().join(".moon/cache/schemas").exists());
}
}

mod sync_hooks {
use super::*;

Expand Down
21 changes: 21 additions & 0 deletions crates/config-schema/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "moon_config_schema"
version = "0.0.1"
edition = "2021"
license = "MIT"
description = "Config schema generator."
homepage = "https://moonrepo.dev/moon"
repository = "https://github.com/moonrepo/moon"
publish = false

[dependencies]
moon_config = { path = "../config" }
miette = { workspace = true }
schematic = { workspace = true, features = ["renderer_json_schema", "schema"] }

[features]
default = []
typescript = ["schematic/renderer_typescript"]

[lints]
workspace = true
62 changes: 62 additions & 0 deletions crates/config-schema/src/json_schemas.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use moon_config::*;
use schematic::schema::json_schema::{JsonSchemaOptions, JsonSchemaRenderer};
use schematic::schema::SchemaGenerator;
use std::path::Path;

fn create_jsonschema_renderer() -> JsonSchemaRenderer<'static> {
JsonSchemaRenderer::new(JsonSchemaOptions {
markdown_description: true,
mark_struct_fields_required: false,
set_field_name_as_title: true,
..JsonSchemaOptions::default()
})
}

fn generate_project(out_dir: &Path) -> miette::Result<()> {
let mut generator = SchemaGenerator::default();
generator.add::<ProjectConfig>();
generator.generate(out_dir.join("project.json"), create_jsonschema_renderer())
}

fn generate_tasks(out_dir: &Path) -> miette::Result<()> {
let mut generator = SchemaGenerator::default();
generator.add::<InheritedTasksConfig>();
generator.generate(out_dir.join("tasks.json"), create_jsonschema_renderer())
}

fn generate_template(out_dir: &Path) -> miette::Result<()> {
let mut generator = SchemaGenerator::default();
generator.add::<TemplateConfig>();
generator.generate(out_dir.join("template.json"), create_jsonschema_renderer())?;

let mut generator = SchemaGenerator::default();
generator.add::<TemplateFrontmatterConfig>();
generator.generate(
out_dir.join("template-frontmatter.json"),
create_jsonschema_renderer(),
)
}

fn generate_toolchain(out_dir: &Path) -> miette::Result<()> {
let mut generator = SchemaGenerator::default();
generator.add::<ToolchainConfig>();
generator.generate(out_dir.join("toolchain.json"), create_jsonschema_renderer())
}

fn generate_workspace(out_dir: &Path) -> miette::Result<()> {
let mut generator = SchemaGenerator::default();
generator.add::<WorkspaceConfig>();
generator.generate(out_dir.join("workspace.json"), create_jsonschema_renderer())
}

pub fn generate_json_schemas(out_dir: impl AsRef<Path>) -> miette::Result<()> {
let out_dir = out_dir.as_ref();

generate_project(out_dir)?;
generate_tasks(out_dir)?;
generate_template(out_dir)?;
generate_toolchain(out_dir)?;
generate_workspace(out_dir)?;

Ok(())
}
3 changes: 3 additions & 0 deletions crates/config-schema/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod json_schemas;
#[cfg(feature = "typescript")]
pub mod typescript_types;
24 changes: 24 additions & 0 deletions crates/config-schema/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use moon_config_schema::json_schemas::generate_json_schemas;
#[cfg(feature = "typescript")]
use moon_config_schema::typescript_types::generate_typescript_types;
use std::env;
use std::process::Command;

fn main() {
let cwd = env::current_dir().unwrap();

generate_json_schemas(cwd.join("website/static/schemas")).unwrap();

#[cfg(feature = "typescript")]
generate_typescript_types(cwd.join("packages/types/src")).unwrap();

// Run prettier
let prettier = cwd.join("node_modules/.bin/prettier");

if prettier.exists() {
let mut cmd = Command::new(prettier);
cmd.args(["--write", "packages/types"]);
cmd.current_dir(cwd);
cmd.output().unwrap();
}
}
Loading

0 comments on commit e7c55ea

Please sign in to comment.