improve build/ci times (#2396)

- avoid building all workspace crates with `cargo x build` (only plugins and main binary)
- only set the target triple in tests for plugins
- add new profile for `cargo x run` to build with optimized dependencies => FAST plugins when developing (thanks [Bevy Book](https://bevyengine.org/learn/book/getting-started/setup/#compile-with-performance-optimizations) for the idea)
- use https://github.com/Swatinem/rust-cache to avoid rebuilding dependencies every time in ci
- split `Build & Test` job into two so they run in parallel
- hopefully improve the flaky tests situation, this also makes the e2e tests run much faster (some tests produced correct snapshots but had some logic errors causing them to loop for much longer than necessary). Add some output to the tests so it is easier to see if something goes wrong.
- remove verbose build output from e2e test build
This commit is contained in:
Thomas Linford 2023-05-03 21:16:38 +02:00 committed by GitHub
parent ecd63a100b
commit f598ca3738
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 167 additions and 117 deletions

View file

@ -10,7 +10,7 @@ env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
jobs: jobs:
test: test-e2e:
name: Build generic binary and run tests on it name: Build generic binary and run tests on it
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: cachix environment: cachix
@ -37,8 +37,10 @@ jobs:
- name: Add musl target - name: Add musl target
run: rustup target add x86_64-unknown-linux-musl run: rustup target add x86_64-unknown-linux-musl
#run: cargo install --debug cargo-make #run: cargo install --debug cargo-make
- name: Build asset - uses: Swatinem/rust-cache@v2
run: cargo xtask ci e2e --build # ensure the target folder exists, otherwise fixtures won't be in the right place
- name: Create target folder
run: mkdir -p ${{ github.workspace }}/target
# we copy this manually into the target folder instead of mounting it because # we copy this manually into the target folder instead of mounting it because
# github actions creates the service first, and if it has a mount that is part # github actions creates the service first, and if it has a mount that is part
# of your yet unchecked out code, you cannot checkout the code after the mount # of your yet unchecked out code, you cannot checkout the code after the mount

View file

@ -2,71 +2,69 @@ name: Rust
on: on:
push: push:
branches: [ main ] branches: [main]
pull_request: pull_request:
branches: [ main ] branches: [main]
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
jobs: jobs:
build: build:
name: Build & Test name: Build
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ ubuntu-latest, macos-latest ] os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/cache@v3 - name: Setup toolchain
with: run: rustup show
path: | - uses: Swatinem/rust-cache@v2
~/.cargo/bin/ - name: Build
~/.cargo/registry run: cargo xtask build
~/.cargo/git
target test:
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} name: Test
- name: Add WASM target
run: rustup target add wasm32-wasi strategy:
- name: Build fail-fast: false
run: cargo xtask build matrix:
- name: Test os: [ubuntu-latest, macos-latest]
run: cargo xtask test
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Setup toolchain
run: rustup show
- uses: Swatinem/rust-cache@v2
- name: Test
run: cargo xtask test
format: format:
name: Check Formatting name: Check Formatting
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/cache@v3 - name: Setup toolchain
with: run: rustup show
path: | - name: Check Format
~/.cargo/bin/ run: cargo xtask format --check
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check Format
run: cargo xtask format --check
clippy: clippy:
name: Check Clippy Lints name: Check Clippy Lints
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/cache@v3 - name: Setup toolchain
with: run: rustup show
path: | - uses: Swatinem/rust-cache@v2
~/.cargo/bin/ - name: Check clippy lints
~/.cargo/registry run: cargo xtask clippy
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check clippy lints
run: cargo xtask clippy

View file

@ -45,6 +45,12 @@ members = [
".", ".",
] ]
[profile.dev-opt]
inherits = "dev"
[profile.dev-opt.package."*"]
opt-level = 3
[profile.release] [profile.release]
lto = true lto = true
strip = true strip = true

View file

@ -190,8 +190,7 @@ pub fn cannot_split_terminals_vertically_when_active_terminal_is_too_small() {
name: "Split pane to the right", name: "Split pane to the right",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2) {
{
remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&PANE_MODE);
remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE);
// back to normal mode after split // back to normal mode after split
@ -205,7 +204,12 @@ pub fn cannot_split_terminals_vertically_when_active_terminal_is_too_small() {
name: "Make sure only one pane appears", name: "Make sure only one pane appears",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) { if remote_terminal.cursor_position_is(3, 2)
//two empty lines at the bottom to make sure there is no plugin output
&& remote_terminal
.current_snapshot()
.ends_with(" \n ")
{
// ... is the truncated tip line // ... is the truncated tip line
step_is_complete = true; step_is_complete = true;
} }
@ -967,7 +971,7 @@ pub fn detach_and_attach_session() {
name: "Wait for session to be attached", name: "Wait for session to be attached",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(77, 2)
{ {
// we're back inside the session // we're back inside the session
step_is_complete = true; step_is_complete = true;
@ -1003,9 +1007,7 @@ pub fn status_bar_loads_custom_keybindings() {
name: "Wait for app to load", name: "Wait for app to load",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 1) if remote_terminal.cursor_position_is(3, 2) && remote_terminal.tip_appears() {
&& remote_terminal.snapshot_contains("$ █ ││$")
&& remote_terminal.snapshot_contains("$ ") {
step_is_complete = true; step_is_complete = true;
} }
step_is_complete step_is_complete
@ -1316,7 +1318,7 @@ pub fn mirrored_sessions() {
name: "take snapshot after", name: "take snapshot after",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.snapshot_contains("┐┌") && remote_terminal.snapshot_contains("┐┌")
{ {
// cursor is back in the first tab // cursor is back in the first tab
@ -1329,7 +1331,7 @@ pub fn mirrored_sessions() {
name: "take snapshot after", name: "take snapshot after",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.snapshot_contains("┐┌") && remote_terminal.snapshot_contains("┐┌")
{ {
// cursor is back in the first tab // cursor is back in the first tab
@ -1592,6 +1594,7 @@ pub fn multiple_users_in_different_tabs() {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.tip_appears() && remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #1 [ ]")
&& remote_terminal.snapshot_contains("Tab #2") && remote_terminal.snapshot_contains("Tab #2")
&& remote_terminal.status_bar_appears() && remote_terminal.status_bar_appears()
{ {
@ -1608,7 +1611,7 @@ pub fn multiple_users_in_different_tabs() {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.tip_appears() && remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #2") && remote_terminal.snapshot_contains("Tab #2 [ ]")
&& remote_terminal.status_bar_appears() && remote_terminal.status_bar_appears()
{ {
// cursor is in the newly opened second tab // cursor is in the newly opened second tab
@ -1649,7 +1652,9 @@ pub fn bracketed_paste() {
name: "Send pasted text followed by normal text", name: "Send pasted text followed by normal text",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) if remote_terminal.status_bar_appears()
&& remote_terminal.tab_bar_appears()
&& remote_terminal.cursor_position_is(3, 2)
{ {
remote_terminal.send_key(&BRACKETED_PASTE_START); remote_terminal.send_key(&BRACKETED_PASTE_START);
remote_terminal.send_key(&TAB_MODE); remote_terminal.send_key(&TAB_MODE);
@ -1717,7 +1722,9 @@ pub fn toggle_floating_panes() {
name: "Wait for new pane to appear", name: "Wait for new pane to appear",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(33, 7) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(33, 7)
&& remote_terminal.snapshot_contains("FLOATING PANES VISIBLE")
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
step_is_complete = true; step_is_complete = true;
} }

View file

@ -299,11 +299,15 @@ impl RemoteTerminal {
x == self.cursor_x && y == self.cursor_y x == self.cursor_x && y == self.cursor_y
} }
pub fn tip_appears(&self) -> bool { pub fn tip_appears(&self) -> bool {
self.last_snapshot.lock().unwrap().contains("Tip:") let snapshot = self.last_snapshot.lock().unwrap();
snapshot.contains("Tip:") || snapshot.contains("QuickNav:")
} }
pub fn status_bar_appears(&self) -> bool { pub fn status_bar_appears(&self) -> bool {
self.last_snapshot.lock().unwrap().contains("Ctrl +") self.last_snapshot.lock().unwrap().contains("Ctrl +")
} }
pub fn tab_bar_appears(&self) -> bool {
self.last_snapshot.lock().unwrap().contains("Tab #1")
}
pub fn snapshot_contains(&self, text: &str) -> bool { pub fn snapshot_contains(&self, text: &str) -> bool {
self.last_snapshot.lock().unwrap().contains(text) self.last_snapshot.lock().unwrap().contains(text)
} }
@ -625,6 +629,10 @@ impl RemoteRunner {
} }
pub fn run_next_step(&mut self) { pub fn run_next_step(&mut self) {
if let Some(next_step) = self.steps.get(self.current_step_index) { if let Some(next_step) = self.steps.get(self.current_step_index) {
println!(
"running step: {}, retries left: {}",
next_step.name, self.retries_left
);
let (cursor_x, cursor_y) = *self.cursor_coordinates.lock().unwrap(); let (cursor_x, cursor_y) = *self.cursor_coordinates.lock().unwrap();
let remote_terminal = RemoteTerminal { let remote_terminal = RemoteTerminal {
cursor_x, cursor_x,
@ -650,6 +658,10 @@ impl RemoteRunner {
let mut retries_left = RETRIES; let mut retries_left = RETRIES;
let instruction = step.instruction; let instruction = step.instruction;
loop { loop {
println!(
"taking snapshot: {}, retries left: {}",
step.name, retries_left
);
if retries_left == 0 { if retries_left == 0 {
self.test_timed_out = true; self.test_timed_out = true;
return self.last_snapshot.lock().unwrap().clone(); return self.last_snapshot.lock().unwrap().clone();
@ -671,6 +683,7 @@ impl RemoteRunner {
} }
} }
pub fn run_all_steps(&mut self) { pub fn run_all_steps(&mut self) {
println!();
loop { loop {
self.run_next_step(); self.run_next_step();
if !self.steps_left() { if !self.steps_left() {

View file

@ -4,7 +4,7 @@
//! //!
//! - [`build`]: Builds general cargo projects (i.e. zellij components) with `cargo build` //! - [`build`]: Builds general cargo projects (i.e. zellij components) with `cargo build`
//! - [`manpage`]: Builds the manpage with `mandown` //! - [`manpage`]: Builds the manpage with `mandown`
use crate::flags; use crate::{flags, WorkspaceMember};
use anyhow::Context; use anyhow::Context;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use xshell::{cmd, Shell}; use xshell::{cmd, Shell};
@ -22,10 +22,13 @@ pub fn build(sh: &Shell, flags: flags::Build) -> anyhow::Result<()> {
std::process::exit(1); std::process::exit(1);
} }
for subcrate in crate::WORKSPACE_MEMBERS.iter() { for WorkspaceMember { crate_name, .. } in crate::WORKSPACE_MEMBERS
let err_context = || format!("failed to build '{subcrate}'"); .iter()
.filter(|member| member.build)
{
let err_context = || format!("failed to build '{crate_name}'");
if subcrate.contains("plugins") { if crate_name.contains("plugins") {
if flags.no_plugins { if flags.no_plugins {
continue; continue;
} }
@ -35,10 +38,10 @@ pub fn build(sh: &Shell, flags: flags::Build) -> anyhow::Result<()> {
} }
} }
let _pd = sh.push_dir(Path::new(subcrate)); let _pd = sh.push_dir(Path::new(crate_name));
// Tell the user where we are now // Tell the user where we are now
println!(); println!();
let msg = format!(">> Building '{subcrate}'"); let msg = format!(">> Building '{crate_name}'");
crate::status(&msg); crate::status(&msg);
println!("{}", msg); println!("{}", msg);
@ -48,8 +51,8 @@ pub fn build(sh: &Shell, flags: flags::Build) -> anyhow::Result<()> {
} }
base_cmd.run().with_context(err_context)?; base_cmd.run().with_context(err_context)?;
if subcrate.contains("plugins") { if crate_name.contains("plugins") {
let (_, plugin_name) = subcrate let (_, plugin_name) = crate_name
.rsplit_once('/') .rsplit_once('/')
.context("Cannot determine plugin name from '{subcrate}'")?; .context("Cannot determine plugin name from '{subcrate}'")?;

View file

@ -90,7 +90,7 @@ fn e2e_build(sh: &Shell) -> anyhow::Result<()> {
.and_then(|cargo| { .and_then(|cargo| {
cmd!( cmd!(
sh, sh,
"{cargo} build --verbose --release --target x86_64-unknown-linux-musl" "{cargo} build --release --target x86_64-unknown-linux-musl"
) )
.run() .run()
.map_err(anyhow::Error::new) .map_err(anyhow::Error::new)
@ -101,26 +101,20 @@ fn e2e_build(sh: &Shell) -> anyhow::Result<()> {
fn e2e_test(sh: &Shell, args: Vec<OsString>) -> anyhow::Result<()> { fn e2e_test(sh: &Shell, args: Vec<OsString>) -> anyhow::Result<()> {
let err_context = "failed to run E2E tests"; let err_context = "failed to run E2E tests";
let _pd = sh.push_dir(crate::project_root());
e2e_build(sh).context(err_context)?; e2e_build(sh).context(err_context)?;
// Build debug plugins for test binary let _pd = sh.push_dir(crate::project_root());
build::build(
sh,
flags::Build {
release: false,
no_plugins: false,
plugins_only: true,
},
)
.context(err_context)?;
// set --no-default-features so the test binary gets built with the plugins from assets/plugins that just got built
crate::cargo() crate::cargo()
.and_then(|cargo| { .and_then(|cargo| {
cmd!(sh, "{cargo} test -- --ignored --nocapture --test-threads 1") cmd!(
.args(args) sh,
.run() "{cargo} test --no-default-features -- --ignored --nocapture --test-threads 1"
.map_err(anyhow::Error::new) )
.args(args)
.run()
.map_err(anyhow::Error::new)
}) })
.context(err_context) .context(err_context)
} }

View file

@ -1,5 +1,5 @@
//! Handle running `cargo clippy` on the sources. //! Handle running `cargo clippy` on the sources.
use crate::{build, flags}; use crate::{build, flags, WorkspaceMember};
use anyhow::Context; use anyhow::Context;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use xshell::{cmd, Shell}; use xshell::{cmd, Shell};
@ -21,17 +21,17 @@ pub fn clippy(sh: &Shell, _flags: flags::Clippy) -> anyhow::Result<()> {
.and_then(|_| crate::cargo()) .and_then(|_| crate::cargo())
.context("failed to run task 'clippy'")?; .context("failed to run task 'clippy'")?;
for subcrate in crate::WORKSPACE_MEMBERS.iter() { for WorkspaceMember { crate_name, .. } in crate::WORKSPACE_MEMBERS.iter() {
let _pd = sh.push_dir(Path::new(subcrate)); let _pd = sh.push_dir(Path::new(crate_name));
// Tell the user where we are now // Tell the user where we are now
println!(); println!();
let msg = format!(">> Running clippy on '{subcrate}'"); let msg = format!(">> Running clippy on '{crate_name}'");
crate::status(&msg); crate::status(&msg);
println!("{}", msg); println!("{}", msg);
cmd!(sh, "{cargo} clippy --all-targets --all-features") cmd!(sh, "{cargo} clippy --all-targets --all-features")
.run() .run()
.with_context(|| format!("failed to run task 'clippy' on '{subcrate}'"))?; .with_context(|| format!("failed to run task 'clippy' on '{crate_name}'"))?;
} }
Ok(()) Ok(())
} }

View file

@ -69,6 +69,8 @@ xflags::xflags! {
optional --data-dir path: PathBuf optional --data-dir path: PathBuf
/// Enable the singlepass compiler for WASM plugins /// Enable the singlepass compiler for WASM plugins
optional --singlepass optional --singlepass
/// Disable optimizing dependencies
optional --disable-deps-optimize
/// Arguments to pass after `cargo run --` /// Arguments to pass after `cargo run --`
repeated args: OsString repeated args: OsString
} }
@ -182,6 +184,7 @@ pub struct Run {
pub data_dir: Option<PathBuf>, pub data_dir: Option<PathBuf>,
pub singlepass: bool, pub singlepass: bool,
pub disable_deps_optimize: bool,
} }
#[derive(Debug)] #[derive(Debug)]

View file

@ -1,5 +1,5 @@
//! Handle running `cargo fmt` on the sources. //! Handle running `cargo fmt` on the sources.
use crate::flags; use crate::{flags, WorkspaceMember};
use anyhow::Context; use anyhow::Context;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use xshell::{cmd, Shell}; use xshell::{cmd, Shell};
@ -11,11 +11,11 @@ pub fn format(sh: &Shell, flags: flags::Format) -> anyhow::Result<()> {
.and_then(|_| crate::cargo()) .and_then(|_| crate::cargo())
.context("failed to run task 'format'")?; .context("failed to run task 'format'")?;
for subcrate in crate::WORKSPACE_MEMBERS.iter() { for WorkspaceMember { crate_name, .. } in crate::WORKSPACE_MEMBERS.iter() {
let _pd = sh.push_dir(Path::new(subcrate)); let _pd = sh.push_dir(Path::new(crate_name));
// Tell the user where we are now // Tell the user where we are now
println!(); println!();
let msg = format!(">> Formatting '{subcrate}'"); let msg = format!(">> Formatting '{crate_name}'");
crate::status(&msg); crate::status(&msg);
println!("{}", msg); println!("{}", msg);
@ -24,7 +24,7 @@ pub fn format(sh: &Shell, flags: flags::Format) -> anyhow::Result<()> {
cmd = cmd.arg("--check"); cmd = cmd.arg("--check");
} }
cmd.run() cmd.run()
.with_context(|| format!("Failed to format '{subcrate}'"))?; .with_context(|| format!("Failed to format '{crate_name}'"))?;
} }
Ok(()) Ok(())
} }

View file

@ -23,18 +23,23 @@ use std::{
}; };
use xshell::Shell; use xshell::Shell;
pub struct WorkspaceMember {
crate_name: &'static str,
build: bool,
}
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref WORKSPACE_MEMBERS: Vec<&'static str> = vec![ pub static ref WORKSPACE_MEMBERS: Vec<WorkspaceMember> = vec![
"default-plugins/compact-bar", WorkspaceMember{crate_name: "default-plugins/compact-bar", build: true},
"default-plugins/status-bar", WorkspaceMember{crate_name: "default-plugins/status-bar", build: true},
"default-plugins/strider", WorkspaceMember{crate_name: "default-plugins/strider", build: true},
"default-plugins/tab-bar", WorkspaceMember{crate_name: "default-plugins/tab-bar", build: true},
"zellij-utils", WorkspaceMember{crate_name: "zellij-utils", build: false},
"zellij-tile-utils", WorkspaceMember{crate_name: "zellij-tile-utils", build: false},
"zellij-tile", WorkspaceMember{crate_name: "zellij-tile", build: false},
"zellij-client", WorkspaceMember{crate_name: "zellij-client", build: false},
"zellij-server", WorkspaceMember{crate_name: "zellij-server", build: false},
".", WorkspaceMember{crate_name: ".", build: true},
]; ];
} }

View file

@ -1,8 +1,8 @@
//! Composite pipelines for the build system. //! Composite pipelines for the build system.
//! //!
//! Defines multiple "pipelines" that run specific individual steps in sequence. //! Defines multiple "pipelines" that run specific individual steps in sequence.
use crate::flags;
use crate::{build, clippy, format, test}; use crate::{build, clippy, format, test};
use crate::{flags, WorkspaceMember};
use anyhow::Context; use anyhow::Context;
use xshell::{cmd, Shell}; use xshell::{cmd, Shell};
@ -95,6 +95,12 @@ pub fn run(sh: &Shell, flags: flags::Run) -> anyhow::Result<()> {
let singlepass = flags.singlepass.then_some(["--features", "singlepass"]); let singlepass = flags.singlepass.then_some(["--features", "singlepass"]);
let profile = if flags.disable_deps_optimize {
"dev"
} else {
"dev-opt"
};
if let Some(ref data_dir) = flags.data_dir { if let Some(ref data_dir) = flags.data_dir {
let data_dir = sh.current_dir().join(data_dir); let data_dir = sh.current_dir().join(data_dir);
@ -105,6 +111,7 @@ pub fn run(sh: &Shell, flags: flags::Run) -> anyhow::Result<()> {
.arg("--no-default-features") .arg("--no-default-features")
.args(["--features", "disable_automatic_asset_installation"]) .args(["--features", "disable_automatic_asset_installation"])
.args(singlepass.iter().flatten()) .args(singlepass.iter().flatten())
.args(["--profile", profile])
.args(["--", "--data-dir", &format!("{}", data_dir.display())]) .args(["--", "--data-dir", &format!("{}", data_dir.display())])
.args(&flags.args) .args(&flags.args)
.run() .run()
@ -124,6 +131,7 @@ pub fn run(sh: &Shell, flags: flags::Run) -> anyhow::Result<()> {
.and_then(|cargo| { .and_then(|cargo| {
cmd!(sh, "{cargo} run") cmd!(sh, "{cargo} run")
.args(singlepass.iter().flatten()) .args(singlepass.iter().flatten())
.args(["--profile", profile])
.args(["--"]) .args(["--"])
.args(&flags.args) .args(&flags.args)
.run() .run()
@ -288,18 +296,18 @@ pub fn publish(sh: &Shell, flags: flags::Publish) -> anyhow::Result<()> {
} }
// Publish all the crates // Publish all the crates
for member in crate::WORKSPACE_MEMBERS.iter() { for WorkspaceMember { crate_name, .. } in crate::WORKSPACE_MEMBERS.iter() {
if member.contains("plugin") || member.contains("xtask") { if crate_name.contains("plugin") || crate_name.contains("xtask") {
continue; continue;
} }
let _pd = sh.push_dir(project_dir.join(member)); let _pd = sh.push_dir(project_dir.join(crate_name));
loop { loop {
let msg = format!(">> Publishing '{member}'"); let msg = format!(">> Publishing '{crate_name}'");
crate::status(&msg); crate::status(&msg);
println!("{}", msg); println!("{}", msg);
let more_args = match *member { let more_args = match *crate_name {
// This is needed for zellij to pick up the plugins from the assets included in // This is needed for zellij to pick up the plugins from the assets included in
// the released zellij-utils binary // the released zellij-utils binary
"." => Some("--no-default-features"), "." => Some("--no-default-features"),
@ -314,7 +322,7 @@ pub fn publish(sh: &Shell, flags: flags::Publish) -> anyhow::Result<()> {
.context(err_context) .context(err_context)
{ {
println!(); println!();
println!("Publishing crate '{member}' failed with error:"); println!("Publishing crate '{crate_name}' failed with error:");
println!("{:?}", err); println!("{:?}", err);
println!(); println!();
println!("Retry? [y/n]"); println!("Retry? [y/n]");
@ -346,7 +354,7 @@ pub fn publish(sh: &Shell, flags: flags::Publish) -> anyhow::Result<()> {
if retry { if retry {
continue; continue;
} else { } else {
println!("Aborting publish for crate '{member}'"); println!("Aborting publish for crate '{crate_name}'");
return Err::<(), _>(err); return Err::<(), _>(err);
} }
} else { } else {

View file

@ -1,4 +1,4 @@
use crate::{build, flags}; use crate::{build, flags, WorkspaceMember};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use std::path::Path; use std::path::Path;
use xshell::{cmd, Shell}; use xshell::{cmd, Shell};
@ -20,18 +20,29 @@ pub fn test(sh: &Shell, flags: flags::Test) -> anyhow::Result<()> {
) )
.context(err_context)?; .context(err_context)?;
for subcrate in crate::WORKSPACE_MEMBERS.iter() { for WorkspaceMember { crate_name, .. } in crate::WORKSPACE_MEMBERS.iter() {
let _pd = sh.push_dir(Path::new(subcrate)); // the workspace root only contains e2e tests, skip it
if *crate_name == "." {
continue;
}
let _pd = sh.push_dir(Path::new(crate_name));
// Tell the user where we are now // Tell the user where we are now
println!(""); println!("");
let msg = format!(">> Testing '{}'", subcrate); let msg = format!(">> Testing '{}'", crate_name);
crate::status(&msg); crate::status(&msg);
println!("{}", msg); println!("{}", msg);
cmd!(sh, "{cargo} test --target {host_triple} --") // Override wasm32-wasi target for plugins only
.args(&flags.args) let cmd = if crate_name.contains("plugins") {
cmd!(sh, "{cargo} test --target {host_triple} --")
} else {
cmd!(sh, "{cargo} test --")
};
cmd.args(&flags.args)
.run() .run()
.with_context(|| format!("Failed to run tests for '{}'", subcrate))?; .with_context(|| format!("Failed to run tests for '{}'", crate_name))?;
} }
Ok(()) Ok(())
} }