Support virtual workspaces
Opened this issue · 4 comments
Bug description
cli-xtask
doesn't work for Virtual workspaces out of the box as the first thing it does is attempt to load the root package, and there's way to pass in a package name with the default setup.
Following the instructions for cli-xtask leads to a no root package found error.
- Would you like to work on a fix? [y/n]
Sure, but I'm not sure if it's a doc issue, or an actual code issue. Need help understanding the issue.
To Reproduce
Details
https://github.com/joshka/cli-xtask-no-root-issue
cd cli-xtask-no-root-issue
cargo xtask dist
Outputs:
Error:
0: no root package found
Location:
/Users/joshka/.cargo/registry/src/github.com-1ecc6299db9ec823/cli-xtask-0.6.1/src/config/dist.rs:96
Steps to reproduce the behavior:
Follow the xtask / cli-xtask instructions:
❯ cargo new --bin testing
Created binary (application) `testing` package
❯ cd testing
❯ mkdir testing
❯ mv src Cargo.toml .gitignore testing
❯ cargo new --bin xtask
Created binary (application) `xtask` package
❯ >Cargo.toml
[workspace]
members = [
"testing",
"xtask",
]
❯ mkdir .cargo
❯ >.cargo/config.toml
[alias]
xtask = "run --package xtask --"
zsh: no matches found: [alias]
❯ cargo add -p xtask cli-xtask --features main,bin-crate
Updating crates.io index
Adding cli-xtask v0.6.1 to dependencies.
Features:
+ archive
+ bin-crate
+ error-handler
+ logger
+ main
+ subcommand-build
+ subcommand-clippy
+ subcommand-dist
+ subcommand-dist-archive
+ subcommand-dist-build-bin
+ subcommand-dist-build-completion
+ subcommand-dist-build-doc
+ subcommand-dist-build-license
+ subcommand-dist-build-man
+ subcommand-dist-build-readme
+ subcommand-dist-clean
+ subcommand-fmt
+ subcommand-lint
+ subcommand-pre-release
+ subcommand-test
+ subcommand-tidy
- bin-crate-extra
- lib-crate
- lib-crate-extra
- subcommand-doc
- subcommand-docsrs
- subcommand-exec
- subcommand-sync-rdme
- subcommand-udeps
❯ cargo xtask dist
Compiling proc-macro2 v1.0.59
Compiling quote v1.0.28
Compiling unicode-ident v1.0.9
Compiling libc v0.2.144
Compiling cfg-if v1.0.0
Compiling once_cell v1.17.1
Compiling memchr v2.5.0
Compiling io-lifetimes v1.0.11
Compiling rustix v0.37.19
Compiling serde v1.0.163
Compiling log v0.4.17
Compiling bitflags v1.3.2
Compiling tracing-core v0.1.31
Compiling regex-syntax v0.6.29
Compiling utf8parse v0.2.1
Compiling lazy_static v1.4.0
Compiling aho-corasick v1.0.1
Compiling anstyle-parse v0.2.0
Compiling regex-syntax v0.7.2
Compiling syn v2.0.18
Compiling errno v0.3.1
Compiling pin-project-lite v0.2.9
Compiling anstyle-query v1.0.0
Compiling anstyle v1.0.0
Compiling overload v0.1.1
Compiling regex-automata v0.1.10
Compiling colorchoice v1.0.0
Compiling adler v1.0.2
Compiling tracing-log v0.1.3
Compiling nu-ansi-term v0.46.0
Compiling sharded-slab v0.1.4
Compiling thread_local v1.1.7
Compiling matchers v0.1.0
Compiling strsim v0.10.0
Compiling smallvec v1.10.0
Compiling is-terminal v0.4.7
Compiling regex v1.8.3
Compiling heck v0.4.1
Compiling cc v1.0.79
Compiling clap_lex v0.5.0
Compiling gimli v0.27.2
Compiling anstream v0.3.2
Compiling camino v1.1.4
Compiling crc32fast v1.3.2
Compiling serde_json v1.0.96
Compiling serde_derive v1.0.163
Compiling tracing-attributes v0.1.24
Compiling clap_builder v4.3.0
Compiling backtrace v0.3.67
Compiling clap_derive v4.3.0
Compiling semver v1.0.17
Compiling thiserror v1.0.40
Compiling eyre v0.6.8
Compiling addr2line v0.19.0
Compiling thiserror-impl v1.0.40
Compiling miniz_oxide v0.6.2
Compiling object v0.30.3
Compiling indenter v0.3.3
Compiling rustc-demangle v0.1.23
Compiling ryu v1.0.13
Compiling itoa v1.0.6
Compiling owo-colors v3.5.0
Compiling miniz_oxide v0.7.1
Compiling xattr v0.2.3
Compiling filetime v0.2.21
Compiling roff v0.2.1
Compiling cli-xtask v0.6.1
Compiling same-file v1.0.6
Compiling time-core v0.1.1
Compiling tar v0.4.38
Compiling walkdir v2.3.3
Compiling time v0.3.21
Compiling flate2 v1.0.26
Compiling tracing v0.1.37
Compiling tracing-subscriber v0.3.17
Compiling tracing-error v0.2.0
Compiling clap v4.3.0
Compiling clap_complete v4.3.0
Compiling clap_mangen v0.2.11
Compiling color-spantrace v0.2.0
Compiling color-eyre v0.6.2
Compiling cargo-platform v0.1.2
Compiling cargo_metadata v0.15.4
Compiling xtask v0.1.0 (/Users/joshka/local/testing/xtask)
Finished dev [unoptimized + debuginfo] target(s) in 11.62s
Running `target/debug/xtask dist`
Hello, world!
❯ >xtask/src/main.rs
use cli_xtask::{Result, Xtask};
fn main() -> Result<()> {
<Xtask>::main()
}
❯ cargo xtask dist
Compiling xtask v0.1.0 (/Users/joshka/local/testing/xtask)
Finished dev [unoptimized + debuginfo] target(s) in 0.95s
Running `target/debug/xtask dist`
Error:
0: no root package found
Location:
/Users/joshka/.cargo/registry/src/github.com-1ecc6299db9ec823/cli-xtask-0.6.1/src/config/dist.rs:96
Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
Expected behavior
Either this succeeds or the error message suggests the next steps.
Screenshots
Environment
- OS: macOS 12.6.5
- cli-xtask version: 0.6.1
Additional context
Details
❯ tree -a --git-ignore --no-icons
./
├── .cargo/
│ └── config.toml
├── .git/
│ ├── hooks/
│ │ └── README.sample*
│ ├── info/
│ │ └── exclude
│ ├── objects/
│ │ ├── info/
│ │ └── pack/
│ ├── refs/
│ │ ├── heads/
│ │ └── tags/
│ ├── config
│ ├── description
│ └── HEAD
├── testing/
│ ├── src/
│ │ └── main.rs
│ ├── .gitignore
│ └── Cargo.toml
├── xtask/
│ ├── src/
│ │ └── main.rs
│ └── Cargo.toml
├── Cargo.lock
└── Cargo.toml
❯ cargo metadata | jq '.'
{
"packages": [
...
{
"name": "testing",
"version": "0.1.0",
"id": "testing 0.1.0 (path+file:///Users/joshka/local/testing/testing)",
"license": null,
"license_file": null,
"description": null,
"source": null,
"dependencies": [],
"targets": [
{
"kind": [
"bin"
],
"crate_types": [
"bin"
],
"name": "testing",
"src_path": "/Users/joshka/local/testing/testing/src/main.rs",
"edition": "2021",
"doc": true,
"doctest": false,
"test": true
}
],
"features": {},
"manifest_path": "/Users/joshka/local/testing/testing/Cargo.toml",
"metadata": null,
"publish": null,
"authors": [],
"categories": [],
"keywords": [],
"readme": null,
"repository": null,
"homepage": null,
"documentation": null,
"edition": "2021",
"links": null,
"default_run": null,
"rust_version": null
},
...
{
"name": "xtask",
"version": "0.1.0",
"id": "xtask 0.1.0 (path+file:///Users/joshka/local/testing/xtask)",
"license": null,
"license_file": null,
"description": null,
"source": null,
"dependencies": [
{
"name": "cli-xtask",
"source": "registry+https://github.com/rust-lang/crates.io-index",
"req": "^0.6.1",
"kind": null,
"rename": null,
"optional": false,
"uses_default_features": true,
"features": [
"main",
"bin-crate"
],
"target": null,
"registry": null
}
],
"targets": [
{
"kind": [
"bin"
],
"crate_types": [
"bin"
],
"name": "xtask",
"src_path": "/Users/joshka/local/testing/xtask/src/main.rs",
"edition": "2021",
"doc": true,
"doctest": false,
"test": true
}
],
"features": {},
"manifest_path": "/Users/joshka/local/testing/xtask/Cargo.toml",
"metadata": null,
"publish": null,
"authors": [],
"categories": [],
"keywords": [],
"readme": null,
"repository": null,
"homepage": null,
"documentation": null,
"edition": "2021",
"links": null,
"default_run": null,
"rust_version": null
}
],
"workspace_members": [
"testing 0.1.0 (path+file:///Users/joshka/local/testing/testing)",
"xtask 0.1.0 (path+file:///Users/joshka/local/testing/xtask)"
],
"resolve": {
"nodes": [
...
{
"id": "testing 0.1.0 (path+file:///Users/joshka/local/testing/testing)",
"dependencies": [],
"deps": [],
"features": []
},
...
{
"id": "xtask 0.1.0 (path+file:///Users/joshka/local/testing/xtask)",
"dependencies": [
"cli-xtask 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)"
],
"deps": [
{
"name": "cli_xtask",
"pkg": "cli-xtask 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"kind": null,
"target": null
}
]
}
],
"features": []
}
],
"root": null
},
"target_directory": "/Users/joshka/local/ja/target",
"version": 1,
"workspace_root": "/Users/joshka/local/ja",
"metadata": null
}
Particularly note the "root": null
there
A bit of a dive through the source of cli-xtask and cargo-workspace suggests that the issue is that resolve is Some(Resolve)
, but the root is set to None within the resolve part. I don't understand why this is so.
This is my first time attempting to use a workspace in a rust project, so I'm assuming that I'm missing a very small and obvious detail that would be obvious for someone more experience. However, I wasn't able to quite understand from the combination of xtask / xtask-cli docs / xtask-cli code / cargo-workspace code / the workspaces section of the cargo book and the workspaces section of the rust programming language book.
The answer is that this doesn't support virtual workspaces (yet ;))
Hey there, reopening this as I'd like to actually have this work for a package that we're going to be using virtual workspaces for soon. When I initially raised this issue, my rust-fu was fairly basic, so I wasn't really sure how this should work and how the pieces fit together.
The cargo way of running commands is that if there's a root package, then that should be used as the default package for any command, but this should be able to be overridden using a --package
argument. When there is no root package (in a virtual workspace), then the commands should act as-if they're called to run against the default members, or all packages if there is no default members list. This also can be overridden with --package
/ --workspace
(and --all
if you want to include the deprecated flag that is common).
The missing parts here seem like:
--package
args are only on the commands at lower levels than the main, so require a root package--workspace
args only work if there's a root package
I propose to do:
- move the package / workspace args up into the main command parser
- make the default distconfigbuilder setup do the right thing for selecting packages based on defaults and args
- parse the cli args before constructing the distconfig
- perhaps add a small affordance where if there's only two packages in a virtual workspace (some main package and xtask), treat the default single package approach as operating just on the main package, regardless of whether this is the root or just a plain package) - this point is debatable (and possibly the wrong thing to do - what do you think @gifnksm)
I suspect some of this might entail breaking changes to existing usages of this package, but there don't seem to be a large amount, so this is likely a small concern. https://crates.io/crates/cli-xtask/reverse_dependencies / https://github.com/search?q=cli-xtask+path%3Acargo.toml&type=code
Alternative workaround:
- As a workaround, users of this crate could define their own main command parser with the package and workspace args and pass these through to the cli-xtask parsing code. This seems janky though.
You can use <Xtask>::main_with_config()
to specify the packages to be distributed.
Also, I've added the virtual workspace example and some utility methods in cli-xtask
v0.9.0.
In this example, binaries in workspace default members are built for distribution.
You can choose arbitrary packages by using DistConfigBuilder::package_by_name()
.
Do you think this will satisfy your use case?
Maybe. I ended up going fairly manual right for expediency (https://github.com/ratatui/ratatui/blob/main/xtask/src/main.rs), so I'll have to take another look at this to work out the overlap.