Skip to content

Commit 65bc77d

Browse files
committed
Replace allowed-refs.json with ref-statuses.json
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>
1 parent ca7cfb3 commit 65bc77d

File tree

10 files changed

+161
-134
lines changed

10 files changed

+161
-134
lines changed

.github/workflows/allowed-refs.yaml

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Check that ref statuses are up to date
2+
3+
on:
4+
schedule:
5+
- cron: "0 0 * * *" # Daily
6+
7+
jobs:
8+
check-ref-statuses:
9+
runs-on: ubuntu-22.04
10+
steps:
11+
- uses: actions/checkout@v4
12+
13+
- uses: DeterminateSystems/nix-installer-action@main
14+
15+
- uses: DeterminateSystems/magic-nix-cache-action@main
16+
17+
- name: Check ref statuses
18+
run: |
19+
nix develop --command cargo run --features ref-statuses -- --check-ref-statuses
20+
21+
- name: Update ref-statuses.json
22+
if: failure()
23+
run: |
24+
ref_statuses_json=$(nix develop --command cargo run --features ref-statuses -- --get-ref-statuses | jq --sort-keys .)
25+
echo "${ref_statuses_json}" > ref-statuses.json
26+
27+
- name: Create pull request
28+
if: failure()
29+
uses: peter-evans/create-pull-request@v6
30+
with:
31+
commit-message: Update ref-statuses.json to new valid Git refs list
32+
title: Update ref-statuses.json
33+
body: |
34+
Nixpkgs has changed its list of maintained references. This PR updates `ref-statuses.json` to reflect that change.
35+
branch: updated-ref-statuses
36+
base: main

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ thiserror = { workspace = true }
3838

3939
[features]
4040
default = []
41-
allowed-refs = []
41+
ref-statuses = []

allowed-refs.json

Lines changed: 0 additions & 11 deletions
This file was deleted.

flake.nix

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@
9191
runtimeInputs = with pkgs; [ rustToolchain ];
9292
text = "cargo fmt --check";
9393
};
94-
get-allowed-refs = pkgs.writeShellApplication {
95-
name = "get-allowed-refs";
94+
get-ref-statuses = pkgs.writeShellApplication {
95+
name = "get-ref-statuses";
9696
runtimeInputs = with pkgs; [ rustToolchain ];
97-
text = "cargo run --features allowed-refs -- --get-allowed-refs";
97+
text = "cargo run --features ref-statuses -- --get-ref-statuses";
9898
};
9999
in
100100
pkgs.mkShell {
@@ -117,7 +117,7 @@
117117
check-rustfmt
118118

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

123123
env = {

ref-statuses.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"nixos-24.05": "deprecated",
3+
"nixos-24.05-small": "deprecated",
4+
"nixos-24.11": "stable",
5+
"nixos-24.11-small": "stable",
6+
"nixos-unstable": "rolling",
7+
"nixos-unstable-small": "rolling",
8+
"nixpkgs-24.05-darwin": "deprecated",
9+
"nixpkgs-24.11-darwin": "stable",
10+
"nixpkgs-unstable": "rolling"
11+
}

src/allowed_refs.rs

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/flake.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,14 @@ pub(super) fn num_days_old(timestamp: i64) -> i64 {
144144

145145
#[cfg(test)]
146146
mod test {
147+
use std::collections::HashMap;
147148
use std::path::PathBuf;
148149

149150
use crate::{
150151
check_flake_lock,
151152
condition::evaluate_condition,
152153
issue::{Disallowed, Issue, IssueKind, NonUpstream},
153-
FlakeCheckConfig, FlakeLock,
154+
supported_refs, FlakeCheckConfig, FlakeLock,
154155
};
155156

156157
#[test]
@@ -170,8 +171,9 @@ mod test {
170171
),
171172
];
172173

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

177179
for (condition, expected) in cases {
@@ -201,8 +203,9 @@ mod test {
201203

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

222225
#[test]
223226
fn dirty_flake_locks() {
224-
let allowed_refs: Vec<String> =
225-
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();
227+
let ref_statuses: HashMap<String, String> =
228+
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();
229+
let allowed_refs = supported_refs(ref_statuses);
226230
let cases: Vec<(&str, Vec<Issue>)> = vec![
227231
(
228232
"flake.dirty.0.lock",
@@ -275,8 +279,9 @@ mod test {
275279

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

304309
#[test]
305310
fn missing_nixpkgs_keys() {
306-
let allowed_refs: Vec<String> =
307-
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();
311+
let ref_statuses: HashMap<String, String> =
312+
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();
313+
let allowed_refs = supported_refs(ref_statuses);
308314
let cases: Vec<(&str, Vec<String>, String)> = vec![(
309315
"flake.clean.0.lock",
310316
vec![String::from("nixpkgs"), String::from("foo"), String::from("bar")],

src/main.rs

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ mod issue;
55
mod summary;
66
mod telemetry;
77

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

1111
use error::FlakeCheckerError;
1212
use flake::{check_flake_lock, FlakeCheckConfig};
1313
use summary::Summary;
1414

15+
use std::collections::HashMap;
1516
use std::path::PathBuf;
1617
use std::process::ExitCode;
1718

@@ -21,7 +22,7 @@ use parse_flake_lock::FlakeLock;
2122
use crate::condition::evaluate_condition;
2223

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

99-
#[cfg(not(feature = "allowed-refs"))]
100+
#[cfg(not(feature = "ref-statuses"))]
101+
pub(crate) fn supported_refs(ref_statuses: HashMap<String, String>) -> Vec<String> {
102+
let mut return_value: Vec<String> = ref_statuses
103+
.iter()
104+
.filter_map(|(channel, status)| {
105+
if *status != "unmaintained" && *status != "beta" {
106+
Some(channel.clone())
107+
} else {
108+
None
109+
}
110+
})
111+
.collect();
112+
return_value.sort();
113+
return_value
114+
}
115+
116+
#[cfg(not(feature = "ref-statuses"))]
100117
fn main() -> Result<ExitCode, FlakeCheckerError> {
101-
let allowed_refs: Vec<String> =
102-
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();
118+
let ref_statuses: HashMap<String, String> =
119+
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();
103120

104121
let Cli {
105122
no_telemetry,
@@ -134,6 +151,8 @@ fn main() -> Result<ExitCode, FlakeCheckerError> {
134151
fail_mode,
135152
};
136153

154+
let allowed_refs = supported_refs(ref_statuses);
155+
137156
let issues = if let Some(condition) = &condition {
138157
evaluate_condition(&flake_lock, &nixpkgs_keys, condition, allowed_refs.clone())?
139158
} else {
@@ -168,61 +187,61 @@ fn main() -> Result<ExitCode, FlakeCheckerError> {
168187
Ok(ExitCode::SUCCESS)
169188
}
170189

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

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

183-
#[cfg(feature = "allowed-refs")]
202+
#[cfg(feature = "ref-statuses")]
184203
fn main() -> Result<ExitCode, FlakeCheckerError> {
185204
let Cli {
186-
check_allowed_refs,
187-
get_allowed_refs,
205+
check_ref_statuses,
206+
get_ref_statuses,
188207
} = Cli::parse();
189208

190-
if !get_allowed_refs && !check_allowed_refs {
191-
panic!("You must select either --get-allowed-refs or --check-allowed-refs");
209+
if !get_ref_statuses && !check_ref_statuses {
210+
panic!("You must select either --get-ref-statuses or --check-ref-statuses");
192211
}
193212

194-
if get_allowed_refs {
195-
match allowed_refs::fetch_allowed_refs() {
213+
if get_ref_statuses {
214+
match ref_statuses::fetch_ref_statuses() {
196215
Ok(refs) => {
197216
let json_refs = serde_json::to_string(&refs)?;
198217
println!("{json_refs}");
199218
return Ok(ExitCode::SUCCESS);
200219
}
201220
Err(e) => {
202-
println!("Error fetching allowed refs: {}", e);
221+
println!("Error fetching ref statuses: {}", e);
203222
return Ok(ExitCode::FAILURE);
204223
}
205224
}
206225
}
207226

208-
if check_allowed_refs {
209-
let mut allowed_refs: Vec<String> =
210-
serde_json::from_str(include_str!("../allowed-refs.json")).unwrap();
211-
212-
allowed_refs.sort();
227+
if check_ref_statuses {
228+
let mut ref_statuses: HashMap<String, String> =
229+
serde_json::from_str(include_str!("../ref-statuses.json")).unwrap();
213230

214-
match allowed_refs::check_allowed_refs(allowed_refs) {
231+
match ref_statuses::check_ref_statuses(ref_statuses) {
215232
Ok(equals) => {
216233
if equals {
217-
println!("The allowed reference sets are up to date.");
234+
println!("The reference statuses sets are up to date.");
218235
return Ok(ExitCode::SUCCESS);
219236
} else {
220-
println!("The allowed reference sets are NOT up to date. Make sure to update.");
237+
println!(
238+
"The reference statuses sets are NOT up to date. Make sure to update."
239+
);
221240
return Ok(ExitCode::FAILURE);
222241
}
223242
}
224243
Err(e) => {
225-
println!("Error checking allowed refs: {}", e);
244+
println!("Error checking ref statuses: {}", e);
226245
return Ok(ExitCode::FAILURE);
227246
}
228247
}

0 commit comments

Comments
 (0)