diff --git a/.clippy.toml b/.clippy.toml index 81d631e..027eef4 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1,5 +1,5 @@ -msrv = "1.72" # MSRV warn-on-all-wildcard-imports = true +allow-print-in-tests = true allow-expect-in-tests = true allow-unwrap-in-tests = true allow-dbg-in-tests = true diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 1725e3e..6cd7ded 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -3,6 +3,7 @@ 'before 5am on the first day of the month', ], semanticCommits: 'enabled', + commitMessageLowerCase: 'never', configMigration: true, dependencyDashboard: true, customManagers: [ @@ -20,7 +21,25 @@ 'MSRV.*?(?\\d+\\.\\d+(\\.\\d+)?)', '(?\\d+\\.\\d+(\\.\\d+)?).*?MSRV', ], - depNameTemplate: 'rust', + depNameTemplate: 'MSRV', + packageNameTemplate: 'rust-lang/rust', + datasourceTemplate: 'github-releases', + }, + { + customType: 'regex', + fileMatch: [ + '^rust-toolchain\\.toml$', + 'Cargo.toml$', + 'clippy.toml$', + '\\.clippy.toml$', + '^\\.github/workflows/ci.yml$', + '^\\.github/workflows/rust-next.yml$', + ], + matchStrings: [ + 'STABLE.*?(?\\d+\\.\\d+(\\.\\d+)?)', + '(?\\d+\\.\\d+(\\.\\d+)?).*?STABLE', + ], + depNameTemplate: 'STABLE', packageNameTemplate: 'rust-lang/rust', datasourceTemplate: 'github-releases', }, @@ -32,7 +51,7 @@ 'custom.regex', ], matchPackageNames: [ - 'rust', + 'MSRV', ], minimumReleaseAge: '126 days', // 3 releases * 6 weeks per release * 7 days per week internalChecksFilter: 'strict', @@ -41,6 +60,19 @@ '* * * * *', ], }, + { + commitMessageTopic: 'Rust Stable', + matchManagers: [ + 'custom.regex', + ], + matchPackageNames: [ + 'STABLE', + ], + extractVersion: '^(?\\d+\\.\\d+)', // Drop the patch version + schedule: [ + '* * * * *', + ], + }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies // - Take advantage of latest dev-dependencies @@ -72,6 +104,7 @@ matchCurrentVersion: '>=1.0.0', matchUpdateTypes: [ 'minor', + 'patch', ], enabled: false, }, @@ -99,6 +132,7 @@ matchCurrentVersion: '>=1.0.0', matchUpdateTypes: [ 'minor', + 'patch', ], automerge: true, groupName: 'compatible (dev)', diff --git a/.github/settings.yml b/.github/settings.yml index 846c8c7..2805c59 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -42,14 +42,18 @@ labels: color: '#c2e0c6' description: "Help wanted!" -branches: - - name: master - protection: - required_pull_request_reviews: null - required_conversation_resolution: true - required_status_checks: - # Required. Require branches to be up to date before merging. - strict: false - contexts: ["CI", "Lint Commits", "Spell Check with Typos"] - enforce_admins: false - restrictions: null +# This serves more as documentation. +# Branch protection API was replaced by rulesets but settings isn't updated. +# See https://github.com/repository-settings/app/issues/825 +# +# branches: +# - name: master +# protection: +# required_pull_request_reviews: null +# required_conversation_resolution: true +# required_status_checks: +# # Required. Require branches to be up to date before merging. +# strict: false +# contexts: ["CI", "Spell Check with Typos"] +# enforce_admins: false +# restrictions: null diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 442e637..35b3da8 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -17,6 +17,10 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: security_audit: permissions: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index efe1230..85ff52c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,25 +10,30 @@ on: - master env: - RUST_BACKTRACE: 1 CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: ci: permissions: contents: none name: CI - needs: [test, msrv, docs, rustfmt, clippy] + needs: [test, msrv, lockfile, docs, rustfmt, clippy] runs-on: ubuntu-latest + if: "always()" steps: - - name: Done - run: exit 0 + - name: Failed + run: exit 1 + if: "contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped')" test: name: Test strategy: matrix: - os: ["ubuntu-latest", "windows-latest", "macos-latest"] + os: ["ubuntu-latest", "windows-latest", "macos-14"] rust: ["stable"] continue-on-error: ${{ matrix.rust != 'stable' }} runs-on: ${{ matrix.os }} @@ -40,16 +45,13 @@ jobs: with: toolchain: ${{ matrix.rust }} - uses: Swatinem/rust-cache@v2 - - name: Build Debug - run: cargo test --no-run - - name: Test Debug - run: cargo test - - name: Build Release - run: cargo test --no-run --release - - name: Test Release - run: cargo test --release + - uses: taiki-e/install-action@cargo-hack + - name: Build + run: cargo test --workspace --no-run + - name: Test + run: cargo hack test --feature-powerset --exclude-features nightly --workspace msrv: - name: "Check MSRV: 1.72" + name: "Check MSRV" runs-on: ubuntu-latest steps: - name: Checkout repository @@ -57,14 +59,11 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.72" # MSRV + toolchain: stable - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack - name: Default features - run: cargo check --workspace --all-targets - - name: No-default features - run: cargo check --workspace --all-targets --no-default-features - - name: Release - run: cargo check --workspace --all-targets --release + run: cargo hack check --feature-powerset --exclude-features nightly --locked --rust-version --ignore-private --workspace --all-targets lockfile: runs-on: ubuntu-latest steps: @@ -76,7 +75,7 @@ jobs: toolchain: stable - uses: Swatinem/rust-cache@v2 - name: "Is lockfile updated?" - run: cargo fetch --locked + run: cargo update --workspace --locked docs: name: Docs runs-on: ubuntu-latest @@ -86,7 +85,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: stable + toolchain: "1.76" # STABLE - uses: Swatinem/rust-cache@v2 - name: Check documentation env: @@ -101,9 +100,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - # Not MSRV because its harder to jump between versions and people are - # more likely to have stable - toolchain: stable + toolchain: "1.76" # STABLE components: rustfmt - uses: Swatinem/rust-cache@v2 - name: Check formatting @@ -119,13 +116,13 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.72" # MSRV + toolchain: "1.76" # STABLE components: clippy - uses: Swatinem/rust-cache@v2 - name: Install SARIF tools - run: cargo install clippy-sarif --version 0.3.4 --locked # Held back due to msrv + run: cargo install clippy-sarif --locked - name: Install SARIF tools - run: cargo install sarif-fmt --version 0.3.4 --locked # Held back due to msrv + run: cargo install sarif-fmt --locked - name: Check run: > cargo clippy --workspace --all-targets --message-format=json -- -D warnings --allow deprecated @@ -140,3 +137,22 @@ jobs: wait-for-processing: true - name: Report status run: cargo clippy --workspace --all-targets -- -D warnings --allow deprecated + coverage: + name: Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + - uses: Swatinem/rust-cache@v2 + - name: Install cargo-tarpaulin + run: cargo install cargo-tarpaulin + - name: Gather coverage + run: cargo tarpaulin --output-dir coverage --out lcov + - name: Publish to Coveralls + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/committed.yml b/.github/workflows/committed.yml index 0462558..e7a50fb 100644 --- a/.github/workflows/committed.yml +++ b/.github/workflows/committed.yml @@ -11,6 +11,10 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: committed: name: Lint Commits diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index e5b3bd4..3d04055 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -12,6 +12,10 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: pre-commit: permissions: diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index eb7c963..f3843fc 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -12,12 +12,16 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: test: name: Test strategy: matrix: - os: ["ubuntu-latest", "windows-latest", "macos-latest"] + os: ["ubuntu-latest", "windows-latest", "macos-latest", "macos-14"] rust: ["stable", "beta"] include: - os: ubuntu-latest @@ -32,14 +36,11 @@ jobs: with: toolchain: ${{ matrix.rust }} - uses: Swatinem/rust-cache@v2 - - name: Build Debug - run: cargo test --no-run - - name: Test Debug - run: cargo test - - name: Build Release - run: cargo test --no-run --release - - name: Test Release - run: cargo test --release + - uses: taiki-e/install-action@cargo-hack + - name: Build + run: cargo test --workspace --no-run + - name: Test + run: cargo hack test --feature-powerset --exclude-features nightly --workspace latest: name: "Check latest dependencies" runs-on: ubuntu-latest @@ -51,13 +52,10 @@ jobs: with: toolchain: stable - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-hack - name: Update dependencues run: cargo update - - name: Build Debug - run: cargo test --no-run - - name: Test Debug - run: cargo test - - name: Build Release - run: cargo test --no-run --release - - name: Test Release - run: cargo test --release + - name: Build + run: cargo test --workspace --no-run + - name: Test + run: cargo hack test --feature-powerset --exclude-features nightly --workspace diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index 12f7585..8e58d9e 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -10,6 +10,10 @@ env: CARGO_TERM_COLOR: always CLICOLOR: 1 +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + jobs: spelling: name: Spell Check with Typos diff --git a/Cargo.toml b/Cargo.toml index a190812..f664d42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,79 @@ include = [ "examples/**/*" ] +[workspace.lints.rust] +rust_2018_idioms = "warn" +unreachable_pub = "warn" +unsafe_op_in_unsafe_fn = "warn" +unused_lifetimes = "warn" +unused_macro_rules = "warn" +unused_qualifications = "warn" + +[workspace.lints.clippy] +bool_assert_comparison = "allow" +branches_sharing_code = "allow" +checked_conversions = "warn" +collapsible_else_if = "allow" +create_dir = "warn" +dbg_macro = "warn" +debug_assert_with_mut_call = "warn" +doc_markdown = "warn" +empty_enum = "warn" +enum_glob_use = "warn" +exhaustive_enums = "warn" +exhaustive_structs = "warn" +exit = "warn" +expl_impl_clone_on_copy = "warn" +explicit_deref_methods = "warn" +explicit_into_iter_loop = "warn" +fallible_impl_from = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +float_cmp_const = "warn" +fn_params_excessive_bools = "warn" +from_iter_instead_of_collect = "warn" +if_same_then_else = "allow" +implicit_clone = "warn" +imprecise_flops = "warn" +inconsistent_struct_constructor = "warn" +inefficient_to_string = "warn" +infinite_loop = "warn" +invalid_upcast_comparisons = "warn" +items_after_statements = "warn" +large_digit_groups = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" +let_and_return = "allow" # sometimes good to name what you are returning +linkedlist = "warn" +lossy_float_literal = "warn" +macro_use_imports = "warn" +match_wildcard_for_single_variants = "warn" +mem_forget = "warn" +mutex_integer = "warn" +needless_continue = "warn" +needless_for_each = "warn" +negative_feature_names = "warn" +path_buf_push_overwrite = "warn" +ptr_as_ptr = "warn" +rc_mutex = "warn" +redundant_feature_names = "warn" +ref_option_ref = "warn" +rest_pat_in_fully_bound_structs = "warn" +same_functions_in_if_condition = "warn" +self_named_module_files = "warn" +semicolon_if_nothing_returned = "warn" +single_match_else = "warn" +str_to_string = "warn" +string_add = "warn" +string_add_assign = "warn" +string_lit_as_bytes = "warn" +string_to_string = "warn" +todo = "warn" +trait_duplication_in_bounds = "warn" +unwrap_used = "warn" +verbose_file_reads = "warn" +wildcard_imports = "warn" +zero_sized_map_values = "warn" [package] name = "human-panic" @@ -61,3 +134,6 @@ toml = { version = "0.8.8", default-features = false, features = ["display"] } serde = "1.0.152" os_info = "3.6.0" backtrace = "0.3.67" + +[lints] +workspace = true diff --git a/src/lib.rs b/src/lib.rs index a98544c..ff7949b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,9 +40,9 @@ //! //! Thank you kindly! -#![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![cfg_attr(feature = "nightly", deny(missing_docs))] #![cfg_attr(feature = "nightly", feature(panic_info_message))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![warn(missing_docs)] pub mod report; use report::{Method, Report}; @@ -55,6 +55,7 @@ use std::path::{Path, PathBuf}; /// A convenient metadata struct that describes a crate /// /// See [`metadata!`] +#[allow(clippy::exhaustive_structs)] pub struct Metadata { /// The crate version pub version: Cow<'static, str>, @@ -129,6 +130,7 @@ macro_rules! setup_panic { } /// Style of panic to be used +#[allow(clippy::exhaustive_enums)] #[derive(Copy, Clone, PartialEq, Eq)] pub enum PanicStyle { /// Normal panic @@ -196,7 +198,7 @@ fn write_msg>( report as an attachment.\n", match file_path { Some(fp) => format!("{}", fp.as_ref().display()), - None => "".to_string(), + None => "".to_owned(), }, name )?; @@ -219,7 +221,7 @@ fn write_msg>( } /// Utility function which will handle dumping information to disk -pub fn handle_dump(meta: &Metadata, panic_info: &PanicInfo) -> Option { +pub fn handle_dump(meta: &Metadata, panic_info: &PanicInfo<'_>) -> Option { let mut expl = String::new(); #[cfg(feature = "nightly")] @@ -230,8 +232,8 @@ pub fn handle_dump(meta: &Metadata, panic_info: &PanicInfo) -> Option { panic_info.payload().downcast_ref::<&str>(), panic_info.payload().downcast_ref::(), ) { - (Some(s), _) => Some(s.to_string()), - (_, Some(s)) => Some(s.to_string()), + (Some(s), _) => Some((*s).to_owned()), + (_, Some(s)) => Some(s.to_owned()), (None, None) => None, }; @@ -251,11 +253,15 @@ pub fn handle_dump(meta: &Metadata, panic_info: &PanicInfo) -> Option { let report = Report::new(&meta.name, &meta.version, Method::Panic, expl, cause); - match report.persist() { - Ok(f) => Some(f), - Err(_) => { - eprintln!("{}", report.serialize().unwrap()); - None - } + if let Ok(f) = report.persist() { + Some(f) + } else { + eprintln!( + "{}", + report + .serialize() + .expect("only doing toml compatible types") + ); + None } } diff --git a/src/report.rs b/src/report.rs index 4bfd091..cbed546 100644 --- a/src/report.rs +++ b/src/report.rs @@ -12,6 +12,7 @@ use std::{env, fs::File, io::Write, path::Path, path::PathBuf}; use uuid::Uuid; /// Method of failure. +#[allow(clippy::exhaustive_enums)] #[derive(Debug, Serialize, Clone, Copy)] pub enum Method { /// Failure caused by a panic. @@ -42,8 +43,6 @@ impl Report { explanation: String, cause: String, ) -> Self { - let operating_system = os_info::get().to_string(); - //We skip 3 frames from backtrace library //Then we skip 3 frames for our own library //(including closure that we set as hook) @@ -56,6 +55,8 @@ impl Report { //Padding for next lines after frame's address const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6; + let operating_system = os_info::get().to_string(); + let mut backtrace = String::new(); //Here we iterate over backtrace frames @@ -129,7 +130,7 @@ impl Report { let file_name = format!("report-{}.toml", &uuid); let file_path = Path::new(&tmp_dir).join(file_name); let mut file = File::create(&file_path)?; - let toml = self.serialize().unwrap(); + let toml = self.serialize().expect("only using toml-compatible types"); file.write_all(toml.as_bytes())?; Ok(file_path) } diff --git a/tests/custom-panic/Cargo.toml b/tests/custom-panic/Cargo.toml index 8fd8336..5db09ca 100644 --- a/tests/custom-panic/Cargo.toml +++ b/tests/custom-panic/Cargo.toml @@ -3,6 +3,7 @@ name = "custom-panic-test" version = "0.1.0" authors = ["Human Panic Authors "] edition = "2018" +publish = false [package.metadata.release] release = false diff --git a/tests/custom-panic/tests/integration.rs b/tests/custom-panic/tests/integration.rs index 7c24a4d..85a5810 100644 --- a/tests/custom-panic/tests/integration.rs +++ b/tests/custom-panic/tests/integration.rs @@ -2,24 +2,22 @@ #[cfg_attr(debug_assertions, ignore)] fn release() { snapbox::cmd::Command::new(snapbox::cmd::cargo_bin!("custom-panic-test")) - .assert() - .stderr_matches( - "\ -Well, this is embarrassing. + .assert() + .stderr_matches(snapbox::str![[r#" + Well, this is embarrassing. -custom-panic-test had a problem and crashed. To help us diagnose the problem you can send us a crash report. + custom-panic-test had a problem and crashed. To help us diagnose the problem you can send us a crash report. -We have generated a report file at \"[..].toml\". Submit an issue or email with the subject of \"custom-panic-test Crash Report\" and include the report as an attachment. + We have generated a report file at "/tmp/report-f599c209-16f1-4858-a6b4-2591a01061e2.toml". Submit an issue or email with the subject of "custom-panic-test Crash Report" and include the report as an attachment. -- Homepage: support.mycompany.com -- Authors: My Company Support "] edition = "2018" +publish = false [package.metadata.release] release = false diff --git a/tests/single-panic/tests/integration.rs b/tests/single-panic/tests/integration.rs index 31cb354..0d21bd3 100644 --- a/tests/single-panic/tests/integration.rs +++ b/tests/single-panic/tests/integration.rs @@ -2,23 +2,21 @@ #[cfg_attr(debug_assertions, ignore)] fn release() { snapbox::cmd::Command::new(snapbox::cmd::cargo_bin!("single-panic-test")) - .assert() - .stderr_matches( - "\ -Well, this is embarrassing. + .assert() + .stderr_matches(snapbox::str![[r#" + Well, this is embarrassing. -single-panic-test had a problem and crashed. To help us diagnose the problem you can send us a crash report. + single-panic-test had a problem and crashed. To help us diagnose the problem you can send us a crash report. -We have generated a report file at \"[..].toml\". Submit an issue or email with the subject of \"single-panic-test Crash Report\" and include the report as an attachment. + We have generated a report file at "/tmp/report-ee5cb7e8-1010-4824-bf57-b9726141e881.toml". Submit an issue or email with the subject of "single-panic-test Crash Report" and include the report as an attachment. -- Authors: Human Panic Authors + - Authors: Human Panic Authors -We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports. + We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports. -Thank you kindly! -", - ) - .code(101); + Thank you kindly! + "#]]) + .code(101); } #[test] @@ -26,11 +24,10 @@ Thank you kindly! fn debug() { snapbox::cmd::Command::new(snapbox::cmd::cargo_bin!("single-panic-test")) .assert() - .stderr_matches( - "\ -thread 'main' panicked at 'OMG EVERYTHING IS ON FIRE!!!', tests/single-panic/src/main.rs:7:3 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -", - ) + .stderr_matches(snapbox::str![[r#" + thread 'main' panicked at tests/single-panic/src/main.rs:7:5: + OMG EVERYTHING IS ON FIRE!!! + note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + "#]]) .code(101); }