Skip to content

Commit 62a60df

Browse files
committed
chore(mcl): rework compare_disko command
1 parent 5743220 commit 62a60df

File tree

2 files changed

+98
-64
lines changed

2 files changed

+98
-64
lines changed

packages/mcl/src/src/mcl/commands/compare_disko.d

Lines changed: 97 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ import mcl.utils.env : optional, parseEnv;
44
import mcl.utils.nix : nix;
55
import mcl.utils.path : getTopLevel;
66
import mcl.utils.process : execute;
7+
import mcl.utils.log : errorAndExit;
78

8-
import std.typecons : Tuple, tuple;
9-
import std.file : mkdirRecurse, exists, rmdirRecurse;
10-
import std.format : fmt = format;
11-
import std.stdio;
12-
import std.json : JSONValue, parseJSON, JSONOptions;
9+
import std.json : JSONValue;
1310
import std.file : write;
14-
import std.logger : tracef, errorf, infof;
15-
import std.process : environment;
16-
import mcl.utils.log : errorAndExit;
11+
import std.logger : infof;
12+
import std.algorithm : uniq;
13+
import std.array;
14+
import std.meta : Filter;
1715

1816
struct Params
1917
{
@@ -26,27 +24,58 @@ struct Params
2624
}
2725
}
2826

27+
enum ChangeStatus{
28+
Unchanged,
29+
Changed,
30+
Removed,
31+
New
32+
}
33+
2934
struct MachineChanges{
3035
string machine;
31-
bool _config;
32-
bool _create;
36+
ChangeStatus _config;
37+
ChangeStatus _create;
38+
}
39+
40+
enum string[] diskoOptions = [ __traits(allMembers, MachineChanges)[1 .. $] ];
41+
42+
string statusToSymbol(ChangeStatus s) {
43+
final switch(s){
44+
case ChangeStatus.Unchanged:
45+
return "🟩";
46+
break;
47+
case ChangeStatus.Changed:
48+
return "";
49+
break;
50+
case ChangeStatus.Removed:
51+
return "🗑";
52+
break;
53+
case ChangeStatus.New:
54+
return "🧩";
55+
break;
56+
}
3357
}
3458

3559
// TODO: handle case where a machine is missing from one branch
3660
export void compare_disko(string[] args){
37-
nix.eval!JSONValue("", [], "");
3861
const params = parseEnv!Params;
62+
3963
JSONValue configurations = nix.flake!JSONValue("", [], "show");
40-
string[] machines;
64+
65+
string[] machinesNew;
4166
foreach (string k, JSONValue v; configurations["nixosConfigurations"]){
4267
if (k[$-3 .. $] != "-vm" &&
4368
k != "gitlab-runner-container" &&
4469
k != "minimal-container" )
4570
{
46-
machines ~= k;
71+
machinesNew ~= k;
4772
}
4873
}
4974

75+
auto attr = constructCommandAttr("./.", machinesNew);
76+
auto machineOptionsRootNew = nix.eval!JSONValue("", ["--impure", "--expr", attr]);
77+
78+
5079
string gitRoot = getTopLevel();
5180
string worktreeBaseBranch = gitRoot~"-"~params.baseBranch;
5281

@@ -55,65 +84,55 @@ export void compare_disko(string[] args){
5584
}
5685

5786
execute(["git", "worktree" , "add", worktreeBaseBranch, params.baseBranch]);
58-
string freshTestsDir = gitRoot~"/disko-tests";
59-
string staleTestsDir = worktreeBaseBranch~"/disko-tests";
60-
mkdirRecurse(staleTestsDir);
61-
mkdirRecurse(freshTestsDir);
6287

63-
Tuple!(string , string )[] machineDiffs;
88+
configurations = nix.flake!JSONValue(worktreeBaseBranch, [], "show");
89+
90+
string[] machinesOld;
91+
foreach (string k, JSONValue v; configurations["nixosConfigurations"]){
92+
if (k[$-3 .. $] != "-vm" &&
93+
k != "gitlab-runner-container" &&
94+
k != "minimal-container" )
95+
{
96+
machinesOld ~= k;
97+
}
98+
}
99+
100+
attr = constructCommandAttr(worktreeBaseBranch, machinesOld);
101+
auto machineOptionsRootOld = nix.eval!JSONValue("", ["--impure", "--expr", attr]);
102+
64103
MachineChanges[] machineChanges;
65104

105+
string[] machines = uniq(machinesOld ~ machinesNew).array;
106+
66107
foreach (string m; machines){
67108
MachineChanges mc;
68109
mc.machine = m;
69-
foreach (setting; __traits(allMembers, MachineChanges)){
70-
static if (is(typeof(__traits(getMember, mc, setting)) == bool)){
71-
string new_setting =
72-
nix.eval(gitRoot~"#nixosConfigurations."~m~".config.disko.devices."~setting, [
73-
"--option", "warn-dirty", "false",
74-
"--accept-flake-config"]);
75-
tracef("CREATING %s_%s_new FILE", m, setting);
76-
write(freshTestsDir~"/"~m~"_"~setting~"_new", new_setting);
77-
string old_setting =
78-
nix.eval(worktreeBaseBranch~"#nixosConfigurations."~m~".config.disko.devices."~setting, [
79-
"--option", "warn-dirty", "false",
80-
"--accept-flake-config"]);
81-
tracef("CREATING %s_%s_old FILE", m, setting);
82-
write(staleTestsDir~"/"~m~"_"~setting~"_old", old_setting);
83-
84-
85-
string diff = execute([
86-
"git", "--no-pager", "diff", "--no-index",
87-
staleTestsDir~"/"~m~"_"~setting~"_old",
88-
freshTestsDir~"/"~m~"_"~setting~"_new"]);
89-
90-
if (diff == ""){
91-
infof("✔ NO DIFFERENCE IN %s", m);
92-
__traits(getMember, mc, setting) = true;
110+
if (m in machineOptionsRootOld && !(m in machineOptionsRootNew)){
111+
static foreach (setting; diskoOptions){
112+
__traits(getMember, mc, setting) = ChangeStatus.Removed;
113+
}
114+
}
115+
else if (m in machineOptionsRootNew && !(m in machineOptionsRootOld)){
116+
static foreach (setting; diskoOptions){
117+
__traits(getMember, mc, setting) = ChangeStatus.New;
118+
}
119+
}
120+
else{
121+
static foreach (setting; diskoOptions){
122+
if (machineOptionsRootOld[m][setting] == machineOptionsRootNew[m][setting]){
123+
__traits(getMember, mc, setting) = ChangeStatus.Unchanged;
93124
}
94125
else{
95-
infof("✖ DIFFERENCE IN %s", m);
96-
__traits(getMember, mc, setting) = false;
126+
__traits(getMember, mc, setting) = ChangeStatus.Changed;
97127
}
98128
}
99129
}
100130
machineChanges ~= mc;
101131
}
102-
infof("------------------------------------------------------");
103-
if(machineDiffs.length == 0){
104-
infof("✔✔✔ NO CONFIGS WITH DIFFS");
105-
}
106-
else{
107-
infof("✖✖✖ LIST OF CONFIGS WITH DIFFS");
108-
foreach(mc; machineChanges){
109-
infof(mc.machine);
110-
}
111-
}
132+
112133
create_comment(machineChanges);
113134

114-
// Cleanup
115135
execute(["git", "worktree" , "remove", worktreeBaseBranch, "--force"]);
116-
rmdirRecurse(freshTestsDir);
117136
}
118137

119138
void create_comment(MachineChanges[] machineChanges){
@@ -122,8 +141,12 @@ void create_comment(MachineChanges[] machineChanges){
122141
data ~="\n\n✅ There have been no changes to disko configs";
123142
}
124143
else{
125-
// TODO: Change the generation of the table to have as many collumns as fields in MachineChanges at compile time
126144
data ~= "\n\nBellow you will find a summary of machines and whether their disko attributes have differences.";
145+
data ~= "\n\n**Legend:**";
146+
data ~= "\n🟩 = No changes";
147+
data ~= "\n⚡ = Something is different";
148+
data ~= "\n🗑 = Has been removed";
149+
data ~= "\n🧩 = Has been added";
127150

128151
data ~= "\n\n";
129152
foreach (string field; __traits(allMembers, MachineChanges)){
@@ -137,18 +160,29 @@ void create_comment(MachineChanges[] machineChanges){
137160

138161
foreach(mc; machineChanges){
139162
foreach (string field; __traits(allMembers, MachineChanges)){
140-
static if (is(typeof(__traits(getMember, mc, field)) == bool)){
141-
data~="| " ~ (__traits(getMember, mc, field) ? "🟩" : "⚠️") ~ " ";
142-
}
143-
else static if (is(typeof(__traits(getMember, mc, field)) == string)){
163+
static if (is(typeof(__traits(getMember, mc, field)) == string)){
144164
data~="| " ~ __traits(getMember, mc, field) ~ " ";
145165
}
146-
else{
147-
assert(0);
166+
else {
167+
data~="| " ~ statusToSymbol(__traits(getMember, mc, field)) ~ " ";
148168
}
149169
}
150170
data ~= "|\n";
151171
}
152172
}
153173
write("comment.md", data);
154174
}
175+
176+
177+
string constructCommandAttr(string flakePath, string[] machines){
178+
string attr = "let flake = (builtins.getFlake (builtins.toString " ~ flakePath ~ ")); in { ";
179+
foreach (m; machines){
180+
attr ~= m ~ " = { ";
181+
foreach (option; diskoOptions){
182+
attr ~= option ~ " = flake.nixosConfigurations." ~ m ~ ".config.disko.devices." ~ option ~ "; ";
183+
}
184+
attr ~= "}; ";
185+
}
186+
attr ~= "}";
187+
return attr;
188+
}

packages/mcl/src/src/mcl/utils/nix.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ struct NixCommand
8080
args = ["--json"] ~ args;
8181

8282
auto command = [
83-
"nix", "--experimental-features", "nix-command flakes",
83+
"nix", "--experimental-features", "nix-command flakes pipe-operators",
8484
commandName
8585
] ~ (subcommand == "" ? [] : [ subcommand ]) ~ args ~ path;
8686

0 commit comments

Comments
 (0)