Move devshell to subdirectory

This commit is contained in:
2022-02-19 23:34:41 +00:00
parent 17e4feb542
commit fafb7d4656
5 changed files with 90 additions and 72 deletions

52
devshell/commands.nix Normal file
View File

@@ -0,0 +1,52 @@
{ pkgs, ... }:
let
homeFlake = "$HOME/.config/nixpkgs/flake.nix";
in
{
commands = [
{
name = "repl";
category = "utilities";
help = "Open a `nix repl` with this flake";
command =
''
tmp="$(mktemp --tmpdir repl.nix.XXXXX)"
echo "builtins.getFlake \"$PRJ_ROOT\"" > "$tmp"
nix repl "$tmp" || true
rm "$tmp"
'';
}
{
name = "home-link";
category = "utilities";
help = "Install link to flake.nix for home-manager to use";
command =
''
[ -e "${homeFlake}" ] && echo "${homeFlake} already exists" && exit 1
mkdir -p "$(dirname "${homeFlake}")"
ln -s "$(pwd)/flake.nix" "${homeFlake}"
echo "Installed link to $(pwd)/flake.nix at ${homeFlake}"
'';
}
{
name = "home-unlink";
category = "utilities";
help = "Remove home-manager flake.nix link";
command = "rm -f ${homeFlake}";
}
{
name = "fmt";
category = "tasks";
help = pkgs.nixpkgs-fmt.meta.description;
command = ''exec "${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt" "$@"'';
}
{
name = "home-switch";
category = "tasks";
help = "Run `home-manager switch`";
command = ''home-manager switch --flake . "$@"'';
}
];
}

25
devshell/default.nix Normal file
View File

@@ -0,0 +1,25 @@
{ lib, pkgs, ... }:
let
inherit (lib.my) attrsToNVList;
in
{
imports = [ ./commands.nix ./install.nix ];
env = attrsToNVList {
# starship will show this
name = "devshell";
NIX_USER_CONF_FILES = toString (pkgs.writeText "nix.conf"
''
experimental-features = nix-command flakes ca-derivations
'');
};
packages = with pkgs; [
coreutils
nixVersions.stable
agenix
deploy-rs.deploy-rs
home-manager
];
}

205
devshell/install.nix Normal file
View File

@@ -0,0 +1,205 @@
{ lib, pkgs, config, ... }:
let
inherit (lib) mapAttrsToList concatMapStringsSep;
inherit (lib.my) mkOpt' attrsToNVList;
parseArgs = opts:
''
POSITIONAL_ARGS=()
while [ $# -gt 0 ]; do
# shellcheck disable=SC2221,SC2222
case $1 in
${opts}
-*|--*)
die "Unknown option $1"
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
set -- "''${POSITIONAL_ARGS[@]}" # restore positional parameters
'';
installCommon = pkgs.writeShellApplication {
name = "install-common.sh";
runtimeInputs = with pkgs; [
coreutils
gnugrep
openssh
nixVersions.stable
jq
];
text =
''
log() {
echo -e "$@" >&2
}
debug() {
[ -n "$DEBUG" ] || return 0
log "[\e[32;1mdebug\e[0m]: \e[32m$*\e[0m"
}
info() {
log "[\e[36;1minfo\e[0m]: \e[36m$*\e[0m"
}
warn() {
log "[\e[33;1minfo\e[0m]: \e[33m$*\e[0m"
}
error() {
log "[\e[31;1minfo\e[0m]: \e[31m$*\e[0m"
}
die() {
error "$@"
exit 1
}
askYN() {
local question="$1"
local options default
if [ "$2" = y ]; then
options="Y/n"
default="y"
else
options="y/N"
default="n"
fi
local input
read -p "$question [$options] " -n 1 -s -r input
: "''${input:=$default}"
echo "$input"
[[ "$input" =~ ^[yY]$ ]]
}
# : is a builtin that does nothing...
: "''${DEBUG:=}"
: "''${INSTALLER:=}"
: "''${INSTALLER_SSH_OPTS:=}"
: "''${INSTALLER_SSH_PORT:=22}"
[ -z "$INSTALLER" ] && die "\$INSTALLER is not set"
KNOWN_HOSTS="$(mktemp --tmpdir known_hosts.XXXXXX)"
cleanup() {
rm -f "$KNOWN_HOSTS"
}
trap cleanup EXIT
IFS=" " read -ra SSH_OPTS <<< "$INSTALLER_SSH_OPTS"
SSH_OPTS+=(-o StrictHostKeyChecking=ask -o UserKnownHostsFile="$KNOWN_HOSTS" -p "$INSTALLER_SSH_PORT")
debug "ssh params: ''${SSH_OPTS[*]}"
execInstaller() {
debug "[root@$INSTALLER -p $INSTALLER_SSH_PORT] $*"
ssh "''${SSH_OPTS[@]}" "root@$INSTALLER" -- "$@" 2> >(grep -v "Permanently added" 1>&2)
}
'';
};
installerCommandOpts = with lib.types; {
options = {
help = mkOpt' str null "Help message.";
script = mkOpt' lines "" "Script contents.";
packages = mkOpt' (listOf package) [ ] "Packages to make available to the script.";
};
};
in
{
options.my.installerCommands = with lib.types;
mkOpt' (attrsOf (submodule installerCommandOpts)) { } "Installer commands.";
config = {
my.installerCommands = {
installer-shell = {
help = "Get a shell into the installer";
script =
''
execInstaller "$@"
'';
};
# TODO: Add new command to generate a template with the output of nixos-generate-config included
do-install = {
help = "Install a system configuration into a prepared installer that can be reached at $INSTALLER";
script =
''
noBootloader=
noSubstitute=
${parseArgs
''
--no-bootloader)
noBootloader=true
shift
;;
--no-substitute)
noSubstitute=true
shift
;;
''}
system="''${1:-}"
[ -z "$system" ] && die "usage: $0 [--no-bootloader] [--no-substitute] <system>"
: "''${INSTALLER_BUILD_OPTS:=}"
IFS=" " read -ra BUILD_OPTS <<< "$INSTALLER_BUILD_OPTS"
INSTALL_ROOT="$(execInstaller echo \$INSTALL_ROOT)"
info "Installing configuration for $system to $INSTALLER:$INSTALL_ROOT"
askYN "Continue?" n || exit 1
params=()
[ -z "$noSubstitute" ] && params+=(--substitute-on-destination)
flakeAttr="$PRJ_ROOT#nixosConfigurations.$system.config.system.build.toplevel"
info "Building $flakeAttr..."
storePath="$(nix build "''${BUILD_OPTS[@]}" --no-link --json "$flakeAttr" | jq -r .[0].outputs.out)"
info "Copying closure of configuration $storePath to target..."
NIX_SSHOPTS="''${SSH_OPTS[*]}" nix copy "''${params[@]}" \
--to "ssh://root@$INSTALLER?remote-store=$INSTALL_ROOT" "$storePath"
profile=/nix/var/nix/profiles/system
info "Setting $profile on target to point to copied configuration..."
# Use `nix-env` since `nix profile` uses a non-backwards compatible manifest format
execInstaller nix-env --store "$INSTALL_ROOT" -p "$INSTALL_ROOT$profile" --set "$storePath"
# Make switch-to-configuration recognise this as a NixOS system
execInstaller "mkdir -m 0755 -p \"$INSTALL_ROOT/etc\" && touch \"$INSTALL_ROOT/etc/NIXOS\""
if [ -z "$noBootloader" ]; then
info "Activating configuration and installing bootloader..."
# Grub needs an mtab.
execInstaller ln -sfn /proc/mounts "$INSTALL_ROOT/etc/mtab"
execInstaller "export NIXOS_INSTALL_BOOTLOADER=1 && \
nixos-enter --root \"$INSTALL_ROOT\" -- /run/current-system/bin/switch-to-configuration boot"
else
info "Activating configuation..."
execInstaller \
nixos-enter --root "$INSTALL_ROOT" -- /run/current-system/bin/switch-to-configuration boot
fi
info "Success!"
'';
};
};
commands = mapAttrsToList (name: cmd: {
inherit name;
inherit (cmd) help;
category = "installation";
package = pkgs.writeShellApplication {
inherit name;
runtimeInputs = cmd.packages;
text =
''
# shellcheck disable=SC1091
source "${installCommon}/bin/install-common.sh"
${cmd.script}
'';
};
}) config.my.installerCommands;
};
}