mirror of
https://github.com/rust-lang/mdBook.git
synced 2025-12-27 10:16:09 -05:00
Add an xtask to help with running tests
During development I often need to run a bunch of tests. Instead of having some unwieldy shell command, I have added this xtask to help with running the testing commands.
This commit is contained in:
2
.cargo/config.toml
Normal file
2
.cargo/config.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
[alias]
|
||||
xtask = "run --manifest-path=crates/xtask/Cargo.toml --"
|
||||
@@ -134,6 +134,21 @@ The main test harness is described in the [testsuite documentation](tests/testsu
|
||||
- `cargo clippy --workspace --all-targets --no-deps -- -D warnings` — This makes sure that there are no clippy warnings.
|
||||
- `RUSTDOCFLAGS="-D warnings" cargo doc --workspace --document-private-items --no-deps` — This verifies that there aren't any rustdoc warnings.
|
||||
- `cargo fmt --check` — Verifies that everything is formatted correctly.
|
||||
- `cargo +stable semver-checks` — Verifies that no SemVer breaking changes have been made. You must install [`cargo-semver-checks`](https://crates.io/crates/cargo-semver-checks) first.
|
||||
|
||||
To help simplify running all these commands, you can run the following cargo command:
|
||||
|
||||
```sh
|
||||
cargo xtask test-all
|
||||
```
|
||||
|
||||
It is useful to run all tests before submitting a PR. While developing I recommend to run some subset of that command based on what you are working on. There are individual arguments for each one. For example:
|
||||
|
||||
```sh
|
||||
cargo xtask test-workspace clippy doc eslint fmt gui semver-checks
|
||||
```
|
||||
|
||||
While developing, remove any of those arguments that are not relevant to what you are changing, or are really slow.
|
||||
|
||||
## Making a pull-request
|
||||
|
||||
@@ -208,12 +223,9 @@ Instructions for mdBook maintainers to publish a new release:
|
||||
|
||||
1. Create a PR to update the version and update the CHANGELOG:
|
||||
1. Update the version in `Cargo.toml`
|
||||
2. Run `cargo test` to verify that everything is passing, and to update `Cargo.lock`.
|
||||
3. Double-check for any SemVer breaking changes.
|
||||
Try [`cargo-semver-checks`](https://crates.io/crates/cargo-semver-checks), though beware that the current version of mdBook isn't properly adhering to SemVer due to the lack of `#[non_exhaustive]` and other issues. See https://github.com/rust-lang/mdBook/issues/1835.
|
||||
4. Update `CHANGELOG.md` with any changes that users may be interested in.
|
||||
5. Update `continuous-integration.md` to update the version number for the installation instructions.
|
||||
6. Commit the changes, and open a PR.
|
||||
2. Run `cargo xtask test-all` to verify that everything is passing, and to update `Cargo.lock`.
|
||||
3. Update `CHANGELOG.md` with any changes that users may be interested in.
|
||||
4. Commit the changes, and open a PR.
|
||||
2. After the PR has been merged, create a release in GitHub. This can either be done in the GitHub web UI, or on the command-line:
|
||||
```bash
|
||||
MDBOOK_VERS="`cargo read-manifest | jq -r .version`" ; \
|
||||
|
||||
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -2514,6 +2514,10 @@ dependencies = [
|
||||
"markup5ever 0.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xtask"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.26"
|
||||
|
||||
12
crates/xtask/Cargo.toml
Normal file
12
crates/xtask/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "xtask"
|
||||
publish = false
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
4
crates/xtask/README.md
Normal file
4
crates/xtask/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# xtask
|
||||
|
||||
This is a CLI utility for running development commands for mdbook.
|
||||
See [CONTRIBUTING.md](../../CONTRIBUTING.md) for how to use this.
|
||||
122
crates/xtask/src/main.rs
Normal file
122
crates/xtask/src/main.rs
Normal file
@@ -0,0 +1,122 @@
|
||||
//! Helper for local development.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::error::Error;
|
||||
use std::process::Command;
|
||||
use std::process::exit;
|
||||
|
||||
type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
macro_rules! commands {
|
||||
($($name:literal => $func:ident),* $(,)?) => {
|
||||
[$(($name, $func as fn() -> Result<()>)),*]
|
||||
};
|
||||
}
|
||||
|
||||
let cmds: BTreeMap<&'static str, fn() -> Result<()>> = commands! {
|
||||
"test-all" => test_all,
|
||||
"test-workspace" => test_workspace,
|
||||
"clippy" => clippy,
|
||||
"doc" => doc,
|
||||
"fmt" => fmt,
|
||||
"semver-checks" => semver_checks,
|
||||
"eslint" => eslint,
|
||||
"gui" => gui,
|
||||
}
|
||||
.into_iter()
|
||||
.collect();
|
||||
let keys = cmds.keys().copied().collect::<Vec<_>>().join(", ");
|
||||
let mut args = std::env::args().skip(1).peekable();
|
||||
if args.peek().is_none() {
|
||||
eprintln!("error: specify a command (valid options: {keys})");
|
||||
exit(1);
|
||||
}
|
||||
for arg in args {
|
||||
if let Some(cmd_fn) = cmds.get(arg.as_str()) {
|
||||
cmd_fn()?;
|
||||
} else if matches!(arg.as_str(), "-h" | "--help") {
|
||||
println!("valid options: {keys}");
|
||||
exit(0)
|
||||
} else {
|
||||
eprintln!("error: unknown command `{arg}` (valid options: {keys}");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
println!("all tests passed!");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_all() -> Result<()> {
|
||||
test_workspace()?;
|
||||
clippy()?;
|
||||
doc()?;
|
||||
fmt()?;
|
||||
semver_checks()?;
|
||||
eslint()?;
|
||||
gui()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cargo(args: &str, cb: &dyn Fn(&mut Command)) -> Result<()> {
|
||||
println!("Running `cargo {args}`");
|
||||
let mut cmd = Command::new("cargo");
|
||||
cmd.args(args.split_whitespace());
|
||||
cb(&mut cmd);
|
||||
let status = cmd.status().expect("cargo should be installed");
|
||||
if !status.success() {
|
||||
return Err("command `cargo {args}` failed".into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_workspace() -> Result<()> {
|
||||
cargo("test --workspace", &|_| {})?;
|
||||
cargo("test --workspace --no-default-features", &|_| {})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn clippy() -> Result<()> {
|
||||
cargo(
|
||||
"clippy --workspace --all-targets --no-deps -- -D warnings",
|
||||
&|_| {},
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn doc() -> Result<()> {
|
||||
cargo(
|
||||
"doc --workspace --document-private-items --no-deps",
|
||||
&|cmd| {
|
||||
cmd.env("RUSTDOCFLAGS", "-D warnings");
|
||||
},
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fmt() -> Result<()> {
|
||||
cargo("fmt --check", &|_| {})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn semver_checks() -> Result<()> {
|
||||
cargo("+stable semver-checks --workspace", &|_| {})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn gui() -> Result<()> {
|
||||
cargo("test --test gui", &|_| {})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn eslint() -> Result<()> {
|
||||
println!("Running `npm run lint`");
|
||||
let status = Command::new("npm")
|
||||
.args(["run", "lint"])
|
||||
.status()
|
||||
.expect("npm should be installed");
|
||||
if !status.success() {
|
||||
return Err("eslint failed".into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user