Skip to content

Commit

Permalink
Push the Nix dependency management configuration to the OSS repository.
Browse files Browse the repository at this point in the history
We don't need to hide it.

PR-URL: hasura/graphql-engine-mono#6255
GitOrigin-RevId: 9b46511c6b274dd7e8e52ee74644dc86c7d75872
  • Loading branch information
SamirTalwar authored and hasura-bot committed Oct 11, 2022
1 parent 2f94bcf commit 1ffc193
Show file tree
Hide file tree
Showing 7 changed files with 361 additions and 0 deletions.
53 changes: 53 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env bash

# This file provides some tooling on an opt-in basis via `direnv`
# (https://direnv.net/)

# To use the functionality here, create an `.envrc.local` file in this folder
# that runs the functions you need.
# There is an example in `.envrc.local.example` you can start with

# `use nvm`
# if `nvm` is installed, use it to select the right node.js version
# as defined in the `.nvmrc` file
use_nvm() {
local NVM_DIR
if [[ -z "${XDG_CONFIG_HOME:-}" ]]; then
NVM_DIR="${HOME}/.nvm"
else
NVM_DIR="${XDG_CONFIG_HOME}/nvm"
fi
if ! [[ -d "$NVM_DIR" ]]; then
echo >&2 "ERROR: nvm not found. Could not set the node.js version."
return 1
fi

# shellcheck source=/dev/null
[[ -s "$NVM_DIR/nvm.sh" ]] && \. "$NVM_DIR/nvm.sh" # This loads nvm
nvm use
}

# `use ghcup`
# if `ghcup` is available, use it to install and set the GHC version
# as defined in the `.ghcversion` file
use_ghcup() {
local GHC_VERSION GHCUP_PATH
GHC_VERSION="$(<.ghcversion)"
GHCUP_PATH="$(which ghcup)"
if [[ -z "$GHC_VERSION" ]]; then
echo >&2 'ERROR: Required GHC version not found.'
return 1
fi
if [[ -z "$GHCUP_PATH" ]]; then
echo 'ERROR: ghcup not found. Could not set the GHC version.'
return 1
fi

if ! ghcup whereis ghc "$GHC_VERSION" &> /dev/null; then
ghcup install ghc "$GHC_VERSION"
fi
ghcup set ghc "$GHC_VERSION"
}

# this line sources your `.envrc.local` file
source_env_if_exists .envrc.local
42 changes: 42 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 55 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# This Nix flake defines the dependencies of the Hasura GraphQL Engine.
# Currently, we do not use it for building anything, just for providing a shell.
#
# The shell provides tooling for the Server, CLI, Console, and other components.
# You can start it with `nix develop`, or by using `direnv` (see .envrc).
#
# If you are using macOS, note that we apply a patch to GHC, and therefore all
# tooling needs to be built from scratch. If you're averse to waiting several
# hours for your environment to become usable, you can add @SamirTalwar's Cachix
# repository to save yourself the trouble:
#
# https://app.cachix.org/cache/hasura-samirtalwar#pull
{
description = "Hasura GraphQL Engine";

inputs = {
flake-utils = {
url = github:numtide/flake-utils;
};

nixpkgs = {
url = github:NixOS/nixpkgs;
};
};

outputs =
{ self
, flake-utils
, nixpkgs
}:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
config = {
allowUnfree = true;
};
overlays = [
(import ./nix/overlays/ghc.nix)
];
};
in
{
packages.graphql-parser = (pkgs.haskell.packages.${pkgs.ghcName}.callCabal2nix "graphql-parser" ./server/lib/graphql-parser-hs { }).overrideScope (
self: super: {
hedgehog = self.hedgehog_1_1_1;
}
);

formatter = pkgs.nixpkgs-fmt;

devShells.default = import ./nix/shell.nix { inherit pkgs; };
}
);
}
62 changes: 62 additions & 0 deletions nix/overlays/ghc.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
self: super:
let
versions = import ../versions.nix { pkgs = super; };

ghcVersion = "9.2.4";
ghcName = "ghc${builtins.replaceStrings ["."] [""] ghcVersion}";
ghcPatches =
if super.stdenv.targetPlatform.isDarwin
then [
# Copied from https://github.com/NixOS/nixpkgs/pull/149942
# If the GHC version is updated, we must update the patch URL too.
# ---
# Reverts the linking behavior of GHC to not resolve `-libc++` to `c++`.
# Without this, we get the following error on macOS:
# ghc: loadArchive: Neither an archive, nor a fat archive: `/path/to/clang++'
(super.fetchpatch {
url = "https://raw.githubusercontent.com/input-output-hk/haskell.nix/4b6ee9767daaf5fc1d5419e07733ab006b95ec93/overlays/patches/ghc/ghc-9.2-macOS-loadArchive-fix.patch";
sha256 = "qOfIOqI5oM9695iWtK//OoP7NeF9K6ykGsdSOWJQN/I=";
})
] else [ ];
in
{
haskell = super.haskell // {
compiler = super.haskell.compiler // {
${ghcName} = (versions.ensureVersion super.haskell.compiler.${ghcName}).overrideAttrs (oldAttrs: {
patches = (if oldAttrs ? patches then oldAttrs.patches else [ ]) ++ ghcPatches;
});
};

packages = super.haskell.packages // {
${ghcName} = super.haskell.packages.${ghcName}.override {
overrides = hself: hsuper:
if super.stdenv.targetPlatform.isDarwin
then
# macOS-specific overrides:
let
# Ormolu v0.5.0.1 doesn't build correctly on aarch64-darwin.
# Disabling the "fixity-th" flag seems to fix it.
# https://github.com/tweag/ormolu/issues/927
fixOrmolu = p: super.lib.pipe p [
(super.haskell.lib.compose.addExtraLibrary hself.file-embed)
(super.haskell.lib.compose.disableCabalFlag "fixity-th")
];
in
{
# On aarch64-darwin, this creates a cycle for some reason; didn't look too much into it.
ghcid = super.haskell.lib.overrideCabal hsuper.ghcid (drv: { enableSeparateBinOutput = false; });
# See above.
ormolu = hself.ormolu_0_5_0_1;
ormolu_0_5_0_1 = fixOrmolu hsuper.ormolu_0_5_0_1;
fourmolu = hself.fourmolu_0_8_2_0;
fourmolu_0_8_2_0 = fixOrmolu hsuper.fourmolu_0_8_2_0;
}
else
# We don't need to override anything on Linux:
{ };
};
};
};

inherit ghcVersion ghcName;
}
132 changes: 132 additions & 0 deletions nix/shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
{ pkgs }:
let
versions = import ./versions.nix { inherit pkgs; };

# Unix ODBC Support
freetdsWithODBC = pkgs.freetds.override {
odbcSupport = true;
inherit (pkgs) unixODBC;
};

# Verify this works by running `odbcinst -q -d`.
# The output should be the headings from the odbcinst.ini file.
# (You can easily see the generated file by running `cat $ODBCINSTINI`.)
# If you see any errors, please contact your friendly MSSQL and/or Nix expert.
odbcinstFile =
let msodbcsql = pkgs.unixODBCDrivers.msodbcsql17;
in
pkgs.writeTextFile {
name = "odbcinst.ini";
text = ''
[${msodbcsql.fancyName}]
Description = ${msodbcsql.meta.description}
Driver = ${msodbcsql}/${msodbcsql.driver}
'';
};

baseInputs = [
pkgs.stdenv
pkgs.jq
];

consoleInputs = [
pkgs.google-cloud-sdk
pkgs."nodejs-${versions.nodejsVersion}_x"
];

docsInputs = [
pkgs.yarn
];

integrationTestInputs = [
pkgs.python3
];

# The version of GHC in `ghcName` is set in nix/overlays/ghc.nix.
#
# We list top-level packages before packages scoped to the GHC version, so
# that they appear first in the PATH. Otherwise we might end up with older
# versions of transitive dependencies (e.g. HLS depending on Ormolu).
haskellInputs = [
pkgs.cabal2nix

# The correct version of GHC.
pkgs.haskell.compiler.${pkgs.ghcName}

# We use the default versions of these packages.
(versions.ensureVersion pkgs.haskellPackages.hlint)
(versions.ensureVersion pkgs.haskellPackages.hpack)
(versions.ensureVersion pkgs.haskellPackages.ormolu)

# We build these packages using our custom GHC.
pkgs.haskell.packages.${pkgs.ghcName}.alex
pkgs.haskell.packages.${pkgs.ghcName}.apply-refact
pkgs.haskell.packages.${pkgs.ghcName}.cabal-install
pkgs.haskell.packages.${pkgs.ghcName}.ghcid
pkgs.haskell.packages.${pkgs.ghcName}.happy
pkgs.haskell.packages.${pkgs.ghcName}.haskell-language-server
pkgs.haskell.packages.${pkgs.ghcName}.hoogle
pkgs.haskell.packages.${pkgs.ghcName}.hspec-discover
];

devInputs = [
pkgs.nixpkgs-fmt
pkgs.shellcheck
];

ciInputs = [
pkgs.go
];

dynamicLibraries = [
pkgs.gmp
pkgs.libkrb5 # Includes required `gssapi` headers.
pkgs.ncurses
pkgs.openssl_3
pkgs.pcre
pkgs.zlib
pkgs.zstd

# PostgreSQL, Microsoft SQL Server, & MySQL dependencies.
freetdsWithODBC
pkgs.libmysqlclient
pkgs.mariadb
pkgs.postgresql
pkgs.unixODBC
]
# Linux-specific libraries.
++ pkgs.lib.optionals pkgs.stdenv.targetPlatform.isLinux [
pkgs.stdenv.cc.cc.lib
# Microsoft SQL Server drivers don't work on aarch64 yet.
pkgs.unixODBCDrivers.msodbcsql17
];

includeLibraries = [
pkgs.libkrb5.dev
pkgs.ncurses.dev
pkgs.openssl_3.dev
pkgs.pcre.dev
pkgs.zlib.dev
];

serverDeps =
haskellInputs
++ dynamicLibraries
++ includeLibraries
++ integrationTestInputs;
in
pkgs.mkShell {
buildInputs = baseInputs ++ consoleInputs ++ docsInputs ++ serverDeps ++ devInputs ++ ciInputs;

# We set the ODBCINSTINI to the file defined above, which points to the MSSQL ODBC driver.
# The path is relative to `ODBCSYSINI`, which we set to empty.
# Microsoft SQL Server drivers don't work on aarch64 yet, so we also disable this.
ODBCSYSINI = "";
ODBCINSTINI = pkgs.lib.strings.optionalString pkgs.stdenv.targetPlatform.isLinux "${odbcinstFile}";

LD_LIBRARY_PATH = pkgs.lib.strings.makeLibraryPath dynamicLibraries;
shellHook = pkgs.lib.strings.optionalString pkgs.stdenv.targetPlatform.isDarwin ''
# Without this, GHC will use the system `libcrypto` and `libssl` libraries, which fail.
export DYLD_LIBRARY_PATH="$LD_LIBRARY_PATH";
'';
}
14 changes: 14 additions & 0 deletions nix/versions.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{ pkgs }:
let
versions = pkgs.lib.trivial.importJSON ../server/VERSIONS.json;
in
{
ensureVersion = package:
let expected = versions.${package.pname};
in
if expected == package.version
then package
else throw "Invalid version for package ${package.pname}: expected ${expected}, got ${package.version}";

nodejsVersion = pkgs.lib.strings.fileContents ../.nvmrc;
}
3 changes: 3 additions & 0 deletions shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# See flake.nix for commentary before using this.
{ system ? builtins.currentSystem }:
(builtins.getFlake (toString ./.)).devShells.${system}

0 comments on commit 1ffc193

Please sign in to comment.