250 lines
6.9 KiB
Nix
250 lines
6.9 KiB
Nix
{
|
|
pkgs,
|
|
inputs,
|
|
lib,
|
|
...
|
|
}:
|
|
|
|
let
|
|
testbedFieldSeparator = ":";
|
|
username = "guest";
|
|
|
|
commonModule =
|
|
{ config, ... }:
|
|
{
|
|
users.users.${username} = {
|
|
description = "Guest";
|
|
hashedPassword = "";
|
|
isNormalUser = true;
|
|
extraGroups = [ "wheel" ];
|
|
};
|
|
|
|
security.sudo.wheelNeedsPassword = false;
|
|
|
|
services.getty.autologinUser = username;
|
|
|
|
# The state version can safely track the latest release because the disk
|
|
# image is ephemeral.
|
|
system.stateVersion = config.system.nixos.release;
|
|
home-manager.users.${username}.home.stateVersion = config.system.nixos.release;
|
|
|
|
virtualisation.vmVariant.virtualisation = {
|
|
# This is a maximum limit; the VM should still work if the host has fewer cores.
|
|
cores = 4;
|
|
memorySize = lib.mkDefault 2048;
|
|
};
|
|
};
|
|
|
|
applicationModule =
|
|
{ config, lib, ... }:
|
|
{
|
|
options.stylix.testbed.application = {
|
|
enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to enable a standard configuration for testing individual
|
|
applications.
|
|
|
|
This will automatically log in as the `${username}` user, then launch
|
|
the application from its desktop entry.
|
|
|
|
This is currently based on GNOME, but the specific desktop environment
|
|
used may change in the future.
|
|
'';
|
|
};
|
|
|
|
name = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = ''
|
|
The name of the desktop entry for the application, without the
|
|
`.desktop` extension.
|
|
'';
|
|
};
|
|
|
|
package = lib.mkOption {
|
|
type = lib.types.package;
|
|
description = ''
|
|
The application being tested.
|
|
'';
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf config.stylix.testbed.application.enable {
|
|
services.xserver = {
|
|
enable = true;
|
|
displayManager.gdm.enable = true;
|
|
desktopManager.gnome.enable = true;
|
|
};
|
|
|
|
services.displayManager.autoLogin = {
|
|
enable = true;
|
|
user = username;
|
|
};
|
|
|
|
# Disable the GNOME tutorial which pops up on first login.
|
|
environment.gnome.excludePackages = [ pkgs.gnome-tour ];
|
|
|
|
environment.systemPackages = [
|
|
(pkgs.makeAutostartItem {
|
|
inherit (config.stylix.testbed.application) name package;
|
|
})
|
|
];
|
|
};
|
|
};
|
|
|
|
autoload =
|
|
let
|
|
directory = "testbeds";
|
|
modules = "${inputs.self}/modules";
|
|
in
|
|
lib.flatten (
|
|
lib.mapAttrsToList (
|
|
module: _:
|
|
let
|
|
testbeds = "${modules}/${module}/${directory}";
|
|
in
|
|
lib.mapAttrsToList (
|
|
testbed: type:
|
|
if type != "regular" then
|
|
builtins.throw "${testbed} must be regular: ${type}"
|
|
|
|
else if !lib.hasSuffix ".nix" testbed then
|
|
builtins.throw "testbed must be a Nix file: ${testbeds}/${testbed}"
|
|
|
|
else if testbed == ".nix" then
|
|
builtins.throw "testbed must have a name: ${testbed}"
|
|
|
|
else
|
|
{
|
|
inherit module;
|
|
|
|
name = lib.removeSuffix ".nix" testbed;
|
|
path = "${testbeds}/${testbed}";
|
|
}
|
|
) (lib.optionalAttrs (builtins.pathExists testbeds) (builtins.readDir testbeds))
|
|
) (builtins.readDir modules)
|
|
);
|
|
|
|
makeTestbed =
|
|
testbed: stylix:
|
|
let
|
|
name = builtins.concatStringsSep testbedFieldSeparator (
|
|
map
|
|
(
|
|
field:
|
|
lib.throwIf (lib.hasInfix testbedFieldSeparator field)
|
|
"testbed field must not contain the '${testbedFieldSeparator}' testbed field separator: ${field}"
|
|
field
|
|
)
|
|
[
|
|
"testbed"
|
|
testbed.module
|
|
testbed.name
|
|
stylix.polarity
|
|
"image${lib.optionalString (stylix.image or null == null) "less"}"
|
|
"scheme${lib.optionalString (stylix.base16Scheme or null == null) "less"}"
|
|
"cursor${lib.optionalString (stylix.cursor or null == null) "less"}"
|
|
]
|
|
);
|
|
|
|
system = lib.nixosSystem {
|
|
inherit (pkgs) system;
|
|
|
|
modules = [
|
|
commonModule
|
|
applicationModule
|
|
inputs.self.nixosModules.stylix
|
|
inputs.home-manager.nixosModules.home-manager
|
|
testbed.path
|
|
|
|
{
|
|
inherit stylix;
|
|
system.name = name;
|
|
}
|
|
];
|
|
};
|
|
|
|
script = pkgs.writeShellApplication {
|
|
inherit name;
|
|
text = ''
|
|
cleanup() {
|
|
if rm --recursive "$directory"; then
|
|
printf '%s\n' 'Virtualisation disk image removed.'
|
|
fi
|
|
}
|
|
|
|
# We create a temporary directory rather than a temporary file, since
|
|
# temporary files are created empty and are not valid disk images.
|
|
directory="$(mktemp --directory)"
|
|
trap cleanup EXIT
|
|
|
|
NIX_DISK_IMAGE="$directory/nixos.qcow2" \
|
|
${lib.getExe system.config.system.build.vm}
|
|
'';
|
|
};
|
|
in
|
|
{
|
|
${name} = script;
|
|
};
|
|
|
|
# This generates a copy of each testbed for each of the following themes.
|
|
makeTestbeds =
|
|
let
|
|
images = {
|
|
dark = pkgs.fetchurl {
|
|
name = "mountains.jpg";
|
|
url = "https://unsplash.com/photos/ZqLeQDjY6fY/download?ixid=M3wxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNzE2MzY1NDY4fA&force=true";
|
|
hash = "sha256-Dm/0nKiTFOzNtSiARnVg7zM0J1o+EuIdUQ3OAuasM58=";
|
|
};
|
|
|
|
light = pkgs.fetchurl {
|
|
name = "three-bicycles.jpg";
|
|
url = "https://unsplash.com/photos/hwLAI5lRhdM/download?ixid=M3wxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNzE2MzYxNDcwfA&force=true";
|
|
hash = "sha256-S0MumuBGJulUekoGI2oZfUa/50Jw0ZzkqDDu1nRkFUA=";
|
|
};
|
|
};
|
|
in
|
|
testbed:
|
|
map (makeTestbed testbed) [
|
|
{
|
|
enable = true;
|
|
image = images.light;
|
|
base16Scheme = "${inputs.tinted-schemes}/base16/catppuccin-latte.yaml";
|
|
polarity = "light";
|
|
}
|
|
{
|
|
enable = true;
|
|
image = images.dark;
|
|
base16Scheme = "${inputs.tinted-schemes}/base16/catppuccin-macchiato.yaml";
|
|
polarity = "dark";
|
|
}
|
|
{
|
|
enable = true;
|
|
base16Scheme = "${inputs.tinted-schemes}/base16/catppuccin-macchiato.yaml";
|
|
polarity = "dark";
|
|
}
|
|
{
|
|
enable = true;
|
|
image = images.dark;
|
|
polarity = "dark";
|
|
}
|
|
{
|
|
enable = true;
|
|
image = images.dark;
|
|
base16Scheme = "${inputs.tinted-schemes}/base16/catppuccin-macchiato.yaml";
|
|
polarity = "dark";
|
|
cursor = {
|
|
name = "Vanilla-DMZ";
|
|
package = pkgs.vanilla-dmz;
|
|
size = 32;
|
|
};
|
|
}
|
|
];
|
|
|
|
in
|
|
# Testbeds are merged using lib.attrsets.unionOfDisjoint to throw an error if
|
|
# testbed names collide.
|
|
builtins.foldl' lib.attrsets.unionOfDisjoint { } (
|
|
lib.flatten (map makeTestbeds autoload)
|
|
)
|