1#[cfg(test)] 2mod tidy; 3 4use std::time::Instant; 5 6use xshell::{cmd, Shell}; 7 8const MSRV: &str = "1.56.0"; 9 10fn main() -> xshell::Result<()> { 11 let sh = Shell::new()?; 12 13 let _e = push_toolchain(&sh, "stable")?; 14 let _e = sh.push_env("CARGO", ""); 15 16 { 17 let _s = section("BUILD"); 18 cmd!(sh, "cargo test --workspace --no-run").run()?; 19 } 20 21 { 22 let _s = section("TEST"); 23 24 for &release in &[None, Some("--release")] { 25 cmd!(sh, "cargo test --features unstable {release...}").run()?; 26 cmd!( 27 sh, 28 "cargo test --no-default-features --features unstable,std,parking_lot {release...}" 29 ) 30 .run()?; 31 } 32 33 // Skip doctests for no_std tests as those don't work 34 cmd!(sh, "cargo test --no-default-features --features unstable --test it").run()?; 35 cmd!(sh, "cargo test --no-default-features --features unstable,alloc --test it").run()?; 36 37 cmd!(sh, "cargo test --no-default-features --features critical-section").run()?; 38 cmd!(sh, "cargo test --features critical-section").run()?; 39 } 40 41 { 42 let _s = section("TEST_BETA"); 43 let _e = push_toolchain(&sh, "beta")?; 44 cmd!(sh, "cargo test --features unstable").run()?; 45 } 46 47 { 48 let _s = section("TEST_MSRV"); 49 let _e = push_toolchain(&sh, MSRV)?; 50 sh.copy_file("Cargo.lock.msrv", "Cargo.lock")?; 51 cmd!(sh, "cargo build").run()?; 52 } 53 54 { 55 let _s = section("TEST_MIRI"); 56 let miri_nightly= cmd!(sh, "curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri").read()?; 57 let _e = push_toolchain(&sh, &format!("nightly-{}", miri_nightly))?; 58 59 sh.remove_path("./target")?; 60 61 cmd!(sh, "rustup component add miri").run()?; 62 cmd!(sh, "cargo miri setup").run()?; 63 cmd!(sh, "cargo miri test --features unstable").run()?; 64 } 65 66 { 67 let _s = section("PUBLISH"); 68 69 let version = cmd!(sh, "cargo pkgid").read()?.rsplit_once('#').unwrap().1.to_string(); 70 let tag = format!("v{version}"); 71 72 let current_branch = cmd!(sh, "git branch --show-current").read()?; 73 let has_tag = cmd!(sh, "git tag --list").read()?.lines().any(|it| it.trim() == tag); 74 let dry_run = sh.var("CI").is_err() || has_tag || current_branch != "master"; 75 eprintln!("Publishing{}!", if dry_run { " (dry run)" } else { "" }); 76 77 let dry_run_arg = if dry_run { Some("--dry-run") } else { None }; 78 cmd!(sh, "cargo publish {dry_run_arg...}").run()?; 79 if dry_run { 80 eprintln!("{}", cmd!(sh, "git tag {tag}")); 81 eprintln!("{}", cmd!(sh, "git push --tags")); 82 } else { 83 cmd!(sh, "git tag {tag}").run()?; 84 cmd!(sh, "git push --tags").run()?; 85 } 86 } 87 Ok(()) 88} 89 90fn push_toolchain<'a>( 91 sh: &'a xshell::Shell, 92 toolchain: &str, 93) -> xshell::Result<xshell::PushEnv<'a>> { 94 cmd!(sh, "rustup toolchain install {toolchain} --no-self-update").run()?; 95 let res = sh.push_env("RUSTUP_TOOLCHAIN", toolchain); 96 cmd!(sh, "rustc --version").run()?; 97 Ok(res) 98} 99 100fn section(name: &'static str) -> impl Drop { 101 println!("::group::{name}"); 102 let start = Instant::now(); 103 defer(move || { 104 let elapsed = start.elapsed(); 105 eprintln!("{name}: {elapsed:.2?}"); 106 println!("::endgroup::"); 107 }) 108} 109 110fn defer<F: FnOnce()>(f: F) -> impl Drop { 111 struct D<F: FnOnce()>(Option<F>); 112 impl<F: FnOnce()> Drop for D<F> { 113 fn drop(&mut self) { 114 if let Some(f) = self.0.take() { 115 f() 116 } 117 } 118 } 119 D(Some(f)) 120} 121