Skip to content

Commit

Permalink
Replace allowed-refs.json with ref-statuses.json
Browse files Browse the repository at this point in the history
As far as stable versions of Nix Flake Checker are concerned, a Nixpkgs
branch is considered supported if it meets the following criteria:

1. The branch is connected to a channel.
2. The branch’s status is not "unmaintained".
3. The branch’s status is not "beta".

Before this change, here’s how Nix Flake Checker would enforce those
criteria:

1. An API request was made to get a list of channels. Refs were only
   considered if they were on that list [1].
2. Refs would only get added to allowed-refs.json if their current field
   was set to "1" [1]. (The current field gets set to "0" for
   unmaintained channels and "1" for all other channels [2].)
3. The Nix Flake Checker project was careful about when it released
   updates that contained changes to allowed-refs.json. Specifically,
   updates to allowed-refs.json would stay in the main branch and
   not be released while Nixpkgs channels were in beta.

This change replaces allowed-refs.json with ref-statuses.json.
allowed-refs.json contained a list of supported Nixpkgs branches.
ref-statuses.json contains a list of Nixpkgs branches along with their
current status ("rolling", "beta", "stable", "deprecated" or
"unmaintained").

Here’s how Nix Flake Checker now enforces those same criteria:

1. Unchanged.
2. All channel branches get added to ref-statuses.json regardless of
   whether or not they’re supported. Nix Flake Checker checks if a
   branch’s status is "unmaintained" at runtime.
3. Nix Flake Checker checks if a branch’s status is "beta" at runtime.

The main motivation behind this change is to make it easier to create a
future commit. That future commit will allow users to access a branch’s
status via a CEL variable. As an added bonus, this change also makes it
so that the Nix Flake Checker project doesn’t have to be careful about
releasing updates while there’s Nixpkgs branches that are in beta.

[1]: src/allowed_refs.rs
[2]: <https://github.com/NixOS/infra/blob/ae9b362fe0d92cff76c0b5404d0bcec59dd322cb/build/pluto/prometheus/exporters/channel-exporter.py#L78>
  • Loading branch information
Jayman2000 committed Dec 18, 2024
1 parent ca7cfb3 commit 65bc77d
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 134 deletions.
36 changes: 0 additions & 36 deletions .github/workflows/allowed-refs.yaml

This file was deleted.

36 changes: 36 additions & 0 deletions .github/workflows/ref-statuses.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Check that ref statuses are up to date

on:
schedule:
- cron: "0 0 * * *" # Daily

jobs:
check-ref-statuses:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

- uses: DeterminateSystems/nix-installer-action@main

- uses: DeterminateSystems/magic-nix-cache-action@main

- name: Check ref statuses
run: |
nix develop --command cargo run --features ref-statuses -- --check-ref-statuses
- name: Update ref-statuses.json
if: failure()
run: |
ref_statuses_json=$(nix develop --command cargo run --features ref-statuses -- --get-ref-statuses | jq --sort-keys .)
echo "${ref_statuses_json}" > ref-statuses.json
- name: Create pull request
if: failure()
uses: peter-evans/create-pull-request@v6
with:
commit-message: Update ref-statuses.json to new valid Git refs list
title: Update ref-statuses.json
body: |
Nixpkgs has changed its list of maintained references. This PR updates `ref-statuses.json` to reflect that change.
branch: updated-ref-statuses
base: main
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ thiserror = { workspace = true }

[features]
default = []
allowed-refs = []
ref-statuses = []
11 changes: 0 additions & 11 deletions allowed-refs.json

This file was deleted.

8 changes: 4 additions & 4 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@
runtimeInputs = with pkgs; [ rustToolchain ];
text = "cargo fmt --check";
};
get-allowed-refs = pkgs.writeShellApplication {
name = "get-allowed-refs";
get-ref-statuses = pkgs.writeShellApplication {
name = "get-ref-statuses";
runtimeInputs = with pkgs; [ rustToolchain ];
text = "cargo run --features allowed-refs -- --get-allowed-refs";
text = "cargo run --features ref-statuses -- --get-ref-statuses";
};
in
pkgs.mkShell {
Expand All @@ -117,7 +117,7 @@
check-rustfmt

# Scripts
get-allowed-refs
get-ref-statuses
]) ++ pkgs.lib.optionals pkgs.stdenv.isDarwin (with pkgs.darwin.apple_sdk.frameworks; [ Security SystemConfiguration ]);

env = {
Expand Down
11 changes: 11 additions & 0 deletions ref-statuses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"nixos-24.05": "deprecated",
"nixos-24.05-small": "deprecated",
"nixos-24.11": "stable",
"nixos-24.11-small": "stable",
"nixos-unstable": "rolling",
"nixos-unstable-small": "rolling",
"nixpkgs-24.05-darwin": "deprecated",
"nixpkgs-24.11-darwin": "stable",
"nixpkgs-unstable": "rolling"
}
45 changes: 0 additions & 45 deletions src/allowed_refs.rs

This file was deleted.

28 changes: 17 additions & 11 deletions src/flake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,14 @@ pub(super) fn num_days_old(timestamp: i64) -> i64 {

#[cfg(test)]
mod test {
use std::collections::HashMap;
use std::path::PathBuf;

use crate::{
check_flake_lock,
condition::evaluate_condition,
issue::{Disallowed, Issue, IssueKind, NonUpstream},
FlakeCheckConfig, FlakeLock,
supported_refs, FlakeCheckConfig, FlakeLock,
};

#[test]
Expand All @@ -170,8 +171,9 @@ mod test {
),
];

let supported_refs: Vec<String> =
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();
let ref_statuses: HashMap<String, String> =
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();
let supported_refs = supported_refs(ref_statuses);
let path = PathBuf::from("tests/flake.cel.0.lock");

for (condition, expected) in cases {
Expand Down Expand Up @@ -201,8 +203,9 @@ mod test {

#[test]
fn clean_flake_locks() {
let allowed_refs: Vec<String> =
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();
let ref_statuses: HashMap<String, String> =
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();
let allowed_refs = supported_refs(ref_statuses);
for n in 0..=7 {
let path = PathBuf::from(format!("tests/flake.clean.{n}.lock"));
let flake_lock = FlakeLock::new(&path).unwrap();
Expand All @@ -221,8 +224,9 @@ mod test {

#[test]
fn dirty_flake_locks() {
let allowed_refs: Vec<String> =
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();
let ref_statuses: HashMap<String, String> =
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();
let allowed_refs = supported_refs(ref_statuses);
let cases: Vec<(&str, Vec<Issue>)> = vec![
(
"flake.dirty.0.lock",
Expand Down Expand Up @@ -275,8 +279,9 @@ mod test {

#[test]
fn explicit_nixpkgs_keys() {
let allowed_refs: Vec<String> =
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();
let ref_statuses: HashMap<String, String> =
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();
let allowed_refs = supported_refs(ref_statuses);
let cases: Vec<(&str, Vec<String>, Vec<Issue>)> = vec![(
"flake.explicit-keys.0.lock",
vec![String::from("nixpkgs"), String::from("nixpkgs-alt")],
Expand All @@ -303,8 +308,9 @@ mod test {

#[test]
fn missing_nixpkgs_keys() {
let allowed_refs: Vec<String> =
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();
let ref_statuses: HashMap<String, String> =
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();
let allowed_refs = supported_refs(ref_statuses);
let cases: Vec<(&str, Vec<String>, String)> = vec![(
"flake.clean.0.lock",
vec![String::from("nixpkgs"), String::from("foo"), String::from("bar")],
Expand Down
71 changes: 45 additions & 26 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ mod issue;
mod summary;
mod telemetry;

#[cfg(feature = "allowed-refs")]
mod allowed_refs;
#[cfg(feature = "ref-statuses")]
mod ref_statuses;

use error::FlakeCheckerError;
use flake::{check_flake_lock, FlakeCheckConfig};
use summary::Summary;

use std::collections::HashMap;
use std::path::PathBuf;
use std::process::ExitCode;

Expand All @@ -21,7 +22,7 @@ use parse_flake_lock::FlakeLock;
use crate::condition::evaluate_condition;

/// A flake.lock checker for Nix projects.
#[cfg(not(feature = "allowed-refs"))]
#[cfg(not(feature = "ref-statuses"))]
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
Expand Down Expand Up @@ -96,10 +97,26 @@ struct Cli {
condition: Option<String>,
}

#[cfg(not(feature = "allowed-refs"))]
#[cfg(not(feature = "ref-statuses"))]
pub(crate) fn supported_refs(ref_statuses: HashMap<String, String>) -> Vec<String> {
let mut return_value: Vec<String> = ref_statuses
.iter()
.filter_map(|(channel, status)| {
if *status != "unmaintained" && *status != "beta" {
Some(channel.clone())
} else {
None
}
})
.collect();
return_value.sort();
return_value
}

#[cfg(not(feature = "ref-statuses"))]
fn main() -> Result<ExitCode, FlakeCheckerError> {
let allowed_refs: Vec<String> =
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();
let ref_statuses: HashMap<String, String> =
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();

let Cli {
no_telemetry,
Expand Down Expand Up @@ -134,6 +151,8 @@ fn main() -> Result<ExitCode, FlakeCheckerError> {
fail_mode,
};

let allowed_refs = supported_refs(ref_statuses);

let issues = if let Some(condition) = &condition {
evaluate_condition(&flake_lock, &nixpkgs_keys, condition, allowed_refs.clone())?
} else {
Expand Down Expand Up @@ -168,61 +187,61 @@ fn main() -> Result<ExitCode, FlakeCheckerError> {
Ok(ExitCode::SUCCESS)
}

#[cfg(feature = "allowed-refs")]
#[cfg(feature = "ref-statuses")]
#[derive(Parser)]
struct Cli {
// Check to make sure that Flake Checker is aware of the current supported branches.
#[arg(long, hide = true)]
check_allowed_refs: bool,
check_ref_statuses: bool,

// Check to make sure that Flake Checker is aware of the current supported branches.
#[arg(long, hide = true)]
get_allowed_refs: bool,
get_ref_statuses: bool,
}

#[cfg(feature = "allowed-refs")]
#[cfg(feature = "ref-statuses")]
fn main() -> Result<ExitCode, FlakeCheckerError> {
let Cli {
check_allowed_refs,
get_allowed_refs,
check_ref_statuses,
get_ref_statuses,
} = Cli::parse();

if !get_allowed_refs && !check_allowed_refs {
panic!("You must select either --get-allowed-refs or --check-allowed-refs");
if !get_ref_statuses && !check_ref_statuses {
panic!("You must select either --get-ref-statuses or --check-ref-statuses");
}

if get_allowed_refs {
match allowed_refs::fetch_allowed_refs() {
if get_ref_statuses {
match ref_statuses::fetch_ref_statuses() {
Ok(refs) => {
let json_refs = serde_json::to_string(&refs)?;
println!("{json_refs}");
return Ok(ExitCode::SUCCESS);
}
Err(e) => {
println!("Error fetching allowed refs: {}", e);
println!("Error fetching ref statuses: {}", e);
return Ok(ExitCode::FAILURE);
}
}
}

if check_allowed_refs {
let mut allowed_refs: Vec<String> =
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();

allowed_refs.sort();
if check_ref_statuses {
let mut ref_statuses: HashMap<String, String> =
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();

match allowed_refs::check_allowed_refs(allowed_refs) {
match ref_statuses::check_ref_statuses(ref_statuses) {
Ok(equals) => {
if equals {
println!("The allowed reference sets are up to date.");
println!("The reference statuses sets are up to date.");
return Ok(ExitCode::SUCCESS);
} else {
println!("The allowed reference sets are NOT up to date. Make sure to update.");
println!(
"The reference statuses sets are NOT up to date. Make sure to update."
);
return Ok(ExitCode::FAILURE);
}
}
Err(e) => {
println!("Error checking allowed refs: {}", e);
println!("Error checking ref statuses: {}", e);
return Ok(ExitCode::FAILURE);
}
}
Expand Down
Loading

0 comments on commit 65bc77d

Please sign in to comment.