mirror of
https://github.com/DeterminateSystems/flake-checker.git
synced 2024-10-05 18:27:42 +03:00
Provide support for tarball nodes
This commit is contained in:
parent
0d16f33018
commit
aa0f8feb98
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -858,7 +858,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parse-flake-lock"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -60,7 +60,7 @@ You can apply a CEL condition to your flake using the `--condition` flag.
|
||||
Here's an example:
|
||||
|
||||
```shell
|
||||
flake-checker --condition "numDaysOld < 365"
|
||||
flake-checker --condition "has(numDaysOld) && numDaysOld < 365"
|
||||
```
|
||||
|
||||
This would check that each Nixpkgs input in your `flake.lock` is less than 365 days old.
|
||||
@ -76,14 +76,16 @@ Variable | Description
|
||||
We recommend a condition *at least* this stringent:
|
||||
|
||||
```ruby
|
||||
supportedRefs.contains(gitRef) && numDaysOld < 30 && owner == 'NixOS'
|
||||
supportedRefs.contains(gitRef) && (has(numDaysOld) && numDaysOld < 30) && owner == 'NixOS'
|
||||
```
|
||||
|
||||
Note that not all Nixpkgs inputs have a `numDaysOld` field, so make sure to ensure that that field exists when checking for the number of days.
|
||||
|
||||
Here are some other example conditions:
|
||||
|
||||
```ruby
|
||||
# Updated in the last two weeks
|
||||
supportedRefs.contains(gitRef) && numDaysOld < 14 && owner == 'NixOS'
|
||||
supportedRefs.contains(gitRef) && (has(numDaysOld) && numDaysOld < 14) && owner == 'NixOS'
|
||||
|
||||
# Check for most recent stable Nixpkgs
|
||||
gitRef.contains("24.05")
|
||||
|
37
flake.lock
37
flake.lock
@ -14,11 +14,12 @@
|
||||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"narHash": "sha256-ASliYUzlN/aTGDZ2d0FIqxq5fiz+Cwk0q2rYXgy4pB0=",
|
||||
"rev": "8cb0282cb7c7b5ad7ce1c47d48f647836f8924a0",
|
||||
"revCount": 432,
|
||||
"lastModified": 1697588719,
|
||||
"narHash": "sha256-n9ALgm3S+ygpzjesBkB9qutEtM4dtIkhn8WnstCPOew=",
|
||||
"rev": "da6b58e270d339a78a6e95728012ec2eea879612",
|
||||
"revCount": 440,
|
||||
"type": "tarball",
|
||||
"url": "https://api.flakehub.com/f/pinned/ipetkov/crane/0.14.2/018b3503-625a-71c8-96ff-c86e61bd12f7/source.tar.gz"
|
||||
"url": "https://api.flakehub.com/f/pinned/ipetkov/crane/0.14.3/018b402e-8337-76a6-9764-1748a79a54fd/source.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
@ -27,6 +28,7 @@
|
||||
},
|
||||
"flake-compat": {
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"revCount": 57,
|
||||
@ -43,11 +45,11 @@
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1694529238,
|
||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -57,16 +59,16 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1704290814,
|
||||
"narHash": "sha256-LWvKHp7kGxk/GEtlrGYV68qIvPHkU9iToomNFGagixU=",
|
||||
"rev": "70bdadeb94ffc8806c0570eb5c2695ad29f0e421",
|
||||
"revCount": 492897,
|
||||
"lastModified": 1717952948,
|
||||
"narHash": "sha256-mJi4/gjiwQlSaxjA6AusXBN/6rQRaPCycR7bd8fydnQ=",
|
||||
"rev": "2819fffa7fa42156680f0d282c60d81e8fb185b7",
|
||||
"revCount": 631440,
|
||||
"type": "tarball",
|
||||
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2305.492897%2Brev-70bdadeb94ffc8806c0570eb5c2695ad29f0e421/018ce318-b896-7d27-b495-cc2cdb39d680/source.tar.gz"
|
||||
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2405.631440%2Brev-2819fffa7fa42156680f0d282c60d81e8fb185b7/0190034c-678d-7039-b45c-fa38168f2500/source.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.2305.%2A.tar.gz"
|
||||
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.2405.%2A.tar.gz"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
@ -105,19 +107,16 @@
|
||||
},
|
||||
"rust-overlay_2": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1697422411,
|
||||
"narHash": "sha256-eCj20wEwATLm7Bd/+/wOIdbqq9jgvS6ZxMrxujX2DxU=",
|
||||
"lastModified": 1718681902,
|
||||
"narHash": "sha256-E/T7Ge6ayEQe7FVKMJqDBoHyLhRhjc6u9CmU8MyYfy0=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "056256f2fcf3c5a652dbc3edba9ec1a956d41f56",
|
||||
"rev": "16c8ad83297c278eebe740dea5491c1708960dd1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2305.*.tar.gz";
|
||||
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2405.*.tar.gz";
|
||||
|
||||
|
||||
rust-overlay = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "parse-flake-lock"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
@ -375,6 +375,9 @@ pub struct TarballNode {
|
||||
/// Information about the tarball input that's "locked" because it's supplied by Nix.
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct TarballLocked {
|
||||
/// The timestamp for when the input was last modified.
|
||||
#[serde(alias = "lastModified")]
|
||||
pub last_modified: Option<i64>,
|
||||
/// The NAR hash of the input.
|
||||
#[serde(alias = "narHash")]
|
||||
pub nar_hash: String,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use cel_interpreter::{Context, Program, Value};
|
||||
use parse_flake_lock::{FlakeLock, Node, RepoNode};
|
||||
use parse_flake_lock::{FlakeLock, Node};
|
||||
|
||||
use crate::{
|
||||
error::FlakeCheckerError,
|
||||
@ -19,61 +19,68 @@ pub(super) fn evaluate_condition(
|
||||
allowed_refs: Vec<String>,
|
||||
) -> Result<Vec<Issue>, FlakeCheckerError> {
|
||||
let mut issues: Vec<Issue> = vec![];
|
||||
|
||||
let allowed_refs: Value = Value::from(
|
||||
allowed_refs
|
||||
.iter()
|
||||
.map(|r| Value::from(r.to_string()))
|
||||
.collect::<Vec<Value>>(),
|
||||
);
|
||||
let mut ctx = Context::default();
|
||||
ctx.add_variable_from_value(KEY_SUPPORTED_REFS, allowed_refs.clone());
|
||||
|
||||
let deps = nixpkgs_deps(flake_lock, nixpkgs_keys)?;
|
||||
|
||||
for (name, dep) in deps {
|
||||
if let Node::Repo(repo) = dep {
|
||||
let mut ctx = Context::default();
|
||||
ctx.add_variable_from_value(KEY_SUPPORTED_REFS, allowed_refs.clone());
|
||||
for (k, v) in nixpkgs_cel_values(repo) {
|
||||
ctx.add_variable_from_value(k, v);
|
||||
}
|
||||
for (name, node) in deps {
|
||||
println!("name: {name}");
|
||||
|
||||
match Program::compile(condition)?.execute(&ctx) {
|
||||
Ok(result) => match result {
|
||||
Value::Bool(b) if !b => {
|
||||
issues.push(Issue {
|
||||
input: name.clone(),
|
||||
kind: IssueKind::Violation,
|
||||
});
|
||||
}
|
||||
Value::Bool(b) if b => continue,
|
||||
result => {
|
||||
return Err(FlakeCheckerError::NonBooleanCondition(
|
||||
result.type_of().to_string(),
|
||||
))
|
||||
}
|
||||
},
|
||||
Err(e) => return Err(FlakeCheckerError::CelExecution(e)),
|
||||
}
|
||||
let (git_ref, last_modified, owner) = match node {
|
||||
Node::Repo(repo) => (
|
||||
repo.original.git_ref,
|
||||
Some(repo.locked.last_modified),
|
||||
Some(repo.original.owner),
|
||||
),
|
||||
Node::Tarball(tarball) => (None, tarball.locked.last_modified, None),
|
||||
_ => (None, None, None),
|
||||
};
|
||||
|
||||
add_cel_variables(&mut ctx, git_ref, last_modified, owner);
|
||||
|
||||
match Program::compile(condition)?.execute(&ctx) {
|
||||
Ok(result) => match result {
|
||||
Value::Bool(b) if !b => {
|
||||
issues.push(Issue {
|
||||
input: name.clone(),
|
||||
kind: IssueKind::Violation,
|
||||
});
|
||||
}
|
||||
Value::Bool(b) if b => continue,
|
||||
result => {
|
||||
return Err(FlakeCheckerError::NonBooleanCondition(
|
||||
result.type_of().to_string(),
|
||||
))
|
||||
}
|
||||
},
|
||||
Err(e) => return Err(FlakeCheckerError::CelExecution(e)),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(issues)
|
||||
}
|
||||
|
||||
fn nixpkgs_cel_values(repo: Box<RepoNode>) -> Vec<(&'static str, Value)> {
|
||||
vec![
|
||||
(
|
||||
KEY_GIT_REF,
|
||||
repo.original
|
||||
.git_ref
|
||||
.map_or_else(|| Value::Null, Value::from),
|
||||
),
|
||||
(
|
||||
KEY_NUM_DAYS_OLD,
|
||||
Value::from(num_days_old(repo.locked.last_modified)),
|
||||
),
|
||||
(KEY_OWNER, Value::from(repo.original.owner)),
|
||||
]
|
||||
fn add_cel_variables(
|
||||
ctx: &mut Context,
|
||||
git_ref: Option<String>,
|
||||
last_modified: Option<i64>,
|
||||
owner: Option<String>,
|
||||
) {
|
||||
ctx.add_variable_from_value(KEY_GIT_REF, value_or_empty_string(git_ref));
|
||||
ctx.add_variable_from_value(
|
||||
KEY_NUM_DAYS_OLD,
|
||||
value_or_zero(last_modified.map(|d| num_days_old(d))),
|
||||
);
|
||||
ctx.add_variable_from_value(KEY_OWNER, value_or_empty_string(owner));
|
||||
}
|
||||
|
||||
fn value_or_empty_string(value: Option<String>) -> Value {
|
||||
Value::from(value.unwrap_or(String::from("")))
|
||||
}
|
||||
|
||||
fn value_or_zero(value: Option<i64>) -> Value {
|
||||
Value::from(value.unwrap_or(0))
|
||||
}
|
||||
|
||||
pub(super) fn vet_condition(condition: &str) -> Result<(), FlakeCheckerError> {
|
||||
|
38
src/flake.rs
38
src/flake.rs
@ -85,25 +85,36 @@ pub(crate) fn check_flake_lock(
|
||||
|
||||
let deps = nixpkgs_deps(flake_lock, &config.nixpkgs_keys)?;
|
||||
|
||||
for (name, dep) in deps {
|
||||
if let Node::Repo(repo) = dep {
|
||||
for (name, node) in deps {
|
||||
let (git_ref, last_modified, owner) = match node {
|
||||
Node::Repo(repo) => (
|
||||
repo.original.git_ref,
|
||||
Some(repo.locked.last_modified),
|
||||
Some(repo.original.owner),
|
||||
),
|
||||
Node::Tarball(tarball) => (None, tarball.locked.last_modified, None),
|
||||
_ => (None, None, None),
|
||||
};
|
||||
|
||||
// Check if not explicitly supported
|
||||
if let Some(git_ref) = git_ref {
|
||||
// Check if not explicitly supported
|
||||
if config.check_supported {
|
||||
if let Some(ref git_ref) = repo.original.git_ref {
|
||||
if !allowed_refs.contains(git_ref) {
|
||||
issues.push(Issue {
|
||||
input: name.clone(),
|
||||
kind: IssueKind::Disallowed(Disallowed {
|
||||
reference: git_ref.to_string(),
|
||||
}),
|
||||
});
|
||||
}
|
||||
if !allowed_refs.contains(&git_ref) {
|
||||
issues.push(Issue {
|
||||
input: name.clone(),
|
||||
kind: IssueKind::Disallowed(Disallowed {
|
||||
reference: git_ref.to_string(),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(last_modified) = last_modified {
|
||||
// Check if outdated
|
||||
if config.check_outdated {
|
||||
let num_days_old = num_days_old(repo.locked.last_modified);
|
||||
let num_days_old = num_days_old(last_modified);
|
||||
|
||||
if num_days_old > MAX_DAYS {
|
||||
issues.push(Issue {
|
||||
@ -112,10 +123,11 @@ pub(crate) fn check_flake_lock(
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(owner) = owner {
|
||||
// Check that the GitHub owner is NixOS
|
||||
if config.check_owner {
|
||||
let owner = repo.original.owner;
|
||||
if owner.to_lowercase() != "nixos" {
|
||||
issues.push(Issue {
|
||||
input: name.clone(),
|
||||
|
Loading…
Reference in New Issue
Block a user