From e41a9d9a233f55a27ac3ebf7f0a1d1b9b243e2e0 Mon Sep 17 00:00:00 2001 From: Rui Chen Date: Sat, 28 Dec 2024 14:33:22 -0500 Subject: [PATCH] feat: add shell completion and manpage support Signed-off-by: Rui Chen --- .gitmodules | 2 +- Cargo.lock | 39 +++++++++++++++++++++++++++++++++------ Cargo.toml | 8 +++++++- build.rs | 40 ++++++++++++++++++++++++++++++++++++++++ src/cli.rs | 19 +++++++++++++++++++ src/lib.rs | 5 +++-- src/main.rs | 4 ++-- src/schemastore | 2 +- 8 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 build.rs create mode 100644 src/cli.rs diff --git a/.gitmodules b/.gitmodules index e5f05af..e1d8739 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "src/schemastore"] path = src/schemastore - url = https://github.com/SchemaStore/schemastore + url = https://github.com/SchemaStore/schemastore.git diff --git a/Cargo.lock b/Cargo.lock index d2fd0ca..556cdc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,8 @@ name = "action-validator" version = "0.0.0-git" dependencies = [ "clap", + "clap_complete", + "clap_mangen", "console_error_panic_hook", "glob", "serde", @@ -163,9 +165,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.22" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -173,9 +175,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.22" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -183,6 +185,15 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_complete" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac2e663e3e3bed2d32d065a8404024dad306e699a04263ec59919529f803aee9" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" version = "4.5.18" @@ -197,9 +208,19 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "clap_mangen" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbae9cbfdc5d4fa8711c09bd7b83f644cb48281ac35bf97af3e47b0675864bdf" +dependencies = [ + "clap", + "roff", +] [[package]] name = "colorchoice" @@ -688,6 +709,12 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "roff" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" + [[package]] name = "ryu" version = "1.0.18" diff --git a/Cargo.toml b/Cargo.toml index 3dfd387..297961e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ authors = ["Matt Palmer "] edition = "2021" # If this is changed, .github/workflows/qa.yml build matrix needs updating as well rust-version = "1.60.0" +build = "build.rs" [lib] crate-type = ["cdylib", "rlib"] @@ -23,7 +24,7 @@ crate-type = ["cdylib", "rlib"] js = ["console_error_panic_hook", "valico/js"] [dependencies] -clap = { version = "4.0", features = ["derive"] } +clap = { version = "4.5.23", features = ["derive"] } glob = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" @@ -41,6 +42,11 @@ console_error_panic_hook = { version = "0.1.6", optional = true } serde-wasm-bindgen = "0.4.5" +[build-dependencies] +clap = { version = "4.5", features = ["derive"] } +clap_complete = "4.2" +clap_mangen = "0.2" + [dev-dependencies] wasm-bindgen-test = "0.3.13" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..256eaa9 --- /dev/null +++ b/build.rs @@ -0,0 +1,40 @@ +use std::{fs, io::Result, path::PathBuf}; + +use clap::{CommandFactory, ValueEnum}; +use clap_complete::{generate_to, Shell}; +use clap_mangen::generate_to as generate_manpage; + +mod cli { + include!("src/cli.rs"); +} + +fn main() -> Result<()> { + println!("cargo:rerun-if-changed=src/main.rs"); + println!("cargo:rerun-if-changed=src/config.rs"); + + if let Some(out_path) = std::env::var_os("GEN_DIR").or(std::env::var_os("OUT_DIR")) { + let out_dir = PathBuf::from(out_path); + + // Generate manpage + let man_dir = out_dir.join("man"); + fs::create_dir_all(&man_dir)?; + let mut cmd = cli::CliConfig::command(); + generate_manpage(cmd.clone(), &man_dir)?; + + // Generate shell completions + let completions_dir = out_dir.join("completions"); + fs::create_dir_all(&completions_dir)?; + + for shell in Shell::value_variants() { + generate_to(*shell, &mut cmd, "action-validator", &completions_dir)?; + } + } + + println!( + "cargo:rustc-env=TARGET={}", + std::env::var("TARGET").unwrap() + ); + println!("cargo:rerun-if-env-changed=GEN_DIR"); + + Ok(()) +} diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..dbbd688 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,19 @@ +use clap::Parser; +use std::path::PathBuf; + +/// Minimal struct for Clap usage, without Serde +#[derive(Parser, Debug)] +#[command( + name = "action-validator", + about = "A validator for GitHub Action and Workflow YAML files", + version +)] +pub struct CliConfig { + /// Be more verbose + #[arg(short, long)] + pub verbose: bool, + + /// Input file(s) + #[arg(name = "path_to_action_yaml")] + pub src: Vec, +} diff --git a/src/lib.rs b/src/lib.rs index be5237e..238e775 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod cli; mod config; mod log; mod schemas; @@ -9,7 +10,7 @@ use config::{ActionType, RunConfig}; use validation_error::ValidationError; use validation_state::ValidationState; -pub use crate::config::CliConfig; +pub use crate::cli::CliConfig; use crate::schemas::{validate_as_action, validate_as_workflow}; #[cfg(feature = "js")] @@ -54,7 +55,7 @@ mod js { } #[cfg(not(feature = "js"))] -pub mod cli { +pub mod cli_runtime { use std::fs; use crate::{ diff --git a/src/main.rs b/src/main.rs index 5b50cbd..a12c50f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,8 +10,8 @@ fn main() { let config = CliConfig::parse(); if matches!( - action_validator::cli::run(&config), - action_validator::cli::RunResult::Failure + action_validator::cli_runtime::run(&config), + action_validator::cli_runtime::RunResult::Failure ) { process::exit(1); } diff --git a/src/schemastore b/src/schemastore index acb7898..3c1cdfa 160000 --- a/src/schemastore +++ b/src/schemastore @@ -1 +1 @@ -Subproject commit acb78980a532436336c3f4d0b1a691d9ae7f0bc9 +Subproject commit 3c1cdfa07540846fa2697d1a21ec3433076d720a