Skip to content
Open
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
31 changes: 31 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,34 @@ We instrument Lux with the [`tracing`](https://docs.rs/tracing/) crate.
When adding traces, be sure to [instrument async code properly](https://docs.rs/tracing/latest/tracing/struct.Span.html#in-asynchronous-code).
In general, prefer the [`#[instrument]` attribute macro](https://docs.rs/tracing/latest/tracing/attr.instrument.html),
as it automatically generates correct code when used on an async function.

### Schema generation

We generate JSON Schema for `config.toml` and `lux.toml` from their Rust types
using [`schemars`](https://github.com/GREsau/schemars).
The generated schemas are [published on the documentation site](https://lux.lumen-labs.org/reference).

The schema's `description` fields are populated from the doc comments on the
TOML-facing structs, e.g. `ConfigBuilder` in
[`lux-lib/src/config/mod.rs`](./lux-lib/src/config/mod.rs) and
`PartialProjectToml` in
[`lux-lib/src/project/project_toml.rs`](./lux-lib/src/project/project_toml.rs),
as well as the build/test/source structs they nest.

> [!IMPORTANT]
>
> Doc comments on these fields are user-facing documentation.
> Write them with that in mind:
>
> - Describe the TOML option, not the Rust implementation.
> - Keep them concise, and mention the default (`Default: ...`) where one exists.
> - Use double quotes for string values (e.g. `">= 5.1"`).
> - Use backticks for identifiers, field names, commands and crates
> (e.g. `version`, `make`, `diffy`).

To preview the generated documentation:

```console
cargo lx util schema --kind lux-toml --output-format text
cargo lx util schema --kind config --output-format text
```
1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion lux-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ flaky_test = "0.2"
[dependencies.lux-lib]
version = "0.64.2"
path = "../lux-lib/"
features = ["clap"]
features = ["clap", "schema"]

[features]
default = ["gpgme"]
Expand Down
4 changes: 4 additions & 0 deletions lux-cli/src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use miette::Result;

mod completion;
mod man;
mod schema;

#[derive(Subcommand)]
pub enum Util {
Expand All @@ -14,11 +15,14 @@ pub enum Util {
Completion(Completion),
/// Generate manpages.
Man(Man),
/// Generate the JSON Schema for `lux.toml` or `config.toml`.
Schema(schema::Schema),
}

pub async fn util(util: Util, _config: Config) -> Result<()> {
match util {
Util::Completion(completion) => completion::completion(completion).await,
Util::Man(man) => man::man(man).await,
Util::Schema(schema) => schema::schema(schema),
}
}
40 changes: 40 additions & 0 deletions lux-cli/src/util/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use clap::ValueEnum;
use miette::{IntoDiagnostic, Result};

use crate::args::OutputFormat;

#[derive(Clone, Copy, Debug, ValueEnum)]
pub enum SchemaKind {
/// The project manifest (`lux.toml`).
LuxToml,
/// The Lux configuration file (`config.toml`).
Config,
}

#[derive(clap::Args)]
pub struct Schema {
/// Which schema to generate.
#[arg(long, value_enum, default_value = "lux-toml", ignore_case = true)]
kind: SchemaKind,

/// Output format: `json` (JSON Schema) or `text` (Markdown).
#[arg(long, default_value = "json", value_enum, ignore_case = true)]
output_format: OutputFormat,
}

pub fn schema(cmd: Schema) -> Result<()> {
let schema = match cmd.kind {
SchemaKind::LuxToml => lux_lib::schema::lux_toml_schema(),
SchemaKind::Config => lux_lib::schema::config_schema(),
};
match cmd.output_format {
OutputFormat::Json => {
println!(
"{}",
serde_json::to_string_pretty(&schema).into_diagnostic()?
)
}
OutputFormat::Text => print!("{}", lux_lib::schema::to_markdown(&schema)),
}
Ok(())
}
2 changes: 2 additions & 0 deletions lux-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ reqwest = { version = "0.13", default-features = false, features = [
semver = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde-enum-str = "0.5"
schemars = { version = "1", optional = true }
sha2 = "0.11"
shell-words = "1.1"
shlex = "2.0"
Expand Down Expand Up @@ -123,6 +124,7 @@ default = [
]
clap = ["dep:clap"]
gpgme = ["dep:gpgme"]
schema = ["dep:schemars"]
vendored = ["vendored-openssl", "vendored-libgit2"]
vendored-openssl = ["openssl/vendored", "reqwest/native-tls-vendored"]
vendored-libgit2 = ["git2/vendored-libgit2"]
Expand Down
2 changes: 2 additions & 0 deletions lux-lib/src/config/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use strum_macros::Display;

/// Configuration for the build process.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub(super) struct BuildConfig {
/// The build profile to use when compiling packages.
/// Default: [`BuildProfile::Release`]
Expand All @@ -20,6 +21,7 @@ pub(super) struct BuildConfig {
/// The build profile to use when compiling packages.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Display)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
pub enum Profile {
Expand Down
1 change: 1 addition & 0 deletions lux-lib/src/config/external_deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize};
/// Used as a fallback when searching for external dependencies if they
/// cannot be found using pkg-config.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ExternalDependencySearchConfig {
/// Patterns for binary files
#[serde(default = "default_bin_patterns")]
Expand Down
40 changes: 40 additions & 0 deletions lux-lib/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,43 +399,74 @@ pub enum ConfigError {
/// - Populate the fields from overriding sources (e.g. CLI arguments).
/// - Finish with [`ConfigBuilder::build`].
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ConfigBuilder {
/// The LuaRocks repository server to fetch rocks and rockspecs from.
/// Default: "https://luarocks.org/".
#[serde(
default,
deserialize_with = "deserialize_url",
serialize_with = "serialize_url"
)]
#[cfg_attr(feature = "schema", schemars(with = "Option<String>"))]
server: Option<Url>,
/// Additional LuaRocks repository servers.
#[serde(
default,
deserialize_with = "deserialize_url_vec",
serialize_with = "serialize_url_vec"
)]
#[cfg_attr(feature = "schema", schemars(with = "Option<Vec<String>>"))]
extra_servers: Option<Vec<Url>>,
/// Additional wally package registries (git-index URLs), in addition to the
/// official wally index.
#[serde(
default,
deserialize_with = "deserialize_url_vec",
serialize_with = "serialize_url_vec"
)]
#[cfg_attr(feature = "schema", schemars(with = "Option<Vec<String>>"))]
extra_wally_registries: Option<Vec<Url>>,
/// The LuaRocks server namespace to use.
namespace: Option<String>,
/// The Lua version to use. Default: the detected installed Lua version.
lua_version: Option<LuaVersion>,
/// The tree in which to install rocks.
user_tree: Option<PathBuf>,
/// The tree to use when in a workspace.
/// Default: a ".lux" directory in the workspace root.
workspace_tree: Option<PathBuf>,
/// The directory in which to install Lua if it is not found.
lua_dir: Option<PathBuf>,
/// The cache directory, e.g. for LuaRocks manifests.
cache_dir: Option<PathBuf>,
/// The data directory, in which the default user install tree resides.
data_dir: Option<PathBuf>,
/// A directory with locally vendored sources and rockspecs, used instead of
/// a remote server.
vendor_dir: Option<PathBuf>,
/// Whether to fetch development/scm rocks. Default: `false`.
enable_development_packages: Option<bool>,
/// Whether to display verbose output of executed commands. Default: `false`.
verbose: Option<bool>,
/// Whether to disable progress bars and spinners. Default: `false`.
no_progress: Option<bool>,
/// Whether to skip prompts, selecting the default option. Default: `false`.
no_prompt: Option<bool>,
/// Timeout for network operations, in seconds. `0` disables the timeout.
/// Default: `30`.
#[cfg_attr(feature = "schema", schemars(with = "Option<u64>"))]
timeout: Option<Duration>,
/// Maximum number of parallel jobs, e.g. for downloads and installs.
/// `0` means no limit.
max_jobs: Option<usize>,
/// Variable names mapped to their values. Lux substitutes these in the
/// `lux.toml` and in rockspecs before building.
variables: Option<HashMap<String, String>>,
/// Access tokens for fetching sources from private hosts, mapped by host.
/// These can also be set via the `LUX_ACCESS_TOKENS` environment variable.
#[serde(default, skip_serializing)]
#[cfg_attr(feature = "schema", schemars(with = "Option<HashMap<String, String>>"))]
access_tokens: Option<HashMap<String, AccessToken>>,
#[serde(default)]
external_deps: ExternalDependencySearchConfig,
Expand All @@ -444,11 +475,20 @@ pub struct ConfigBuilder {

#[serde(skip)]
entrypoint_layout: Option<Arc<dyn CustomRockLayout>>,
/// The user agent to use when making web requests.
/// Default: "lux/<version>" (CLI), "lux-lua/<version>" (lux-lua) or "lux-lib/<version>".
user_agent: Option<String>,
/// Whether to generate a ".luarc.json" on build. Default: `true`.
generate_luarc: Option<bool>,
/// The Lua language server configuration file name. Default: ".luarc.json".
luarc_file_name: Option<String>,
/// Whether to wrap installed Lua bin scripts to run with the detected or
/// configured Lua installation. Default: `true`.
wrap_bin_scripts: Option<bool>,
/// Which package types to include in searches.
package_types: Option<RemotePackageTypeFilterSpec>,
/// Whether to disable prompts for two-factor authentication (2FA) codes.
/// Default: `false`.
no_tfa: Option<bool>,
}

Expand Down
2 changes: 2 additions & 0 deletions lux-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pub mod progress;
pub mod project;
pub mod remote_package_db;
pub mod rockspec;
#[cfg(feature = "schema")]
pub mod schema;
pub mod toolchains;
pub mod tree;
pub mod upload;
Expand Down
Loading
Loading