* xtask: Implement a new build system xtask is a cargo alias that is used to extend the cargo build system with custom commands. For an introduction to xtask, see here: https://github.com/matklad/cargo-xtask/ The idea is that instead of writing makefiles, xtask requires no additional dependencies except `cargo` and `rustc`, which must be available to build the project anyway. This commit provides a basic implementation of the `build` and `test` subcommands. * xtask/deps: Add 'which' * xtask/test: Handle error when cargo not found * xtask/flags: Add more commands to perform different useful tasks. Includes: - clippy - format - "make" (composite) - "install" (composite) Also add more options to `build` to selectively compile plugins or leave them out entirely. * xtask/main: Return error when cargo not found * xtask/build: Add more subtasks - `wasm_opt_plugins` and - `manpage` that perform other build commands. Add thorough documentation on what each of these does and also handle the new `build` cli flags appropriately. * xtask/clippy: Add job to run clippy * xtask/format: Add job to run rustfmt * xtask/pipeline: Add composite commands that perform multiple atomic xtask commands sequentially in a pipeline sort of fashion. * xtask/deps: Pin dependencies * xtask/main: Integrate new jobs and add documentation. * xtask: Implement 'dist' which performs an 'install' and copies the resulting zellij binary along with some other assets to a `target/dist` folder. * cargo: Update xflags version * xtask: Measure task time, update tty title * xtask: Update various tasks * xtask: wasm-opt plugins in release builds automatically. * xtask/build: Copy debug plugins to assets folder * xtask: Add 'run' subcommand * xtask: Add arbitrary args to test and run * xtask: Rearrange CLI commands in help * xtask: Add deprecation notice * docs: Replace `cargo make` with `xtask` * github: Use `xtask` in workflows. * xtask: Add support for CI commands * xtask: Streamline error handling * github: Use new xtask commands in CI * xtask: Add 'publish' job * xtask/publish: Add retry when publish fails * xtask: Apply rustfmt * xtask: Refine 'make' deprecation warning * xtask: add task to build manpage * contributing: Fix e2e commands * xtask/run: Add missing `--` to pass all arguments following `xtask run` directly to the zellij binary being run. * xtask: Stay in invocation dir and make all tasks that need it change to the project root dir themselves. * xtask/run: Add `--data-dir` flag which will allow very quick iterations when not changing the plugins between builds. * xtask/ci: Install dependencies without asking * utils: Allow including plugins from target folder * utils/assets: Reduce asset map complexity * utils/consts: Update asset map docs * xtask: Fix plugin includes * xtask/test: Build plugins first because the zellij binary needs to include the plugins. * xtask/test: Fix formatting * xtask: Add notice on how to disable it
172 lines
4.6 KiB
Rust
172 lines
4.6 KiB
Rust
//! Tasks related to zellij CI
|
|
use crate::{
|
|
build,
|
|
flags::{self, CiCmd, Cross, E2e},
|
|
};
|
|
use anyhow::Context;
|
|
use std::{ffi::OsString, path::PathBuf};
|
|
use xshell::{cmd, Shell};
|
|
|
|
pub fn main(sh: &Shell, flags: flags::Ci) -> anyhow::Result<()> {
|
|
let err_context = "failed to run CI task";
|
|
|
|
match flags.subcommand {
|
|
CiCmd::E2e(E2e {
|
|
build: false,
|
|
test: false,
|
|
..
|
|
}) => Err(anyhow::anyhow!(
|
|
"either '--build' or '--test' must be provided!"
|
|
)),
|
|
CiCmd::E2e(E2e {
|
|
build: true,
|
|
test: true,
|
|
..
|
|
}) => Err(anyhow::anyhow!(
|
|
"flags '--build' and '--test' are mutually exclusive!"
|
|
)),
|
|
CiCmd::E2e(E2e {
|
|
build: true,
|
|
test: false,
|
|
..
|
|
}) => e2e_build(sh),
|
|
CiCmd::E2e(E2e {
|
|
build: false,
|
|
test: true,
|
|
args,
|
|
}) => e2e_test(sh, args),
|
|
CiCmd::Cross(Cross { triple }) => cross_compile(sh, &triple),
|
|
}
|
|
.context(err_context)
|
|
}
|
|
|
|
fn e2e_build(sh: &Shell) -> anyhow::Result<()> {
|
|
let err_context = "failed to build E2E binary";
|
|
|
|
build::build(
|
|
sh,
|
|
flags::Build {
|
|
release: true,
|
|
no_plugins: false,
|
|
plugins_only: true,
|
|
},
|
|
)
|
|
.context(err_context)?;
|
|
|
|
// Copy plugins to e2e data-dir
|
|
let project_root = crate::project_root();
|
|
let plugin_dir = project_root
|
|
.join("zellij-utils")
|
|
.join("assets")
|
|
.join("plugins");
|
|
let data_dir = project_root.join("target").join("e2e-data");
|
|
let plugins: Vec<_> = std::fs::read_dir(plugin_dir)
|
|
.context(err_context)?
|
|
.filter_map(|dir_entry| {
|
|
if let Ok(entry) = dir_entry {
|
|
entry
|
|
.file_name()
|
|
.to_string_lossy()
|
|
.ends_with(".wasm")
|
|
.then_some(entry.path())
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
sh.remove_path(&data_dir)
|
|
.and_then(|_| sh.create_dir(&data_dir))
|
|
.and_then(|_| sh.create_dir(&data_dir.join("plugins")))
|
|
.context(err_context)?;
|
|
|
|
for plugin in plugins {
|
|
sh.copy_file(plugin, data_dir.join("plugins"))
|
|
.context(err_context)?;
|
|
}
|
|
|
|
let _pd = sh.push_dir(project_root);
|
|
crate::cargo()
|
|
.and_then(|cargo| {
|
|
cmd!(
|
|
sh,
|
|
"{cargo} build --verbose --release --target x86_64-unknown-linux-musl"
|
|
)
|
|
.run()
|
|
.map_err(anyhow::Error::new)
|
|
})
|
|
.context(err_context)
|
|
}
|
|
|
|
fn e2e_test(sh: &Shell, args: Vec<OsString>) -> anyhow::Result<()> {
|
|
let err_context = "failed to run E2E tests";
|
|
|
|
let _pd = sh.push_dir(crate::project_root());
|
|
e2e_build(sh).context(err_context)?;
|
|
|
|
// Build debug plugins for test binary
|
|
build::build(
|
|
sh,
|
|
flags::Build {
|
|
release: false,
|
|
no_plugins: false,
|
|
plugins_only: true,
|
|
},
|
|
)
|
|
.context(err_context)?;
|
|
|
|
crate::cargo()
|
|
.and_then(|cargo| {
|
|
cmd!(sh, "{cargo} test -- --ignored --nocapture --test-threads 1")
|
|
.args(args)
|
|
.run()
|
|
.map_err(anyhow::Error::new)
|
|
})
|
|
.context(err_context)
|
|
}
|
|
|
|
fn cross_compile(sh: &Shell, target: &OsString) -> anyhow::Result<()> {
|
|
let err_context = || format!("failed to cross-compile for {target:?}");
|
|
|
|
crate::cargo()
|
|
.and_then(|cargo| {
|
|
cmd!(sh, "{cargo} install mandown").run()?;
|
|
Ok(cargo)
|
|
})
|
|
.and_then(|cargo| {
|
|
cmd!(sh, "{cargo} install cross")
|
|
.run()
|
|
.map_err(anyhow::Error::new)
|
|
})
|
|
.with_context(err_context)?;
|
|
|
|
build::build(
|
|
sh,
|
|
flags::Build {
|
|
release: true,
|
|
no_plugins: false,
|
|
plugins_only: true,
|
|
},
|
|
)
|
|
.and_then(|_| build::manpage(sh))
|
|
.with_context(err_context)?;
|
|
|
|
cross()
|
|
.and_then(|cross| {
|
|
cmd!(sh, "{cross} build --verbose --release --target {target}")
|
|
.run()
|
|
.map_err(anyhow::Error::new)
|
|
})
|
|
.with_context(err_context)
|
|
}
|
|
|
|
fn cross() -> anyhow::Result<PathBuf> {
|
|
match which::which("cross") {
|
|
Ok(path) => Ok(path),
|
|
Err(e) => {
|
|
eprintln!("!! 'cross' wasn't found but is needed for this build step.");
|
|
eprintln!("!! Please install it with: `cargo install cross`");
|
|
Err(e).context("couldn't find 'cross' executable")
|
|
},
|
|
}
|
|
}
|