From b059c590c4122acdddbf10cb7565ec97fe249837 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 5 Oct 2023 13:42:58 -0400 Subject: [PATCH] Add basic CI via GitHub Actions (#10) Closes https://github.com/astral-sh/puffin/issues/1. --- .cargo/config.toml | 33 ++++++++++ .github/workflows/ci.yaml | 66 ++++++++++++++++++++ Cargo.toml | 2 +- crates/puffin-cli/src/commands/install.rs | 2 +- crates/puffin-requirements/benches/parser.rs | 4 +- crates/puffin-requirements/src/lib.rs | 13 ++-- rust-toolchain.toml | 2 + 7 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 .github/workflows/ci.yaml create mode 100644 rust-toolchain.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..ca8c7f355 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,33 @@ +[target.'cfg(all())'] +rustflags = [ + # CLIPPY LINT SETTINGS + # This is a workaround to configure lints for the entire workspace, pending the ability to configure this via TOML. + # See: `https://github.com/rust-lang/cargo/issues/5034` + # `https://github.com/EmbarkStudios/rust-ecosystem/issues/22#issuecomment-947011395` + "-Dunsafe_code", + "-Wclippy::pedantic", + # Allowed pedantic lints + "-Wclippy::char_lit_as_u8", + "-Aclippy::collapsible_else_if", + "-Aclippy::collapsible_if", + "-Aclippy::implicit_hasher", + "-Aclippy::match_same_arms", + "-Aclippy::missing_errors_doc", + "-Aclippy::missing_panics_doc", + "-Aclippy::module_name_repetitions", + "-Aclippy::must_use_candidate", + "-Aclippy::similar_names", + "-Aclippy::too_many_lines", + # Disallowed restriction lints + "-Wclippy::print_stdout", + "-Wclippy::print_stderr", + "-Wclippy::dbg_macro", + "-Wclippy::empty_drop", + "-Wclippy::empty_structs_with_brackets", + "-Wclippy::exit", + "-Wclippy::get_unwrap", + "-Wclippy::rc_buffer", + "-Wclippy::rc_mutex", + "-Wclippy::rest_pat_in_fully_bound_structs", + "-Wunreachable_pub" +] diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 000000000..9764c24d2 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,66 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true + +env: + CARGO_INCREMENTAL: 0 + CARGO_NET_RETRY: 10 + CARGO_TERM_COLOR: always + RUSTUP_MAX_RETRIES: 10 + +jobs: + cargo-fmt: + name: "cargo fmt" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: "Install Rust toolchain" + run: rustup component add rustfmt + - name: "rustfmt" + run: cargo fmt --all --check + + cargo-clippy: + name: "cargo clippy" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: "Install Rust toolchain" + run: | + rustup component add clippy + - uses: Swatinem/rust-cache@v2 + - name: "Clippy" + run: cargo clippy --workspace --all-targets --all-features -- -D warnings + + cargo-test: + strategy: + matrix: + os: [ ubuntu-latest, windows-latest ] + runs-on: ${{ matrix.os }} + name: "cargo test | ${{ matrix.os }}" + steps: + - uses: actions/checkout@v4 + - name: "Install Rust toolchain" + run: rustup show + - name: "Install cargo insta" + uses: taiki-e/install-action@v2 + with: + tool: cargo-insta + - uses: Swatinem/rust-cache@v2 + - name: "Tests (Ubuntu)" + if: ${{ matrix.os == 'ubuntu-latest' }} + run: cargo insta test --all --all-features --unreferenced reject + - name: "Tests (Windows)" + if: ${{ matrix.os == 'windows-latest' }} + shell: bash + run: cargo insta test --all --all-features --unreferenced reject + - run: cargo doc --all --no-deps + env: + RUSTDOCFLAGS: "-D warnings" diff --git a/Cargo.toml b/Cargo.toml index 9da828b35..b78fce4a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ resolver = "2" [workspace.package] edition = "2021" -rust-version = "1.71" +rust-version = "1.72" homepage = "https://astral.sh" documentation = "https://astral.sh" repository = "https://github.com/astral-sh/puffin" diff --git a/crates/puffin-cli/src/commands/install.rs b/crates/puffin-cli/src/commands/install.rs index 619c40e26..249db37ca 100644 --- a/crates/puffin-cli/src/commands/install.rs +++ b/crates/puffin-cli/src/commands/install.rs @@ -77,7 +77,7 @@ pub(crate) async fn install(src: &Path) -> Result { // Push all the requirements into the package sink. let mut in_flight: HashSet = HashSet::with_capacity(requirements.len()); - for requirement in requirements.iter() { + for requirement in &*requirements { debug!("--> adding root dependency: {}", requirement); package_sink.unbounded_send(Request::Package(requirement.clone()))?; in_flight.insert(PackageName::normalize(&requirement.name)); diff --git a/crates/puffin-requirements/benches/parser.rs b/crates/puffin-requirements/benches/parser.rs index c7876c094..9e552b247 100644 --- a/crates/puffin-requirements/benches/parser.rs +++ b/crates/puffin-requirements/benches/parser.rs @@ -4,7 +4,7 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use puffin_requirements::Requirements; -const REQUIREMENTS_TXT: &str = r#" +const REQUIREMENTS_TXT: &str = r" # # This file is autogenerated by pip-compile with Python 3.7 # by the following command: @@ -80,7 +80,7 @@ zipp==3.15.0 \ --hash=sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b \ --hash=sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556 # via importlib-metadata -"#; +"; fn bench_fibs(c: &mut Criterion) { let mut group = c.benchmark_group("Parser"); diff --git a/crates/puffin-requirements/src/lib.rs b/crates/puffin-requirements/src/lib.rs index 16fbcd671..60ef40dd9 100644 --- a/crates/puffin-requirements/src/lib.rs +++ b/crates/puffin-requirements/src/lib.rs @@ -77,8 +77,7 @@ impl<'a> RequirementLine<'a> { // The comment _must_ be preceded by whitespace. if requirement[..len + position] .chars() - .rev() - .next() + .next_back() .is_some_and(char::is_whitespace) { len = position; @@ -138,8 +137,7 @@ impl<'a> Iterator for RequirementsIterator<'a> { // If the newline is preceded by a continuation (\\), keep going. if self.text[..self.index + start] .chars() - .rev() - .next() + .next_back() .is_some_and(|c| c == '\\') { // Add the line contents, preceding the continuation. @@ -150,8 +148,7 @@ impl<'a> Iterator for RequirementsIterator<'a> { while let Some((start, length)) = find_newline(&self.text[self.index..]) { if self.text[..self.index + start] .chars() - .rev() - .next() + .next_back() .is_some_and(|c| c == '\\') { // Add the line contents, preceding the continuation. @@ -212,7 +209,7 @@ mod tests { #[test] fn pip_compile() -> Result<()> { assert_debug_snapshot!(Requirements::from_str( - r#" + r" # # This file is autogenerated by pip-compile with Python 3.7 # by the following command: @@ -288,7 +285,7 @@ zipp==3.15.0 \ --hash=sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b \ --hash=sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556 # via importlib-metadata -"# +" )?); Ok(()) } diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 000000000..7e8f0a9aa --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.72"