Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

env:
CARGO_TERM_COLOR: always

jobs:
check:
name: Check (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]

steps:
- uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- name: Cache cargo registry and build
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-

- name: Check formatting
run: cargo fmt --check

- name: Clippy
run: cargo clippy -- -D warnings

- name: Run tests
run: cargo test
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ version = "0.1.0"
edition = "2024"
description = "CLI for arborist-metrics: cognitive/cyclomatic complexity and SLOC metrics"
license = "MIT OR Apache-2.0"
repository = "https://github.com/StrangeDaysTech/arborist-cli"
homepage = "https://github.com/StrangeDaysTech/arborist-cli"
readme = "README.md"
keywords = ["complexity", "metrics", "cognitive", "cyclomatic", "cli"]
categories = ["command-line-utilities", "development-tools"]
exclude = [".devtrail/", ".github/", ".claude/", ".specify/", "specs/", "tests/fixtures/"]

[dependencies]
arborist-metrics = { version = "0.1", features = ["all"] }
Expand Down
21 changes: 17 additions & 4 deletions tests/cli/directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ fn directory_gitignore_excludes() {

assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(!stdout.contains("generated"), "gitignored file should be excluded");
assert!(stdout.contains("compute"), "non-ignored files should be included");
assert!(
!stdout.contains("generated"),
"gitignored file should be excluded"
);
assert!(
stdout.contains("compute"),
"non-ignored files should be included"
);
}

/// T029: verify `--languages rust` analyzes only .rs files, skips .py
Expand All @@ -44,7 +50,10 @@ fn directory_language_filter() {
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.contains("Rust"), "should include Rust files");
assert!(!stdout.contains("Python"), "should not include Python files");
assert!(
!stdout.contains("Python"),
"should not include Python files"
);
}

/// T030: verify directory with no recognized files prints info and exits 0
Expand All @@ -56,7 +65,11 @@ fn directory_no_recognized_files() {
// Let's just test that empty results are handled gracefully.
// We'll use a path filter that excludes everything.
cmd()
.args(["tests/fixtures/nested_project/", "--languages", "javascript"])
.args([
"tests/fixtures/nested_project/",
"--languages",
"javascript",
])
.assert()
.success();
}
22 changes: 14 additions & 8 deletions tests/cli/filtering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,14 @@ fn threshold_exceeds_only() {
.unwrap();

let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.contains("complex_function"), "exceeding function should appear");
assert!(!stdout.contains("simple_function"), "non-exceeding function should be filtered");
assert!(
stdout.contains("complex_function"),
"exceeding function should appear"
);
assert!(
!stdout.contains("simple_function"),
"non-exceeding function should be filtered"
);
assert!(
!stdout.contains("moderate_function"),
"non-exceeding function should be filtered"
Expand Down Expand Up @@ -68,11 +74,7 @@ fn no_methods_flag() {
#[test]
fn sort_cognitive_descending() {
let output = cmd()
.args([
"tests/fixtures/nested_project/src/",
"--sort",
"cognitive",
])
.args(["tests/fixtures/nested_project/src/", "--sort", "cognitive"])
.output()
.unwrap();

Expand Down Expand Up @@ -101,7 +103,11 @@ fn sort_name_ascending() {
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
let compute_pos = stdout.find("compute").unwrap();
let main_pos = stdout.find(" main").unwrap_or_else(|| stdout.find("\nmain").unwrap_or_else(|| stdout.find("main").unwrap()));
let main_pos = stdout.find(" main").unwrap_or_else(|| {
stdout
.find("\nmain")
.unwrap_or_else(|| stdout.find("main").unwrap())
});
let transform_pos = stdout.find("transform").unwrap();
assert!(
compute_pos < main_pos && main_pos < transform_pos,
Expand Down
5 changes: 4 additions & 1 deletion tests/cli/output_formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ fn csv_directory_multiple_rows() {
let stdout = String::from_utf8(output.stdout).unwrap();
let lines: Vec<&str> = stdout.lines().collect();
// header + at least 3 functions (compute, transform, main)
assert!(lines.len() >= 4, "expected header + 3+ data rows, got {lines:?}");
assert!(
lines.len() >= 4,
"expected header + 3+ data rows, got {lines:?}"
);
}

/// T058: verify CSV with no-function file produces header only
Expand Down
Loading