From 778af2d1794947add5d3ccfb5e80e748d7c845b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Gardstr=C3=B6m?= Date: Wed, 6 Apr 2022 18:04:08 +0200 Subject: [PATCH] add ci testing for markdown toml fences --- .github/workflows/ci.yml | 2 +- Cargo.lock | 67 ++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 +++ README.md | 4 +-- ci/Cargo.toml | 16 ++++++++++ ci/lib.rs | 48 ++++++++++++++++++++++++++++ ci/tests/toml.rs | 63 +++++++++++++++++++++++++++++++++++++ 7 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 ci/Cargo.toml create mode 100644 ci/lib.rs create mode 100644 ci/tests/toml.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 362000fdc..bbc967cef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,7 +74,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --locked + args: --locked --all-targets --workspace timeout-minutes: 5 generate-matrix: diff --git a/Cargo.lock b/Cargo.lock index ffe034fdc..f51632541 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + [[package]] name = "atty" version = "0.2.14" @@ -67,6 +76,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "ci" +version = "0.0.0" +dependencies = [ + "cross", + "once_cell", + "regex", + "serde", + "serde_json", + "walkdir", +] + [[package]] name = "color-eyre" version = "0.6.1" @@ -269,6 +290,23 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -290,6 +328,15 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "semver" version = "1.0.6" @@ -434,6 +481,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "which" version = "4.2.4" @@ -461,6 +519,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 14e3ba4af..f1b13a5cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,3 +33,7 @@ dunce = "1" [profile.release] lto = true + +[workspace] +default-members = ["."] +members = [".", "ci"] \ No newline at end of file diff --git a/README.md b/README.md index c1e09744e..9ae5418a5 100644 --- a/README.md +++ b/README.md @@ -226,7 +226,7 @@ non-standard targets (i.e. something not reported by rustc/rustup). However, you can use the `build.xargo` or `target.{{TARGET}}.xargo` field in `Cross.toml` to force the use of `xargo`: -``` toml +```toml # all the targets will use `xargo` [build] xargo = true @@ -234,7 +234,7 @@ xargo = true Or, -``` toml +```toml # only this target will use `xargo` [target.aarch64-unknown-linux-gnu] xargo = true diff --git a/ci/Cargo.toml b/ci/Cargo.toml new file mode 100644 index 000000000..c63c0ce69 --- /dev/null +++ b/ci/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "ci" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +path = "lib.rs" + +[dependencies] +regex = "1" +serde = "1" +serde_json = "1" +once_cell = "1" +walkdir = "2" +cross = { path = ".." } diff --git a/ci/lib.rs b/ci/lib.rs new file mode 100644 index 000000000..6e5413632 --- /dev/null +++ b/ci/lib.rs @@ -0,0 +1,48 @@ +use std::{path::{Path, PathBuf}, ffi::OsStr}; + +use once_cell::sync::OnceCell; +use serde::Deserialize; + +static WORKSPACE: OnceCell = OnceCell::new(); + +/// Returns the cargo workspace for the manifest +pub fn get_cargo_workspace() -> &'static Path { + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + WORKSPACE.get_or_init(|| { + #[derive(Deserialize)] + struct Manifest { + workspace_root: PathBuf, + } + let output = std::process::Command::new( + std::env::var("CARGO") + .ok() + .unwrap_or_else(|| "cargo".to_string()), + ) + .arg("metadata") + .arg("--format-version=1") + .arg("--no-deps") + .current_dir(manifest_dir) + .output() + .unwrap(); + let manifest: Manifest = serde_json::from_slice(&output.stdout).unwrap(); + manifest.workspace_root + }) +} + +pub fn walk_dir<'a>( + root: &'_ Path, + skip: &'a [impl AsRef], +) -> impl Iterator> + 'a { + walkdir::WalkDir::new(root).into_iter().filter_entry(|e| { + if skip + .iter() + .map(|s| -> &std::ffi::OsStr { s.as_ref() }) + .any(|dir| e.file_name() == dir) + { + return false; + } else if e.file_type().is_dir() { + return true; + } + e.path().extension() == Some("md".as_ref()) + }) +} diff --git a/ci/tests/toml.rs b/ci/tests/toml.rs new file mode 100644 index 000000000..26adf73bd --- /dev/null +++ b/ci/tests/toml.rs @@ -0,0 +1,63 @@ +use std::io::Read; + +use once_cell::sync::Lazy; +use regex::{Regex, RegexBuilder}; + +static TOML_REGEX: Lazy = Lazy::new(|| { + RegexBuilder::new(r#"```toml\n(.*?)```"#) + .multi_line(true) + .dot_matches_new_line(true) + .build() + .unwrap() +}); + +#[test] +fn toml_check() -> Result<(), Box> { + let workspace_root = ci::get_cargo_workspace(); + let walk = ci::walk_dir( + workspace_root, + &[ + "target", + ".git", + "src", + "CODE_OF_CONDUCT.md", + "CHANGELOG.md", + ], + ); + + for dir_entry in walk { + let dir_entry = dir_entry?; + if dir_entry.file_type().is_dir() { + continue; + } + eprintln!("File: {:?}", dir_entry.path().display()); + let mut file = std::fs::File::open(dir_entry.path()).unwrap(); + let mut contents = String::new(); + file.read_to_string(&mut contents).unwrap(); + for matches in TOML_REGEX.captures_iter(&contents) { + let fence = matches.get(1).unwrap(); + eprintln!( + "testing snippet at: {}:{:?}", + dir_entry.path().display(), + text_line_no(&contents, fence.range().start), + ); + assert!(cross::cross_toml::CrossToml::from_str(fence.as_str())? + .1 + .is_empty()); + } + } + Ok(()) +} + +pub fn text_line_no(text: &str, index: usize) -> usize { + let mut line_no = 0; + let mut count = 0; + for line in text.split('\n') { + line_no += 1; + count += line.as_bytes().len() + 1; + if count >= index { + break; + } + } + line_no +}