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]]
|
[[package]]
|
||||||
name = "parse-flake-lock"
|
name = "parse-flake-lock"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -60,7 +60,7 @@ You can apply a CEL condition to your flake using the `--condition` flag.
|
|||||||
Here's an example:
|
Here's an example:
|
||||||
|
|
||||||
```shell
|
```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.
|
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:
|
We recommend a condition *at least* this stringent:
|
||||||
|
|
||||||
```ruby
|
```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:
|
Here are some other example conditions:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# Updated in the last two weeks
|
# 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
|
# Check for most recent stable Nixpkgs
|
||||||
gitRef.contains("24.05")
|
gitRef.contains("24.05")
|
||||||
|
37
flake.lock
37
flake.lock
@ -14,11 +14,12 @@
|
|||||||
"rust-overlay": "rust-overlay"
|
"rust-overlay": "rust-overlay"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"narHash": "sha256-ASliYUzlN/aTGDZ2d0FIqxq5fiz+Cwk0q2rYXgy4pB0=",
|
"lastModified": 1697588719,
|
||||||
"rev": "8cb0282cb7c7b5ad7ce1c47d48f647836f8924a0",
|
"narHash": "sha256-n9ALgm3S+ygpzjesBkB9qutEtM4dtIkhn8WnstCPOew=",
|
||||||
"revCount": 432,
|
"rev": "da6b58e270d339a78a6e95728012ec2eea879612",
|
||||||
|
"revCount": 440,
|
||||||
"type": "tarball",
|
"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": {
|
"original": {
|
||||||
"type": "tarball",
|
"type": "tarball",
|
||||||
@ -27,6 +28,7 @@
|
|||||||
},
|
},
|
||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"locked": {
|
"locked": {
|
||||||
|
"lastModified": 1696426674,
|
||||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||||
"revCount": 57,
|
"revCount": 57,
|
||||||
@ -43,11 +45,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1694529238,
|
"lastModified": 1710146030,
|
||||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -57,16 +59,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1704290814,
|
"lastModified": 1717952948,
|
||||||
"narHash": "sha256-LWvKHp7kGxk/GEtlrGYV68qIvPHkU9iToomNFGagixU=",
|
"narHash": "sha256-mJi4/gjiwQlSaxjA6AusXBN/6rQRaPCycR7bd8fydnQ=",
|
||||||
"rev": "70bdadeb94ffc8806c0570eb5c2695ad29f0e421",
|
"rev": "2819fffa7fa42156680f0d282c60d81e8fb185b7",
|
||||||
"revCount": 492897,
|
"revCount": 631440,
|
||||||
"type": "tarball",
|
"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": {
|
"original": {
|
||||||
"type": "tarball",
|
"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": {
|
"root": {
|
||||||
@ -105,19 +107,16 @@
|
|||||||
},
|
},
|
||||||
"rust-overlay_2": {
|
"rust-overlay_2": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": [
|
|
||||||
"flake-utils"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1697422411,
|
"lastModified": 1718681902,
|
||||||
"narHash": "sha256-eCj20wEwATLm7Bd/+/wOIdbqq9jgvS6ZxMrxujX2DxU=",
|
"narHash": "sha256-E/T7Ge6ayEQe7FVKMJqDBoHyLhRhjc6u9CmU8MyYfy0=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "056256f2fcf3c5a652dbc3edba9ec1a956d41f56",
|
"rev": "16c8ad83297c278eebe740dea5491c1708960dd1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
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 = {
|
rust-overlay = {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "parse-flake-lock"
|
name = "parse-flake-lock"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -375,6 +375,9 @@ pub struct TarballNode {
|
|||||||
/// Information about the tarball input that's "locked" because it's supplied by Nix.
|
/// Information about the tarball input that's "locked" because it's supplied by Nix.
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub struct TarballLocked {
|
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.
|
/// The NAR hash of the input.
|
||||||
#[serde(alias = "narHash")]
|
#[serde(alias = "narHash")]
|
||||||
pub nar_hash: String,
|
pub nar_hash: String,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use cel_interpreter::{Context, Program, Value};
|
use cel_interpreter::{Context, Program, Value};
|
||||||
use parse_flake_lock::{FlakeLock, Node, RepoNode};
|
use parse_flake_lock::{FlakeLock, Node};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::FlakeCheckerError,
|
error::FlakeCheckerError,
|
||||||
@ -19,61 +19,68 @@ pub(super) fn evaluate_condition(
|
|||||||
allowed_refs: Vec<String>,
|
allowed_refs: Vec<String>,
|
||||||
) -> Result<Vec<Issue>, FlakeCheckerError> {
|
) -> Result<Vec<Issue>, FlakeCheckerError> {
|
||||||
let mut issues: Vec<Issue> = vec![];
|
let mut issues: Vec<Issue> = vec![];
|
||||||
|
let mut ctx = Context::default();
|
||||||
let allowed_refs: Value = Value::from(
|
ctx.add_variable_from_value(KEY_SUPPORTED_REFS, allowed_refs.clone());
|
||||||
allowed_refs
|
|
||||||
.iter()
|
|
||||||
.map(|r| Value::from(r.to_string()))
|
|
||||||
.collect::<Vec<Value>>(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let deps = nixpkgs_deps(flake_lock, nixpkgs_keys)?;
|
let deps = nixpkgs_deps(flake_lock, nixpkgs_keys)?;
|
||||||
|
|
||||||
for (name, dep) in deps {
|
for (name, node) in deps {
|
||||||
if let Node::Repo(repo) = dep {
|
println!("name: {name}");
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
match Program::compile(condition)?.execute(&ctx) {
|
let (git_ref, last_modified, owner) = match node {
|
||||||
Ok(result) => match result {
|
Node::Repo(repo) => (
|
||||||
Value::Bool(b) if !b => {
|
repo.original.git_ref,
|
||||||
issues.push(Issue {
|
Some(repo.locked.last_modified),
|
||||||
input: name.clone(),
|
Some(repo.original.owner),
|
||||||
kind: IssueKind::Violation,
|
),
|
||||||
});
|
Node::Tarball(tarball) => (None, tarball.locked.last_modified, None),
|
||||||
}
|
_ => (None, None, None),
|
||||||
Value::Bool(b) if b => continue,
|
};
|
||||||
result => {
|
|
||||||
return Err(FlakeCheckerError::NonBooleanCondition(
|
add_cel_variables(&mut ctx, git_ref, last_modified, owner);
|
||||||
result.type_of().to_string(),
|
|
||||||
))
|
match Program::compile(condition)?.execute(&ctx) {
|
||||||
}
|
Ok(result) => match result {
|
||||||
},
|
Value::Bool(b) if !b => {
|
||||||
Err(e) => return Err(FlakeCheckerError::CelExecution(e)),
|
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)
|
Ok(issues)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nixpkgs_cel_values(repo: Box<RepoNode>) -> Vec<(&'static str, Value)> {
|
fn add_cel_variables(
|
||||||
vec![
|
ctx: &mut Context,
|
||||||
(
|
git_ref: Option<String>,
|
||||||
KEY_GIT_REF,
|
last_modified: Option<i64>,
|
||||||
repo.original
|
owner: Option<String>,
|
||||||
.git_ref
|
) {
|
||||||
.map_or_else(|| Value::Null, Value::from),
|
ctx.add_variable_from_value(KEY_GIT_REF, value_or_empty_string(git_ref));
|
||||||
),
|
ctx.add_variable_from_value(
|
||||||
(
|
KEY_NUM_DAYS_OLD,
|
||||||
KEY_NUM_DAYS_OLD,
|
value_or_zero(last_modified.map(|d| num_days_old(d))),
|
||||||
Value::from(num_days_old(repo.locked.last_modified)),
|
);
|
||||||
),
|
ctx.add_variable_from_value(KEY_OWNER, value_or_empty_string(owner));
|
||||||
(KEY_OWNER, Value::from(repo.original.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> {
|
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)?;
|
let deps = nixpkgs_deps(flake_lock, &config.nixpkgs_keys)?;
|
||||||
|
|
||||||
for (name, dep) in deps {
|
for (name, node) in deps {
|
||||||
if let Node::Repo(repo) = dep {
|
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
|
// Check if not explicitly supported
|
||||||
if config.check_supported {
|
if config.check_supported {
|
||||||
if let Some(ref git_ref) = repo.original.git_ref {
|
if !allowed_refs.contains(&git_ref) {
|
||||||
if !allowed_refs.contains(git_ref) {
|
issues.push(Issue {
|
||||||
issues.push(Issue {
|
input: name.clone(),
|
||||||
input: name.clone(),
|
kind: IssueKind::Disallowed(Disallowed {
|
||||||
kind: IssueKind::Disallowed(Disallowed {
|
reference: git_ref.to_string(),
|
||||||
reference: git_ref.to_string(),
|
}),
|
||||||
}),
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(last_modified) = last_modified {
|
||||||
// Check if outdated
|
// Check if outdated
|
||||||
if config.check_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 {
|
if num_days_old > MAX_DAYS {
|
||||||
issues.push(Issue {
|
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
|
// Check that the GitHub owner is NixOS
|
||||||
if config.check_owner {
|
if config.check_owner {
|
||||||
let owner = repo.original.owner;
|
|
||||||
if owner.to_lowercase() != "nixos" {
|
if owner.to_lowercase() != "nixos" {
|
||||||
issues.push(Issue {
|
issues.push(Issue {
|
||||||
input: name.clone(),
|
input: name.clone(),
|
||||||
|
Loading…
Reference in New Issue
Block a user