diff --git a/flake.nix b/flake.nix index 86d0572fe..58e2561c4 100644 --- a/flake.nix +++ b/flake.nix @@ -1,37 +1,38 @@ { description = "Comm flake"; inputs = { utils.url = "github:numtide/flake-utils"; nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; }; outputs = { self, nixpkgs, utils, ... }: let # Overlays allow for extending a package set, in this case, we are # extending nixpkgs with our devShell localOverlay = import ./nix/overlay.nix; overlays = [ localOverlay + (_: _: { commSrc = toString self; } ) ]; # Since we build for many systems (e.g. aarch64, x86_64-linux), we # create a helper function to help facilitate instantiation of the related # package set pkgsForSystem = system: import nixpkgs { inherit overlays system; }; # utils.lib.eachSystem helps create a result set of expected flake outputs # of the form . # https://github.com/numtide/flake-utils#usage for more examples in utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ] (system: rec { legacyPackages = pkgsForSystem system; inherit (legacyPackages) devShell devShells; }) // { # these outputs will lack the system suffix (e.g. # devShell.aarch64-darwin), thus should be system agnostic such as # overlays or utility functions. overlays.default = localOverlay; }; } diff --git a/nix/dev-shell.nix b/nix/dev-shell.nix index 8beeafc09..8bd9d3b43 100644 --- a/nix/dev-shell.nix +++ b/nix/dev-shell.nix @@ -1,149 +1,151 @@ { mkShell , stdenv , lib , amqp-cpp , arcanist , aws-sdk-cpp , better-prompt , boost , bundler , c-ares_cmake-config , cmake , cmake-format , cocoapods , corrosion , cryptopp , darwin , double-conversion , folly , fmt , glog , grpc , gtest , libiconv , libuv , localstack , mariadb , mariadb-up , nodejs-16_x-openssl_1_1 , olm , openjdk11 , openssl , pkg-config , protobuf_3_15_cmake , python3 +, rabbitmq-server , redis , redis-up , rustup , shellcheck , sqlite , terraform , watchman , rustfmt , yarn }: mkShell { # programs which are meant to be executed should go here nativeBuildInputs = [ # generic development or tools arcanist shellcheck terraform # android openjdk11 # node development mariadb nodejs-16_x-openssl_1_1 yarn watchman # react native python3 redis # native dependencies # C/CXX toolchains are already brought in with mkShell # Identity Service rustfmt rustup # Tunnelbroker + CMake amqp-cpp c-ares_cmake-config cryptopp cmake cmake-format # linting libuv # Localstack is currently broken by partial update # See https://github.com/NixOS/nixpkgs/pull/197572 #localstack pkg-config protobuf_3_15_cmake grpc + rabbitmq-server # runtime service ] ++ lib.optionals stdenv.isDarwin [ cocoapods # needed for ios bundler ]; # include any libraries buildInputs buildInputs = [ # protobuf exposes both a library and a command # thus should appear in both inputs protobuf_3_15_cmake aws-sdk-cpp # tunnelbroker corrosion # tunnelbroker double-conversion # tunnelbroker glog # tunnelbroker gtest # testing services folly # cpp tools fmt # needed for folly boost # needed for folly olm # needed for CryptoTools sqlite # needed for sqlite_orm openssl # needed for grpc ] ++ lib.optionals stdenv.isDarwin (with darwin.apple_sdk.frameworks; [ CoreFoundation CoreServices Security libiconv # identity service ]); JAVA_HOME = openjdk11.passthru.home; # shell commands to be ran upon entering shell shellHook = '' PRJ_ROOT=$(git rev-parse --show-toplevel) # Set development environment variable defaults source "${../scripts/source_development_defaults.sh}" # Cache development path for some use cases such as XCode "$PRJ_ROOT/scripts/save_path.sh" '' # Darwin condition can be removed once linux services are supported + lib.optionalString stdenv.isDarwin '' # Start MariaDB development services "${mariadb-up}"/bin/mariadb-up & mariadb_pid=$! "${redis-up}"/bin/redis-up & redis_pid=$! wait "$mariadb_pid" "$redis_pid" '' + '' # Render default configuration for keyserver $PRJ_ROOT/scripts/create_url_facts.sh # Ensure rustup tooling is installed $PRJ_ROOT/scripts/ensure_rustup_setup.sh # Provide decent bash prompt source "${better-prompt}/bin/better-prompt" echo "Welcome to Comm dev environment! :)" ''; } diff --git a/nix/overlay.nix b/nix/overlay.nix index fb5029245..eba54f241 100644 --- a/nix/overlay.nix +++ b/nix/overlay.nix @@ -1,96 +1,98 @@ # An overlay allows for a package set to be extended with new or modified packages # `final` refers to the package set with all overlays applied. # This allows for added or modified packages to be referenced with # all relevant changes final: # `prev` refers to the previous package set before this current overlay is applied. # This is cheaper for nix to evaluate, thus should be prefered over final when possible. prev: { # Patch aws-sdk-cpp to automatically pick up header location # specific to nixpkgs, as nixpkgs separates build-time and runtime # depencenies (a saving of 400MB in header + generated files). # In the case of c and c++, this means the header files are # located in a separate directory from the libraries. # # From a developer perspective, this avoids having to manually specify # the header location with `-DAWS_CORE_HEADER_FILE` each time # one invokes `cmake` on the command line when using # `find_package(AWSSDK COMPONENTS [comps])` # # For more information, see: # - aws-sdk-cpp issue: https://github.com/aws/aws-sdk-cpp/issues/2009 # - Nixpkgs fix: https://github.com/NixOS/nixpkgs/pull/182918 aws-sdk-cpp = (prev.aws-sdk-cpp.overrideAttrs(oldAttrs:{ postPatch = oldAttrs.postPatch + '' substituteInPlace cmake/AWSSDKConfig.cmake \ --replace 'C:/AWSSDK/''${AWSSDK_INSTALL_INCLUDEDIR}/aws/core' \ 'C:/AWSSDK/''${AWSSDK_INSTALL_INCLUDEDIR}/aws/core" "${placeholder "dev"}/include/aws/core' ''; })).override { # avoid rebuildilng all 300+ apis apis = [ "core" "s3" "dynamodb" ]; }; # add packages meant for just this repository amqp-cpp = prev.callPackage ./amqp-cpp.nix { }; arcanist = prev.callPackage ./arcanist.nix { }; better-prompt = prev.callPackage ./better-prompt.nix { }; # c-ares is used to bootstrap curl, so cmake is not available in the default # build c-ares_cmake-config = prev.c-ares.overrideAttrs(o: { nativeBuildInputs = (o.nativeBuildInputs or []) ++ [ prev.cmake ]; }); protobuf_3_15_cmake = prev.callPackage ./protobuf_3_15.nix { }; devShells.default = final.callPackage ./dev-shell.nix { }; devShell = final.devShells.default; localstack-down = prev.callPackage ./localstack-down.nix { }; localstack-up = prev.callPackage ./localstack-up.nix { }; # Make our version of mariadb the default everywhere mariadb = prev.mariadb_108; mariadb-up = prev.callPackage ./mariadb-up-mac.nix { }; mysql-down = prev.callPackage ./mysql-down-linux.nix { }; mysql-up = prev.callPackage ./mysql-up-linux.nix { }; redis-up = prev.callPackage ./redis-up-mac.nix { }; olm = prev.olm.overrideAttrs(oldAttrs: { # *.hh files aren't meant to be used externally # so we patch installation to add it postInstall = '' cp \ $NIX_BUILD_TOP/${oldAttrs.src.name}/include/olm/*.h* \ ''${!outputDev}/include/olm ''; }); corrosion = prev.corrosion.overrideAttrs(_: { patches = [ # Fix logic around finding cargo and rustc when not managed by rustup (prev.fetchpatch { url = "https://github.com/corrosion-rs/corrosion/commit/d5330b3f03c7abb4e4da71e35654fa03ecb778bb.patch"; sha256 = "sha256-jrA30bWNWprkqCiedf+xL7GlR9+9jgOyKAoTPVKkB9c="; }) ]; }); + rabbitmq-up = prev.callPackage ./rabbitmq-up-mac.nix { }; + # Ensure that yarn is using the pinned version yarn = prev.yarn.override (_: { nodejs = final.nodejs-16_x-openssl_1_1; }); } diff --git a/nix/rabbitmq-up-mac.nix b/nix/rabbitmq-up-mac.nix new file mode 100644 index 000000000..7055c2d7c --- /dev/null +++ b/nix/rabbitmq-up-mac.nix @@ -0,0 +1,27 @@ +{ lib +, rabbitmq-server +, writeShellApplication +, commSrc +}: + +# writeShellApplication is a "writer helper" which +# will create a shellchecked executable shell script located in $out/bin/ +# This shell script will be used to allow for impure+stateful actions +writeShellApplication { + name = "rabbitmq-up"; + runtimeInputs = [ rabbitmq-server ]; + text = '' + RABBITMQ_HOME=''${XDG_DATA_HOME:-$HOME/.local/share}/RabbitMQ + RABBITMQ_PIDFILE=''${RABBITMQ_HOME}/rabbitmq.pid + + "${commSrc}/scripts/start_comm_daemon.sh" \ + beam.smp \ + RabbitMQ \ + "${commSrc}/scripts/start_rabbitmq.sh" \ + "$RABBITMQ_PIDFILE" + + # Explicitly exit this script so the parent shell can determine + # when it's safe to return control of terminal to user + exit 0 + ''; +} diff --git a/scripts/source_development_defaults.sh b/scripts/source_development_defaults.sh index 12cfa2722..b7bf915dc 100644 --- a/scripts/source_development_defaults.sh +++ b/scripts/source_development_defaults.sh @@ -1,36 +1,48 @@ #!/usr/bin/env bash if [[ "$OSTYPE" == 'linux'* ]]; then export MYSQL_UNIX_PORT="${XDG_RUNTIME_DIR:-/run/user/$UID}/mysql.sock" export ANDROID_HOME="${ANDROID_HOME:-$HOME/Android/Sdk}" fi if [[ "$OSTYPE" == 'darwin'* ]]; then MARIADB_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/MariaDB" export MYSQL_UNIX_PORT="$MARIADB_DIR"/mysql.sock export ANDROID_HOME="${ANDROID_HOME:-$HOME/Library/Android/sdk}" fi +# User defaults of +# https://www.rabbitmq.com/configure.html#supported-environment-variables +export RABBITMQ_NODENAME=comm +export RABBITMQ_DEFAULT_PASS=comm +export RABBITMQ_DEFAULT_USER=comm +export RABBITMQ_HOME=${XDG_DATA_HOME:-$HOME/.local/share}/RabbitMQ +export RABBITMQ_MNESIA_BASE=${RABBITMQ_HOME}/mnesia +export RABBITMQ_LOG_BASE=${RABBITMQ_HOME}/logs +export RABBITMQ_LOGS=${RABBITMQ_LOG_BASE}/comm.log +export RABBITMQ_PLUGINS_EXPAND_DIR=${RABBITMQ_HOME}/plugins_expand +export RABBITMQ_PID_FILE=${RABBITMQ_HOME}/rabbitmq.pid + export PATH="$PATH":"$ANDROID_HOME"/emulator:"$ANDROID_HOME"/tools export PATH="$PATH":"$ANDROID_HOME"/tools/bin:"$ANDROID_HOME"/platform-tools # ANDROID_SDK_ROOT is deprecated, but it's still used by some tooling # such as sdkmanager. ANDROID_HOME is the new prefered env var. export ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT:-$ANDROID_HOME}" export PATH="$PATH":./node_modules/.bin # mysql2 package wants stable prefixes for temporary directory paths # 'nix develop' will set TMP and related variables to something different each # invocation export TMP=/tmp/app.comm export TEMP="$TMP" export TMPDIR="$TMP" export TEMPDIR="$TMP" mkdir -p "$TMP" # For cargo + rustup applications, ensure cargo user bin directory is on path if [[ ! "$PATH" =~ \.cargo/bin ]]; then export PATH="$PATH":${HOME}/.cargo/bin fi diff --git a/scripts/start_rabbitmq.sh b/scripts/start_rabbitmq.sh new file mode 100755 index 000000000..0a2bd7913 --- /dev/null +++ b/scripts/start_rabbitmq.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -eou pipefail + +if ! command -v rabbitmq-server > /dev/null; then + echo "Please install rabbitmq-server or run 'nix develop'" >&2 + exit 1 +fi + +SCRIPT_DIR=$(cd "$(dirname "$0")"; pwd -P) + +# shellcheck source=/dev/null +source "${SCRIPT_DIR}/source_development_defaults.sh" + +# RabbitMQ is mostly configured through environment variables +# located in scripts/source_development_defaults.sh +mkdir -p "$RABBITMQ_LOG_BASE" + +echo "View RabbitMQ logs: tail -f $RABBITMQ_LOGS" >&2 +echo "Kill RabbitMQ server: pkill rabbitmq-server beam.smp" >&2 + +# 'exec' allows for us to replace bash process with RabbitMQ +exec rabbitmq-server > "$RABBITMQ_LOG_BASE/startup.log"