Add clean and dirty tests

This commit is contained in:
Luc Perkins 2023-06-21 10:08:25 -07:00
parent 145fd124a4
commit e13713b477
No known key found for this signature in database
GPG Key ID: 4F102D0C16E232F2
7 changed files with 264 additions and 19 deletions

View File

@ -18,6 +18,16 @@ jobs:
- name: Check Rust formatting
run: nix develop -c check-rustfmt
rust-tests:
name: Test Rust
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@v4
- name: cargo test
run: nix develop -c cargo test
check-flake-dirty:
name: Check flake.lock test (dirty 😈)
runs-on: ubuntu-22.04
@ -27,7 +37,7 @@ jobs:
uses: DeterminateSystems/nix-installer-action@v4
- name: Check flake.lock
run: |
nix develop -c cargo run -- ./flake.dirty.lock
nix develop -c cargo run -- ./tests/flake.dirty.0.lock
check-flake-clean:
name: Check flake.lock test (clean 👼)
@ -50,4 +60,4 @@ jobs:
uses: DeterminateSystems/nix-installer-action@v2
- name: Check flake.lock
run: |
nix develop -c cargo run -- ./flake.dirty.lock --fail-mode
nix develop -c cargo run -- --fail-mode ./tests/flake.dirty.0.lock

2
Cargo.lock generated
View File

@ -204,7 +204,7 @@ dependencies = [
[[package]]
name = "flake-checker"
version = "0.1.6"
version = "0.1.7"
dependencies = [
"chrono",
"clap",

View File

@ -1,8 +1,11 @@
#![allow(dead_code)]
use std::collections::HashMap;
use std::fmt;
use std::fs::read_to_string;
use std::path::PathBuf;
use crate::issue::{Issue, IssueKind};
use crate::FlakeCheckerError;
use chrono::{Duration, Utc};
use serde::de::{self, Deserializer, MapAccess, Visitor};
@ -24,18 +27,29 @@ pub const ALLOWED_REFS: &[&str] = &[
];
pub const MAX_DAYS: i64 = 30;
pub fn check_flake_lock(
flake_lock: &FlakeLock,
check_supported: bool,
check_outdated: bool,
check_owner: bool,
) -> Vec<Issue> {
pub struct FlakeCheckConfig {
pub check_supported: bool,
pub check_outdated: bool,
pub check_owner: bool,
}
impl Default for FlakeCheckConfig {
fn default() -> Self {
Self {
check_supported: true,
check_outdated: true,
check_owner: true,
}
}
}
pub fn check_flake_lock(flake_lock: &FlakeLock, config: &FlakeCheckConfig) -> Vec<Issue> {
let mut issues = vec![];
for (name, dep) in flake_lock.nixpkgs_deps() {
if let Node::Repo(repo) = dep {
// Check if not explicitly supported
if check_supported {
if config.check_supported {
if let Some(ref git_ref) = repo.original.git_ref {
if !ALLOWED_REFS.contains(&git_ref.as_str()) {
issues.push(Issue {
@ -51,7 +65,7 @@ pub fn check_flake_lock(
}
// Check if outdated
if check_outdated {
if config.check_outdated {
let now_timestamp = Utc::now().timestamp();
let diff = now_timestamp - repo.locked.last_modified;
let num_days_old = Duration::seconds(diff).num_days();
@ -69,7 +83,7 @@ pub fn check_flake_lock(
}
// Check that the GitHub owner is NixOS
if check_owner {
if config.check_owner {
let owner = repo.original.owner;
if owner.to_lowercase() != "nixos" {
issues.push(Issue {
@ -94,6 +108,14 @@ pub struct FlakeLock {
version: usize,
}
impl FlakeLock {
pub fn new(path: &PathBuf) -> Result<Self, FlakeCheckerError> {
let flake_lock_file = read_to_string(path)?;
let flake_lock: FlakeLock = serde_json::from_str(&flake_lock_file)?;
Ok(flake_lock)
}
}
impl<'de> Deserialize<'de> for FlakeLock {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@ -252,3 +274,58 @@ struct RepoOriginal {
#[serde(alias = "ref")]
git_ref: Option<String>,
}
#[cfg(test)]
mod test {
use crate::{check_flake_lock, FlakeCheckConfig, FlakeLock, issue::{Issue, IssueKind}};
use serde_json::json;
#[test]
fn test_clean_flake_locks() {
for n in vec![0] {
let path = format!("tests/flake.clean.{n}.lock");
let flake_lock = FlakeLock::new(&path.into()).expect("couldn't create flake.lock");
let config = FlakeCheckConfig {
check_outdated: false,
..Default::default()
};
let issues = check_flake_lock(&flake_lock, &config);
assert!(issues.is_empty());
}
}
#[test]
fn test_dirty_flake_locks() {
let cases: Vec<(&str, Vec<Issue>)> = vec![
("flake.dirty.0.lock", vec![
Issue {
dependency: String::from("nixpkgs"),
kind: IssueKind::Disallowed,
details: json!({
"input": String::from("nixpkgs"),
"ref": String::from("this-should-fail"),
}),
},
Issue {
dependency: String::from("nixpkgs"),
kind: IssueKind::NonUpstream,
details: json!({
"input": String::from("nixpkgs"),
"owner": String::from("bitcoin-miner-org"),
}),
},
]),
];
for (file, expected_issues) in cases {
let path = format!("tests/{file}");
let flake_lock = FlakeLock::new(&path.into()).expect("couldn't create flake.lock");
let config = FlakeCheckConfig {
check_outdated: false,
..Default::default()
};
let issues = check_flake_lock(&flake_lock, &config);
assert_eq!(issues, expected_issues);
}
}
}

View File

@ -1,13 +1,13 @@
use serde::Serialize;
#[derive(Clone, Serialize)]
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct Issue {
pub dependency: String,
pub kind: IssueKind,
pub details: serde_json::Value,
}
#[derive(Clone, PartialEq, Serialize)]
#[derive(Clone, Debug, PartialEq, Serialize)]
pub enum IssueKind {
#[serde(rename = "disallowed")]
Disallowed,

View File

@ -5,10 +5,9 @@ mod summary;
pub mod telemetry;
pub use error::FlakeCheckerError;
pub use flake::{check_flake_lock, FlakeLock};
pub use flake::{check_flake_lock, FlakeCheckConfig, FlakeLock};
pub use summary::Summary;
use std::fs::read_to_string;
use std::path::PathBuf;
use std::process::ExitCode;
@ -86,10 +85,15 @@ fn main() -> Result<ExitCode, FlakeCheckerError> {
}
}
let flake_lock_file = read_to_string(flake_lock_path)?;
let flake_lock: FlakeLock = serde_json::from_str(&flake_lock_file)?;
let flake_lock = FlakeLock::new(&flake_lock_path)?;
let issues = check_flake_lock(&flake_lock, check_supported, check_outdated, check_owner);
let flake_check_config = FlakeCheckConfig {
check_supported,
check_outdated,
check_owner,
};
let issues = check_flake_lock(&flake_lock, &flake_check_config);
if !no_telemetry {
telemetry::TelemetryReport::make_and_send(&issues);

154
tests/flake.clean.0.lock Normal file
View File

@ -0,0 +1,154 @@
{
"nodes": {
"crane": {
"inputs": {
"flake-compat": [
"flake-compat"
],
"flake-utils": [
"flake-utils"
],
"nixpkgs": [
"nixpkgs"
],
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1684468982,
"narHash": "sha256-EoC1N5sFdmjuAP3UOkyQujSOT6EdcXTnRw8hPjJkEgc=",
"owner": "ipetkov",
"repo": "crane",
"rev": "99de890b6ef4b4aab031582125b6056b792a4a30",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
"id": "flake-utils",
"type": "indirect"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1686960236,
"narHash": "sha256-AYCC9rXNLpUWzD9hm+askOfpliLEC9kwAo7ITJc4HIw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "04af42f3b31dba0ef742d254456dc4c14eedac86",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"crane": "crane",
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay_2"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": [
"crane",
"flake-utils"
],
"nixpkgs": [
"crane",
"nixpkgs"
]
},
"locked": {
"lastModified": 1683080331,
"narHash": "sha256-nGDvJ1DAxZIwdn6ww8IFwzoHb2rqBP4wv/65Wt5vflk=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "d59c3fa0cba8336e115b376c2d9e91053aa59e56",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"rust-overlay_2": {
"inputs": {
"flake-utils": [
"flake-utils"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1684808436,
"narHash": "sha256-WG5LgB1+Oguj4H4Bpqr5GoLSc382LyGlaToiOw5xhwA=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "a227d4571dd1f948138a40ea8b0d0c413eefb44b",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}