Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ jobs:
toolchain: stable
override: true
- name: Rust build
run: cd crates/client && cargo build --release
run: |
cargo build --release --all-features
cargo clippy --release --all-features
12 changes: 7 additions & 5 deletions crates/client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "process-compose-client"
version = "1.73.0"
version = "1.75.2"
description = "Client for Process Compose via OpenAPI and/or project file"
license = "Apache-2.0"
edition = "2021"
Expand All @@ -18,21 +18,21 @@ crate-type = ["rlib"]
[dependencies]
serde = { version = "^1.0", default-features = false, features = ["derive"], optional = true}
serde_json = { version = "^1.0", default-features = false }
openapiv3 = { version = "^2", default-features = false }
openapiv3 = { version = "^2.2", default-features = false }
url = { version = "^2.5", default-features = false, optional = true }

progenitor = { version = "^0.11", default-features = false, optional = true }
prettyplease = { version = "^0.2.24", optional = true }
syn = { version = "^2.0.80", optional = true }
schemars = { version = "^0.8.*" } # update to 1.0 blocked by typify

typify = { version = "^0.4", default-features = false, optional = true }
typify = { version = "^0.5", default-features = false, optional = true }

process-wrap = { version = "9.0", default-features = false, optional = true, features = ["tokio1", "kill-on-drop", ]}


clap = {version = "4.5", default-features = false, features = ["derive", "std", "env", "help", "usage", "error-context", "suggestions"], optional = true}
bon = { version = "3.7", default-features = false, optional = true}
bon = { version = "3.8", default-features = false, optional = true}
struct_field_names = { version = "0.2", default-features = false, optional = true}

[features]
Expand All @@ -42,6 +42,8 @@ typify = ["dep:typify", "dep:prettyplease"]

progenitor = ["dep:progenitor", "dep:prettyplease", "dep:syn"]

cli = ["dep:process-wrap", "dep:bon", "dep:clap", "dep:struct_field_names"]
cli = ["dep:process-wrap", "dep:clap", "dep:struct_field_names"]

ws = ["dep:url", "dep:serde"]

builder = ["dep:bon"]
3 changes: 2 additions & 1 deletion crates/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ Compile time and runtime utility to get Rust Process Compose interface.

- as raw OpenAPI schema or with `progenitor` client.
- as raw project config JSON schema or with `typify` builder.
- as Rust "native" crate behind `cli` providing process-wrap handle produced from command line args builder
- as Rust "native" crate behind `cli` providing process-wrap handle produced from command line args builder
- `builder` to ensure any of features gets builder interface
13 changes: 7 additions & 6 deletions crates/client/src/cli/cmd/parent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use crate::cli::cmd::flags::env;
use crate::cli::cmd::flags::DEFAULT_PORT_NUM;
use crate::cli::cmd::up::ProcessComposeFlagsUp;
/// Process Compose startup flags
#[derive(Debug, Clone, Parser, struct_field_names::StructFieldNames, bon::Builder)]
#[derive(Debug, Clone, Parser, struct_field_names::StructFieldNames)]
#[cfg_attr(feature = "builder", derive(bon::Builder))]
pub struct ProcessComposeFlags {
/// Specify the log file path (env: PC_LOG_FILE)
/// Default "/tmp/process-compose-<user>.log"
Expand All @@ -14,22 +15,22 @@ pub struct ProcessComposeFlags {

/// Disable HTTP server (env: PC_NO_SERVER)
#[arg(long = "no-server", env = env::NO_SERVER)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub no_server: bool,

/// Shut down processes in reverse dependency order (env: PC_ORDERED_SHUTDOWN)
#[arg(long = "ordered-shutdown", env = env::ORDERED_SHUTDOWN)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub ordered_shutdown: bool,

/// Port number (env: PC_PORT_NUM)
#[arg(long = "port", env = env::PORT_NUM, default_value_t = DEFAULT_PORT_NUM)]
#[builder(default = DEFAULT_PORT_NUM)]
#[cfg_attr(feature = "builder", builder(default = DEFAULT_PORT_NUM))]
pub port: u16,

/// Enable read-only mode (env: PC_READ_ONLY)
#[arg(long = "read-only", env = env::READ_ONLY)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub read_only: bool,

/// Path to unix socket (env: PC_SOCKET_PATH)
Expand All @@ -39,7 +40,7 @@ pub struct ProcessComposeFlags {

/// Use unix domain sockets instead of TCP
#[arg(long = "use-uds", default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub use_uds: bool,

#[command(subcommand)]
Expand Down
44 changes: 24 additions & 20 deletions crates/client/src/cli/cmd/up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,88 +5,92 @@ use std::path::PathBuf;
use crate::cli::cmd::flags::env;
use crate::cli::cmd::flags::{DEFAULT_REFRESH_RATE, DEFAULT_SORT_COLUMN, DEFAULT_THEME_NAME};

#[derive(Debug, Clone, Parser, struct_field_names::StructFieldNames, bon::Builder)]
#[derive(Debug, Clone, Parser, struct_field_names::StructFieldNames)]
#[cfg_attr(feature = "builder", derive(bon::Builder))]
pub struct ProcessComposeFlagsUp {
/// Path to config files to load (env: PC_CONFIG_FILES)
#[arg(long = "config", env = env::CONFIG_FILES)]
#[builder(default = Vec::new())]
#[cfg_attr(feature = "builder", builder(default = Vec::new()))]
pub config: Vec<PathBuf>,

/// Detach the TUI after successful startup (requires --detached-with-tui)
#[arg(long = "detach-on-success", default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub detach_on_success: bool,

/// Run in detached mode
#[cfg(unix)]
#[arg(long = "detached", default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub detached: bool,

/// Run in detached mode with TUI
#[cfg(unix)]
#[arg(long = "detached-with-tui", default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub detached_with_tui: bool,

/// Disable .env file loading (env: PC_DISABLE_DOTENV=1)
#[arg(long = "disable-dotenv", env = env::DISABLE_DOTENV, default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub disable_dotenv: bool,

/// Validate the config and exit
#[arg(long = "dry-run", default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub dry_run: bool,

/// Path to env files to load (default .env)
#[arg(long = "env", default_value = ".env")]
#[builder(default = vec![PathBuf::from(".env")])]
#[cfg_attr(feature = "builder", builder(default = vec![PathBuf::from(".env")]))]
pub env_files: Vec<PathBuf>,

/// Hide disabled processes (env: PC_HIDE_DISABLED_PROC)
#[arg(long = "hide-disabled", env = env::HIDE_DISABLED_PROC, default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub hide_disabled: bool,

/// Keep the project running even after all processes exit
#[arg(long = "keep-project", default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub keep_project: bool,

/// Truncate process logs buffer on startup
#[arg(long = "logs-truncate", default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub logs_truncate: bool,

/// Run only specified namespaces (default: all)
#[arg(long = "namespace")]
#[builder(default = Vec::new())]
#[cfg_attr(feature = "builder", builder(default = Vec::new()))]
pub namespaces: Vec<String>,

/// Do not start dependent processes
#[arg(long = "no-deps", default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub no_deps: bool,

/// Collect metrics recursively (env: PC_RECURSIVE_METRICS)
#[arg(long = "recursive-metrics", env = env::RECURSIVE_METRICS, default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub recursive_metrics: bool,

/// TUI refresh interval in seconds
#[arg(long = "ref-rate", default_value_t = DEFAULT_REFRESH_RATE.as_secs().try_into().unwrap())]
#[builder(default = NonZero::new(DEFAULT_REFRESH_RATE.as_secs()).unwrap())]
#[cfg_attr(
feature = "builder",
builder(default = NonZero::new(DEFAULT_REFRESH_RATE.as_secs()).unwrap())
)]
pub refresh_rate: NonZero<u64>,

/// Sort in reverse order
#[arg(long = "reverse", default_value_t = false)]
#[builder(default = false)]
#[cfg_attr(feature = "builder", builder(default = false))]
pub reverse: bool,

/// Paths to shortcut config files to load (env: PC_SHORTCUTS_FILES)
#[arg(long = "shortcuts", env = env::SHORTCUTS_FILES)]
#[builder(default = Vec::new())]
#[cfg_attr(feature = "builder", builder(default = Vec::new()))]
pub shortcuts: Vec<PathBuf>,

/// Slow(er) refresh interval for resource metrics (must be > --ref-rate)
Expand All @@ -95,17 +99,17 @@ pub struct ProcessComposeFlagsUp {

/// Sort column name (default NAME)
#[arg(long = "sort", default_value = DEFAULT_SORT_COLUMN)]
#[builder(default = DEFAULT_SORT_COLUMN.to_string())]
#[cfg_attr(feature = "builder", builder(default = DEFAULT_SORT_COLUMN.to_string()))]
pub sort: String,

/// Select process compose theme (default Default)
#[arg(long = "theme", default_value = DEFAULT_THEME_NAME)]
#[builder(default = DEFAULT_THEME_NAME.to_string())]
#[cfg_attr(feature = "builder", builder(default = DEFAULT_THEME_NAME.to_string()))]
pub theme: String,

/// Enable / disable TUI (use --tui=false to disable) (env: PC_DISABLE_TUI)
#[arg(long = "tui", env = env::DISABLE_TUI, default_value_t = true)]
#[builder(default = true)]
#[cfg_attr(feature = "builder", builder(default = true))]
pub tui: bool,
}

Expand Down
8 changes: 7 additions & 1 deletion crates/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ pub fn typify_pretty(maybe_config: Option<typify::TypeSpace>) -> String {
/// nor upgrades (101 Switching Protocols).
#[cfg(feature = "progenitor")]
pub fn progenitor_pretty(maybe_config: Option<progenitor::Generator>) -> String {
let mut generator = maybe_config.unwrap_or_default();
let mut generator = maybe_config.unwrap_or_else(|| {
#[allow(unused_mut)]
let mut settings = progenitor::GenerationSettings::default();
#[cfg(feature = "builder")]
settings.with_interface(progenitor::InterfaceStyle::Builder);
progenitor::Generator::new(&settings)
});
let mut openapi = openapi().clone();
{
use openapiv3::{PathItem, ReferenceOr};
Expand Down
4 changes: 2 additions & 2 deletions crates/example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ serde_json = { version = "1.0", default-features = false }
progenitor-client = { version = "0.11", default-features = false, optional = false}

# Use the local client crate for CLI flags and exec
process-compose-client = { path = "../client", default-features = false, features = ["cli"] }
process-compose-client = { path = "../client", default-features = false, features = ["cli", "builder"] }
process-wrap = { version = "9.0", default-features = false, features = ["tokio1", ]}

[build-dependencies]
process-compose-client = { path = "../client", default-features = false, features = ["progenitor", "typify"] }
process-compose-client = { path = "../client", default-features = false, features = ["progenitor", "typify", "builder"] }
23 changes: 16 additions & 7 deletions crates/example/src/bin/gen.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
// includes generated code
#![allow(renamed_and_removed_lints)]
include!(concat!(env!("OUT_DIR"), "/client.rs"));
include!(concat!(env!("OUT_DIR"), "/config.rs"));
use crate::openapi::builder::GetProcessInfo;

#[allow(mismatched_lifetime_syntaxes)] // seems some rust version detection prevents consistent linting for expect
pub mod openapi {
include!(concat!(env!("OUT_DIR"), "/client.rs"));
}

#[expect(clippy::derivable_impls)]
#[expect(clippy::clone_on_copy)]
pub mod config {
include!(concat!(env!("OUT_DIR"), "/config.rs"));
}

#[tokio::main]
async fn main() {
// we just compile it to check for compile errors
let client = crate::Client::new("locahost:8080");
if let Ok(response) = client.get_process_info("process-compose").await {
let client = crate::openapi::Client::new("locahost:8080");
if let Ok(response) = GetProcessInfo::new(&client).name("process-compose").send().await {
let _name = &response.name;
unreachable!("errors on bad url");
}

let _config = crate::Project::builder().processes(Processes(<_>::default()));
let _config =
crate::config::Project::builder().processes(crate::config::Processes(<_>::default()));

println!("Compiles!")
}
3 changes: 3 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[toolchain]
channel = "1.90.0"
profile = "default"