Skip to content
Merged
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
30 changes: 20 additions & 10 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["crates/macros", "crates/cargo-bake", "bake"]
resolver = "3"

[workspace.package]
version = "0.19.1"
version = "0.19.2"
edition = "2024"
license = "MIT"
repository = "https://github.com/socketry/bake-rust"
Expand Down Expand Up @@ -65,7 +65,7 @@ name = "bake"
serde.workspace = true
serde_json.workspace = true
linkme.workspace = true
bake-macros = { version = "0.19.1", path = "crates/macros" }
bake-macros = { version = "0.19.2", path = "crates/macros" }

[dev-dependencies]
tempfile.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion bake/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ publish = false

[dependencies]
socketry-project = ">=0.3.7"
bake = { version = "0.19.1", path = ".." }
bake = { version = "0.19.2", path = ".." }
bake-agent-context = { version = "0.3.0" }
bake-test-rust = { version = "0.3.0" }
bake-releases = { version = "0.3.0" }
Expand Down
4 changes: 3 additions & 1 deletion context/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ Bake is a Cargo-compatible task runner inspired by Samuel Williams's Ruby Bake.

## Source map

- src/arguments.rs: parameter metadata, typed validation, command-line parsing.
- src/arguments.rs: typed validation and command-line parsing.
- src/parameter.rs: task parameter metadata and builders.
- src/task.rs: task descriptor and handler interface.
- src/task\_name.rs: constant-evaluated crate and module namespace inference.
- src/registry.rs: registration, namespace imports, command planning, help and output.
- src/output\_format.rs: supported output formats and their names.
- src/output.rs: replaceable default output, raw/JSON/NDJSON formatting, and null sink.
- src/context.rs: shared state, project root, previous result, nested calls.
- crates/macros/: task attribute and generated adapters; re-exported by bake.
Expand Down
10 changes: 5 additions & 5 deletions context/task-libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,11 @@ Use ordinary Rust calls to compose implementation operations. Use `context.call(

Add a reusable task library as a dependency of the local task binary, then run `cargo bake --regenerate` so its registration entries are linked:

```toml
[dependencies]
bake = "0.19"
socketry_executor = { package = "socketry-executor", version = "0.1" }
bake_agent_context = "0.3"
```sh
cargo bake --regenerate
cargo add --manifest-path bake/Cargo.toml socketry-executor --rename socketry_executor
cargo add --manifest-path bake/Cargo.toml bake-agent-context
cargo bake --regenerate
```

The first `cargo bake --regenerate` creates the private `bake/` workspace member and its minimal binary if they do not exist. Each run regenerates a small source file that links unconditional, non-optional, platform-independent direct dependencies in `bake/Cargo.toml` (apart from `bake` itself), and adds a module declaration to the selected binary if needed. It preserves the rest of the task source. Put reusable task libraries in `[dependencies]`; ordinary dependencies used by task code are also linked.
Expand Down
46 changes: 14 additions & 32 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,35 +31,15 @@ The earlier `socketry-bake` package remains available for existing projects; use

## Add tasks to a project

Add an unpublished `bake` binary crate to your workspace:

```text
Cargo.toml
src/
bake/
Cargo.toml
src/main.rs
```

In the project's `Cargo.toml`:
Create the private task package and let Cargo select the Bake dependency:

```toml
[workspace]
members = ["bake"]
```sh
cargo bake --regenerate
cargo add --manifest-path bake/Cargo.toml bake
cargo bake --regenerate
```

In `bake/Cargo.toml`, depend on Bake by its published crate version:

```toml
[package]
name = "project-tasks"
version = "0.0.0"
edition = "2024"
publish = false

[dependencies]
bake = "0.19"
```
The launcher creates an unpublished `bake/` binary and adds it to your workspace. The manifest records the dependency requirement; `Cargo.lock` records the selected version.

In `bake/src/main.rs`:

Expand Down Expand Up @@ -223,6 +203,10 @@ Prepare a release with `cargo bake cargo:version:patch` (or `minor`, `major`, or

See [releases.md](releases.md) for the full release history.

### v0.19.2

- Give `Parameter` and `OutputFormat` dedicated source files; preserve `Format` as a compatibility alias and refresh dependency setup examples.

### v0.19.1

- Keep generated dependency skills out of the tracked repository.
Expand All @@ -237,14 +221,12 @@ See [releases.md](releases.md) for the full release history.

- Support unbounded positional `Vec<T>` task arguments with `#[bake(positional)]`. Require `::` before chaining another task.

### v0.18.0
<!-- bake-readme:releases:end -->

- Derive default task namespaces from `bake_*` library crate names, stripping `bake_` and translating remaining underscores to colons. Preserve explicit names, project binary names, and matching module prefixes. Existing unnamed library tasks outside those prefixes gain a namespace; use explicit names to retain their previous commands.
- Use `bake = "0"` for reusable task libraries so linked crates resolve one Bake 0.x version and share its task registry.
- Resolve task names at compile time. Generated descriptors now include their full namespaces, making manual registration and automatic discovery agree. Manual registries that added those namespaces with `Registry::include` should register the descriptors directly to avoid repeating the prefix.
- Document semantic task-library APIs, crate-derived namespaces, and testing conventions aligned with `socketry-project`.
## See Also

<!-- bake-readme:releases:end -->
- [`socketry-project`](https://github.com/socketry/socketry-project-rust).
- [`bake-agent-context`](https://github.com/socketry/bake-agent-context-rust).

## Contributing

Expand Down
4 changes: 4 additions & 0 deletions releases.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Releases

## v0.19.2

- Give `Parameter` and `OutputFormat` dedicated source files; preserve `Format` as a compatibility alias and refresh dependency setup examples.

## v0.19.1

- Keep generated dependency skills out of the tracked repository.
Expand Down
69 changes: 2 additions & 67 deletions src/arguments.rs
Original file line number Diff line number Diff line change
@@ -1,77 +1,12 @@
// Released under the MIT License.
// Copyright, 2026, by Samuel Williams.

use crate::{Error, Result};
use crate::{Error, Parameter, Result};
use std::collections::BTreeMap;
use std::fmt::Display;
use std::str::FromStr;

/// A task parameter. Names use underscores; command-line flags also accept hyphens.
pub struct Parameter {
pub(crate) name: String,
pub(crate) type_name: &'static str,
pub(crate) positional: bool,
pub(crate) required: bool,
pub(crate) repeated: bool,
pub(crate) default: Option<String>,
pub(crate) description: String,
validate: fn(&str) -> Result<()>,
}

impl Parameter {
/// Values use `FromStr`; custom types can implement it too.
pub fn new<Value: FromStr>(name: &str) -> Self
where
Value::Err: Display,
{
Self {
name: name.into(),
type_name: std::any::type_name::<Value>(),
positional: true,
required: true,
repeated: false,
default: None,
description: String::new(),
validate: |value| parse::<Value>(value).map(|_| ()),
}
}
pub fn named(mut self) -> Self {
self.positional = false;
self
}
pub fn optional(mut self) -> Self {
self.required = false;
self
}
pub fn repeated(mut self) -> Self {
self.repeated = true;
self.positional = false;
self.required = false;
self
}
/// Consume repeated bare values until the task chain separator.
pub fn variadic(mut self) -> Self {
self.repeated = true;
self.positional = true;
self.required = false;
self
}
pub fn default(mut self, value: impl Into<String>) -> Self {
self.default = Some(value.into());
self.required = false;
self.positional = false;
self
}
pub fn help(mut self, description: impl Into<String>) -> Self {
self.description = description.into();
self
}
pub fn name(&self) -> &str {
&self.name
}
}

fn parse<Value: FromStr>(value: &str) -> Result<Value>
pub(crate) fn parse<Value: FromStr>(value: &str) -> Result<Value>
where
Value::Err: Display,
{
Expand Down
12 changes: 6 additions & 6 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Released under the MIT License.
// Copyright, 2026, by Samuel Williams.

use crate::output::Format;
use crate::OutputFormat;
use crate::registry::Invocation;
use crate::{Error, Registry, Result, Value};
use std::any::{Any, TypeId};
Expand All @@ -21,7 +21,7 @@ pub struct Context {
state: HashMap<TypeId, Box<dyn Any>>,
depth: usize,
terminal_output: String,
default_format: Option<Format>,
default_format: Option<OutputFormat>,
}

impl Context {
Expand Down Expand Up @@ -49,10 +49,10 @@ impl Context {
pub(crate) fn take_output(&mut self) -> String {
std::mem::take(&mut self.terminal_output)
}
pub(crate) fn set_default_format(&mut self, format: Option<Format>) {
pub(crate) fn set_default_format(&mut self, format: Option<OutputFormat>) {
self.default_format = format;
}
pub(crate) fn default_format(&self) -> Option<Format> {
pub(crate) fn default_format(&self) -> Option<OutputFormat> {
self.default_format
}
pub fn insert<State: Any>(&mut self, state: State) {
Expand Down Expand Up @@ -133,8 +133,8 @@ mod tests {
let mut context = Registry::new().context("project");
assert_eq!(context.root(), Path::new("project"));
assert_eq!(context.previous(), &Value::Null);
context.set_default_format(Some(Format::Json));
assert_eq!(context.default_format(), Some(Format::Json));
context.set_default_format(Some(OutputFormat::Json));
assert_eq!(context.default_format(), Some(OutputFormat::Json));
assert!(context.get::<usize>().is_none());
assert!(context.get_mut::<usize>().is_none());

Expand Down
9 changes: 7 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ mod arguments;
mod context;
mod error;
mod output;
mod output_format;
mod parameter;
mod registry;
mod task;
mod task_name;
Expand All @@ -24,11 +26,14 @@ pub mod __private {
pub use linkme;
}

pub use arguments::{Arguments, Parameter};
pub use arguments::Arguments;
pub use bake_macros::task;
pub use context::Context;
pub use error::{Error, Result};
pub use output::Format;
pub use output_format::OutputFormat;
/// Compatibility name for [`OutputFormat`].
pub use output_format::OutputFormat as Format;
pub use parameter::Parameter;
pub use registry::Registry;
pub use serde_json::Value;
pub use task::Task;
Expand Down
Loading
Loading