Skip to content

Commit 8f77aff

Browse files
committed
ci: Add GitHub Actions workflow and fix lints
- Add CI workflow for test, lint, and docs - Configure clippy pedantic lints with appropriate allows - Fix unused import in discovery.rs - Run cargo fmt for consistent formatting
1 parent 6a553b9 commit 8f77aff

File tree

9 files changed

+146
-18
lines changed

9 files changed

+146
-18
lines changed

.github/workflows/ci.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
env:
10+
CARGO_TERM_COLOR: always
11+
RUST_BACKTRACE: 1
12+
13+
jobs:
14+
test:
15+
name: Test (${{ matrix.os }})
16+
runs-on: ${{ matrix.os }}
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
os: [ubuntu-latest, macos-latest, windows-latest]
21+
22+
steps:
23+
- uses: actions/checkout@v4
24+
25+
- name: Install Rust
26+
uses: dtolnay/rust-action@stable
27+
28+
- name: Cache cargo
29+
uses: actions/cache@v4
30+
with:
31+
path: |
32+
~/.cargo/bin/
33+
~/.cargo/registry/index/
34+
~/.cargo/registry/cache/
35+
~/.cargo/git/db/
36+
target/
37+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
38+
39+
- name: Build
40+
run: cargo build --all-targets
41+
42+
- name: Run tests
43+
run: cargo test --all
44+
45+
lint:
46+
name: Lint
47+
runs-on: ubuntu-latest
48+
steps:
49+
- uses: actions/checkout@v4
50+
51+
- name: Install Rust
52+
uses: dtolnay/rust-action@stable
53+
with:
54+
components: rustfmt, clippy
55+
56+
- name: Check formatting
57+
run: cargo fmt --all -- --check
58+
59+
- name: Clippy
60+
run: cargo clippy --all-targets -- -D warnings
61+
62+
docs:
63+
name: Documentation
64+
runs-on: ubuntu-latest
65+
steps:
66+
- uses: actions/checkout@v4
67+
68+
- name: Install Rust
69+
uses: dtolnay/rust-action@stable
70+
71+
- name: Build docs
72+
run: cargo doc --no-deps
73+
env:
74+
RUSTDOCFLAGS: -D warnings

Cargo.toml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,37 @@ tempfile.workspace = true
5454
unsafe_code = "warn"
5555

5656
[lints.clippy]
57-
all = "warn"
58-
pedantic = "warn"
57+
all = { level = "warn", priority = -1 }
58+
pedantic = { level = "warn", priority = -1 }
59+
# Allow common false positives from pedantic
60+
missing_errors_doc = "allow"
61+
missing_panics_doc = "allow"
62+
must_use_candidate = "allow"
63+
items_after_statements = "allow"
64+
unreadable_literal = "allow"
65+
module_name_repetitions = "allow"
66+
doc_markdown = "allow"
67+
# Allow cast issues in stats code
68+
cast_precision_loss = "allow"
69+
cast_possible_truncation = "allow"
70+
cast_sign_loss = "allow"
71+
cast_lossless = "allow"
72+
# Allow these style choices
73+
if_not_else = "allow"
74+
redundant_closure_for_method_calls = "allow"
75+
option_if_let_else = "allow"
76+
map_unwrap_or = "allow"
77+
trivially_copy_pass_by_ref = "allow"
78+
match_same_arms = "allow"
79+
needless_raw_string_hashes = "allow"
80+
unused_self = "allow"
81+
uninlined_format_args = "allow"
82+
ref_option = "allow"
83+
unnecessary_map_or = "allow"
84+
collapsible_if = "allow"
85+
needless_pass_by_value = "allow"
86+
too_many_lines = "allow"
87+
struct_excessive_bools = "allow"
88+
cloned_instead_of_copied = "allow"
89+
stable_sort_primitive = "allow"
90+
manual_midpoint = "allow"

src/corpus/checksum.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub fn compute_checksum(path: &Path) -> Result<String> {
3535

3636
/// Compute a checksum for in-memory data.
3737
#[must_use]
38+
#[allow(dead_code)] // Used in tests, may be useful for API consumers
3839
pub fn compute_checksum_bytes(data: &[u8]) -> String {
3940
let mut hash: u64 = 0xcbf29ce484222325;
4041
const FNV_PRIME: u64 = 0x100000001b3;

src/corpus/discovery.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,6 @@ fn infer_categories(corpus: &mut Corpus) {
247247

248248
#[cfg(test)]
249249
mod tests {
250-
use super::*;
251-
252250
#[test]
253251
fn test_png_dimensions() {
254252
// Minimal valid PNG header with 100x50 dimensions

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,6 @@ pub use eval::{
5454
pub use import::{CsvImporter, CsvSchema, ExternalResult};
5555
pub use metrics::{MetricConfig, MetricResult, PerceptionLevel};
5656
pub use stats::{
57-
generate_svg, ChartConfig, ChartPoint, ChartSeries, ParetoFront, RDPoint, Summary,
57+
ChartConfig, ChartPoint, ChartSeries, ParetoFront, RDPoint, Summary, generate_svg,
5858
};
5959
pub use viewing::ViewingCondition;

src/metrics/butteraugli.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//! - < 5.0: Noticeable difference
1111
//! - >= 5.0: Degraded
1212
13-
use butteraugli_oxide::{compute_butteraugli, ButteraugliParams};
13+
use butteraugli_oxide::{ButteraugliParams, compute_butteraugli};
1414

1515
use crate::error::{Error, Result};
1616

@@ -128,7 +128,10 @@ mod tests {
128128
let data: Vec<u8> = (0..100 * 100 * 3).map(|i| (i % 256) as u8).collect();
129129
let score = calculate_butteraugli(&data, &data, 100, 100).unwrap();
130130
// Identical images should have score close to 0
131-
assert!(score < 0.01, "Identical images should have score ~0, got {score}");
131+
assert!(
132+
score < 0.01,
133+
"Identical images should have score ~0, got {score}"
134+
);
132135
}
133136

134137
#[test]
@@ -137,7 +140,10 @@ mod tests {
137140
let test_data: Vec<u8> = vec![200u8; 100 * 100 * 3];
138141
let score = calculate_butteraugli(&ref_data, &test_data, 100, 100).unwrap();
139142
// Very different images should have high score
140-
assert!(score > 1.0, "Very different images should have high score, got {score}");
143+
assert!(
144+
score > 1.0,
145+
"Very different images should have high score, got {score}"
146+
);
141147
}
142148

143149
#[test]
@@ -152,6 +158,9 @@ mod tests {
152158
fn test_custom_intensity() {
153159
let data: Vec<u8> = (0..100 * 100 * 3).map(|i| (i % 256) as u8).collect();
154160
let score = calculate_butteraugli_with_intensity(&data, &data, 100, 100, 250.0).unwrap();
155-
assert!(score < 0.01, "Identical images should have score ~0 at any intensity");
161+
assert!(
162+
score < 0.01,
163+
"Identical images should have score ~0 at any intensity"
164+
);
156165
}
157166
}

src/metrics/ssimulacra2.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//! - <= 50: Degraded
1313
1414
use ssimulacra2::{
15-
compute_frame_ssimulacra2, ColorPrimaries, Rgb as Ssim2Rgb, TransferCharacteristic,
15+
ColorPrimaries, Rgb as Ssim2Rgb, TransferCharacteristic, compute_frame_ssimulacra2,
1616
};
1717

1818
use crate::error::{Error, Result};
@@ -120,7 +120,10 @@ mod tests {
120120
let data: Vec<u8> = (0..100 * 100 * 3).map(|i| (i % 256) as u8).collect();
121121
let score = calculate_ssimulacra2(&data, &data, 100, 100).unwrap();
122122
// Identical images should have score close to 100
123-
assert!(score > 99.0, "Identical images should have score ~100, got {score}");
123+
assert!(
124+
score > 99.0,
125+
"Identical images should have score ~100, got {score}"
126+
);
124127
}
125128

126129
#[test]
@@ -129,7 +132,10 @@ mod tests {
129132
let test_data: Vec<u8> = vec![200u8; 100 * 100 * 3];
130133
let score = calculate_ssimulacra2(&ref_data, &test_data, 100, 100).unwrap();
131134
// Very different images should have low score
132-
assert!(score < 80.0, "Very different images should have low score, got {score}");
135+
assert!(
136+
score < 80.0,
137+
"Very different images should have low score, got {score}"
138+
);
133139
}
134140

135141
#[test]

src/stats/chart.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,14 @@ pub fn generate_svg(series: &[ChartSeries], config: &ChartConfig) -> String {
132132
return String::new();
133133
}
134134

135-
let all_x: Vec<f64> = non_empty.iter().flat_map(|s| s.points.iter().map(|p| p.x)).collect();
136-
let all_y: Vec<f64> = non_empty.iter().flat_map(|s| s.points.iter().map(|p| p.y)).collect();
135+
let all_x: Vec<f64> = non_empty
136+
.iter()
137+
.flat_map(|s| s.points.iter().map(|p| p.x))
138+
.collect();
139+
let all_y: Vec<f64> = non_empty
140+
.iter()
141+
.flat_map(|s| s.points.iter().map(|p| p.y))
142+
.collect();
137143

138144
let (min_x, max_x) = bounds_with_padding(&all_x, 0.05);
139145
let (min_y, max_y) = bounds_with_padding(&all_y, 0.05);
@@ -155,8 +161,7 @@ pub fn generate_svg(series: &[ChartSeries], config: &ChartConfig) -> String {
155161
if config.lower_is_better {
156162
f64::from(margin_top) + (v - min_y) / (max_y - min_y) * f64::from(plot_height)
157163
} else {
158-
f64::from(margin_top)
159-
+ (1.0 - (v - min_y) / (max_y - min_y)) * f64::from(plot_height)
164+
f64::from(margin_top) + (1.0 - (v - min_y) / (max_y - min_y)) * f64::from(plot_height)
160165
}
161166
};
162167

@@ -251,7 +256,10 @@ pub fn generate_svg(series: &[ChartSeries], config: &ChartConfig) -> String {
251256
let _ = writeln!(
252257
svg,
253258
r#"<line x1="{}" y1="{}" x2="{}" y2="{}" class="axis"/>"#,
254-
margin_left, margin_top, margin_left, height - margin_bottom
259+
margin_left,
260+
margin_top,
261+
margin_left,
262+
height - margin_bottom
255263
);
256264

257265
// Tick labels

src/stats/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
pub mod chart;
77
mod pareto;
88

9-
pub use chart::{generate_svg, ChartConfig, ChartPoint, ChartSeries};
9+
pub use chart::{ChartConfig, ChartPoint, ChartSeries, generate_svg};
1010
pub use pareto::{ParetoFront, RDPoint};
1111

1212
use serde::{Deserialize, Serialize};

0 commit comments

Comments
 (0)