Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow usage with nix daemon #45

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci-bzl-projects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,7 @@ jobs:
uses: cachix/install-nix-action@v15
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: |
experimental-features = nix-command flakes
- name: Build all
run: ./nix-shell.sh -- --run 'cd projects/${{ matrix.project }}; bazel build //...'
54 changes: 54 additions & 0 deletions scripts/nix-conf-diff.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
let
lib = (import <nixpkgs> { }).lib;
# attrset representing current host nix settings
global-nix-config = builtins.mapAttrs (_: value: value.value)
(builtins.fromJSON (builtins.readFile ../.cache/.global-nix-conf));
# list of config file lines
config-lines = lib.lists.remove ""
(lib.strings.splitString "\n" (builtins.readFile ./nix.conf));
# list of tuples representing config lines
config-kv-pairs = (builtins.map (x:
lib.strings.splitString "=" (builtins.replaceStrings [ " = " ] [ "=" ] x))
config-lines);
# attrset with strigified nix config values (i.e. "a b" instead of [ "a", "b" ], "true" instead of true
disruptor-config-strs = builtins.listToAttrs (builtins.map (x: {
name = (builtins.elemAt x 0);
value = (builtins.elemAt x 1);
}) config-kv-pairs);

# Convert disruptor config string values into correct types (except for numbers)
from_str = x:
(if x == "true" then
true
else if x == "false" then
false
else if (builtins.length (lib.strings.splitString " " x) == 1) then
x
else
(lib.strings.splitString " " x));

# Counteract the questionable translation of boolean values
to_string = x:
(if x == true then
"true"
else if x == false then
"false"
else
builtins.toString x);

# attrset representing disruptor required config
disruptor-config =
builtins.mapAttrs (_: v: (from_str v)) disruptor-config-strs;

# attrset representing diff in configuration
different_settings = lib.attrsets.filterAttrsRecursive (k: v:
(let global-value = builtins.getAttr k global-nix-config;
in if (builtins.isInt global-value) then
(builtins.toString global-value) != v
else
global-value != v)) disruptor-config;
output = lib.mapAttrs (k: v:
"'${to_string v}' change to => '${
to_string (builtins.getAttr k global-nix-config)
}';") different_settings;
in output
81 changes: 49 additions & 32 deletions scripts/shell.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,43 @@ preflightCheck() {
esac
}

verify_nix_daemon_config_compatibility() {
# Check if there is no discrepancies between host nix daemon configuration
# and project disruptor requirements.
#
# As one cannot assume the commands will be executed by a trusted nix user,
# only verification remains to notify user of any potential issues in host
# nix configuration.
#
# This function assumes nix is installed globally and present in $PATH.

local readonly config_difference;
local readonly global_nix_conf_settings="${CACHE_ROOT}/.global-nix-conf"

# `nix show-config` seems to be the only available way of obtaning
# "final" nix configuration, without doing the re-implementation of
# said logic.
# Therefore "experimental-features = nix-command" are needed.

mkdir -p "${CACHE_ROOT}"
# Why not $(nix show-config)? It fails with cryptic 'access-tokens: command not found'
nix show-config --json > "${global_nix_conf_settings}" 2>/dev/null
# shellcheck disable=SC2181
if [ $? -ne 0 ]; then
fail "nix show-config command has failed. Please enable it by following this steps: https://nixos.wiki/wiki/Nix_command"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not add --experimental-features nix-command to the command above?

Also this condition can be reached in cases when installed nix version is below 2.4.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add the flag, I have been stuck thinking about unprivledged user but in other cases it saves the user a trip to nix.conf.

As to nix version... isn't it available even in version 2.0?
https://github.com/NixOS/nix/blob/2.0/src/nix/show-config.cc

fi

config_difference="$(nix-instantiate --strict --eval "${__DIR__}"/nix-conf-diff.nix)"
if [ "${config_difference}" == "{ }" ]; then
return
fi
echo "The configuration of host nix daemon differs from the expected one."
echo "These are the offending settings: "
echo "${config_difference}"
echo "---"
echo "Please update your configuration otherwise the shell may not work as intended."
}

printHelp() {
cat << EOF
Usage: nix-shell.sh [--rcfile] [--vanilla] [--help] -- <PARAMS TO PASS TO NIX-SHELL>
Expand Down Expand Up @@ -162,6 +199,7 @@ setup_nix() {
}

ensure_direnv_is_configured() {
# shellcheck disable=SC2034
local readonly project_root
project_root=$(dirname "$(realpath "${__DIR__}"/..)")
mkdir -p "${CACHE_ROOT}"
Expand All @@ -172,52 +210,25 @@ EOF
}

ensure_nix_is_present() {
if ${IS_NIXOS}; then
# On nixos, nix is installed by default
return
fi

if command -v "nix" >/dev/null 2>&1; then
IS_NIX_INSTALLED=true;
else
IS_NIX_INSTALLED=false;
fi
# We need to distinguish between single-user and multi-user installs.
# This is difficult because there's no official way to do this.
# Details: https://github.com/lilyball/nix-env.fish/blob/00c6cc762427efe08ac0bd0d1b1d12048d3ca727/conf.d/nix-env.fish

# stat is not portable. Splitting the output of ls -nd is reliable on most platforms.
# Global nix installation
if ${IS_NIX_INSTALLED}; then
local readonly nix_store_owner
# shellcheck disable=SC2012
nix_store_owner=$(ls -nd /nix/store | cut -d' ' -f3)
if [ "${nix_store_owner}" -eq 0 ]; then
local readonly is_nix_multiuser_install=true;
else
local readonly is_nix_multiuser_install=false;
fi
else
# shellcheck disable=SC2034
local readonly is_nix_multiuser_install=false;
fi

# Global, single-user installation
if ${IS_NIX_INSTALLED} && ! ${is_nix_multiuser_install}; then
verify_nix_daemon_config_compatibility
return
fi

if ${IS_NIX_INSTALLED} && ${is_nix_multiuser_install}; then
# TODO: Find a solution
fail "Daemon-based nix installation is not supported"
fi

if [ -d "${NIX_STORE}" ]; then
# Nix has already been set up
echo "Detected previous setup in ${CACHE_ROOT}. Will attempt to use it."
return
fi

# No nix installed or nix is multi-user installation
# No nix installed
setup_nix_user_chroot
setup_nix
}
Expand All @@ -228,9 +239,15 @@ ensure_nix_shell_rc_exists() {
: > "${NIX_SHELL_RC}"
if [ -n "${EXTRA_RC}" ]; then cat "${EXTRA_RC}" >> "${NIX_SHELL_RC}"; fi

if ! ${IS_NIXOS} || ${IS_NIX_INSTALLED}; then
# NixOS does not have/use boostraping nix.sh script
if ! ${IS_NIXOS}; then
cat >> "${NIX_SHELL_RC}" <<-EOL
. ${USER_HOME}/.nix-profile/etc/profile.d/nix.sh
EOL
fi

if ${IS_NIX_INSTALLED}; then
cat >> "${NIX_SHELL_RC}" <<-EOL
NIX_CONF_DIR=${NIX_CONF_DIR}
NIX_USER_CONF_FILES=${NIX_USER_CONF_FILES}
EOL
Expand Down Expand Up @@ -279,7 +296,7 @@ ensure_nix_shell_rc_exists
# shellcheck disable=SC1091
. "${__DIR__}/push.sh"

if ! ${IS_NIXOS} && ! ${IS_NIX_INSTALLED}; then
if ! ${IS_NIX_INSTALLED}; then
# shellcheck disable=SC2250
SHELL="$NIX_USER_CHROOT_BIN ${NIX_STORE} bash"
fi
Expand Down