Skip to content
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
Copy Markdown
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
Copy Markdown
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