mirror of
https://github.com/haskell/ghcide.git
synced 2024-09-11 05:36:09 +03:00
Add a GitHub action for the Nix build (#918)
* Add an action to build and cache the nix-shell * [nix] ghc-paths must always be in the package set Otherwise ghc-check will not get the Nix libdir and fail at compile time * [nix] extract the nixpkgs instantiation to nix/default.nix * [nix] niv init * [nix] switch to haskell-updates * Mention the Cachix binary cache in the README * [nix] pin the version used to set up Cachix * [nix] disable tests and jailbreak 8.10.x packages * [nix] rely on cabal2nix to enumerate the dependencies * [nix] install haskell tools from the Nix cache
This commit is contained in:
parent
863392b9b9
commit
90b859b202
23
.github/workflows/nix.yml
vendored
Normal file
23
.github/workflows/nix.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
name: Nix
|
||||
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
nix:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ghc: ['default', 'ghc8102', 'ghc884', 'ghc865']
|
||||
os: [ubuntu-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cachix/install-nix-action@v12
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-20.03
|
||||
- uses: cachix/cachix-action@v7
|
||||
with:
|
||||
name: haskell-ghcide
|
||||
signingKey: '${{ secrets.GHCIDE_CACHIX_SIGNING_KEY }}'
|
||||
- run: nix-shell --argstr compiler ${{ matrix.ghc }} --run "cabal update && cabal build"
|
@ -325,6 +325,8 @@ To build and work on `ghcide` itself, you should use cabal, e.g.,
|
||||
running `cabal test` will execute the test suite. You can use `stack test` too, but
|
||||
note that some tests will fail, and none of the maintainers are currently using `stack`.
|
||||
|
||||
If you are using Nix, there is a Cachix nix-shell cache for all the supported platforms: `cachix use haskell-ghcide`.
|
||||
|
||||
If you are using Windows, you should disable the `auto.crlf` setting and configure your editor to use LF line endings, directly or making it use the existing `.editor-config`.
|
||||
|
||||
If you are chasing down test failures, you can use the tasty-rerun feature by running tests as
|
||||
|
29
nix/default.nix
Normal file
29
nix/default.nix
Normal file
@ -0,0 +1,29 @@
|
||||
{ sources ? import ./sources.nix }:
|
||||
let
|
||||
overlay = _self: pkgs:
|
||||
let sharedOverrides = {
|
||||
overrides = _self: super: {
|
||||
mkDerivation = args: super.mkDerivation (args //
|
||||
{
|
||||
# skip running tests for Hackage packages
|
||||
doCheck =
|
||||
# but not for ghcide
|
||||
args.version == "0";
|
||||
# relax upper bounds
|
||||
jailbreak = args.pname != "jailbreak-cabal";
|
||||
});
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
ourHaskell = pkgs.haskell // {
|
||||
packages = pkgs.haskell.packages // {
|
||||
# relax upper bounds on ghc 8.10.x versions (and skip running tests)
|
||||
ghc8101 = pkgs.haskell.packages.ghc8101.override sharedOverrides;
|
||||
ghc8102 = pkgs.haskell.packages.ghc8102.override sharedOverrides;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in import sources.nixpkgs
|
||||
{ overlays = [ overlay ] ; config = {allowBroken = true;}; }
|
@ -12,15 +12,15 @@
|
||||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||
},
|
||||
"nixpkgs": {
|
||||
"branch": "nixpkgs-unstable",
|
||||
"branch": "haskell-updates",
|
||||
"description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to",
|
||||
"homepage": "https://github.com/NixOS/nixpkgs",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs-channels",
|
||||
"rev": "f9567594d5af2926a9d5b96ae3bada707280bec6",
|
||||
"sha256": "0vr2di6z31c5ng73f0cxj7rj9vqvlvx3wpqdmzl0bx3yl3wr39y6",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4fea8c85a109c57e945c5047f78b399d169e2577",
|
||||
"sha256": "0j9hqaa37400lpmdrgm8sq84ylbyrda21dv1rydn6sdx3lqn72fg",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs-channels/archive/f9567594d5af2926a9d5b96ae3bada707280bec6.tar.gz",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/4fea8c85a109c57e945c5047f78b399d169e2577.tar.gz",
|
||||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||
}
|
||||
}
|
||||
|
@ -12,36 +12,29 @@ let
|
||||
else
|
||||
pkgs.fetchurl { inherit (spec) url sha256; };
|
||||
|
||||
fetch_tarball = pkgs: spec:
|
||||
if spec.builtin or true then
|
||||
builtins_fetchTarball { inherit (spec) url sha256; }
|
||||
else
|
||||
pkgs.fetchzip { inherit (spec) url sha256; };
|
||||
fetch_tarball = pkgs: name: spec:
|
||||
let
|
||||
ok = str: ! builtins.isNull (builtins.match "[a-zA-Z0-9+-._?=]" str);
|
||||
# sanitize the name, though nix will still fail if name starts with period
|
||||
name' = stringAsChars (x: if ! ok x then "-" else x) "${name}-src";
|
||||
in
|
||||
if spec.builtin or true then
|
||||
builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
|
||||
else
|
||||
pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
|
||||
|
||||
fetch_git = spec:
|
||||
builtins.fetchGit { url = spec.repo; inherit (spec) rev ref; };
|
||||
|
||||
fetch_builtin-tarball = spec:
|
||||
builtins.trace
|
||||
''
|
||||
WARNING:
|
||||
The niv type "builtin-tarball" will soon be deprecated. You should
|
||||
instead use `builtin = true`.
|
||||
fetch_local = spec: spec.path;
|
||||
|
||||
$ niv modify <package> -a type=tarball -a builtin=true
|
||||
''
|
||||
builtins_fetchTarball { inherit (spec) url sha256; };
|
||||
fetch_builtin-tarball = name: throw
|
||||
''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
|
||||
$ niv modify ${name} -a type=tarball -a builtin=true'';
|
||||
|
||||
fetch_builtin-url = spec:
|
||||
builtins.trace
|
||||
''
|
||||
WARNING:
|
||||
The niv type "builtin-url" will soon be deprecated. You should
|
||||
instead use `builtin = true`.
|
||||
|
||||
$ niv modify <package> -a type=file -a builtin=true
|
||||
''
|
||||
(builtins_fetchurl { inherit (spec) url sha256; });
|
||||
fetch_builtin-url = name: throw
|
||||
''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
|
||||
$ niv modify ${name} -a type=file -a builtin=true'';
|
||||
|
||||
#
|
||||
# Various helpers
|
||||
@ -72,13 +65,23 @@ let
|
||||
if ! builtins.hasAttr "type" spec then
|
||||
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
|
||||
else if spec.type == "file" then fetch_file pkgs spec
|
||||
else if spec.type == "tarball" then fetch_tarball pkgs spec
|
||||
else if spec.type == "tarball" then fetch_tarball pkgs name spec
|
||||
else if spec.type == "git" then fetch_git spec
|
||||
else if spec.type == "builtin-tarball" then fetch_builtin-tarball spec
|
||||
else if spec.type == "builtin-url" then fetch_builtin-url spec
|
||||
else if spec.type == "local" then fetch_local spec
|
||||
else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
|
||||
else if spec.type == "builtin-url" then fetch_builtin-url name
|
||||
else
|
||||
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
|
||||
|
||||
# If the environment variable NIV_OVERRIDE_${name} is set, then use
|
||||
# the path directly as opposed to the fetched source.
|
||||
replace = name: drv:
|
||||
let
|
||||
saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
|
||||
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
|
||||
in
|
||||
if ersatz == "" then drv else ersatz;
|
||||
|
||||
# Ports of functions for older nix versions
|
||||
|
||||
# a Nix version of mapAttrs if the built-in doesn't exist
|
||||
@ -87,13 +90,23 @@ let
|
||||
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
|
||||
);
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
|
||||
range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
|
||||
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
|
||||
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
|
||||
concatStrings = builtins.concatStringsSep "";
|
||||
|
||||
# fetchTarball version that is compatible between all the versions of Nix
|
||||
builtins_fetchTarball = { url, sha256 }@attrs:
|
||||
builtins_fetchTarball = { url, name, sha256 }@attrs:
|
||||
let
|
||||
inherit (builtins) lessThan nixVersion fetchTarball;
|
||||
in
|
||||
if lessThan nixVersion "1.12" then
|
||||
fetchTarball { inherit url; }
|
||||
fetchTarball { inherit name url; }
|
||||
else
|
||||
fetchTarball attrs;
|
||||
|
||||
@ -115,13 +128,13 @@ let
|
||||
then abort
|
||||
"The values in sources.json should not have an 'outPath' attribute"
|
||||
else
|
||||
spec // { outPath = fetch config.pkgs name spec; }
|
||||
spec // { outPath = replace name (fetch config.pkgs name spec); }
|
||||
) config.sources;
|
||||
|
||||
# The "config" used by the fetchers
|
||||
mkConfig =
|
||||
{ sourcesFile ? ./sources.json
|
||||
, sources ? builtins.fromJSON (builtins.readFile sourcesFile)
|
||||
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
|
||||
, sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
|
||||
, pkgs ? mkPkgs sources
|
||||
}: rec {
|
||||
# The sources, i.e. the attribute set of spec name to spec
|
||||
@ -130,5 +143,6 @@ let
|
||||
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
|
||||
inherit pkgs;
|
||||
};
|
||||
|
||||
in
|
||||
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }
|
||||
|
100
shell.nix
100
shell.nix
@ -1,93 +1,30 @@
|
||||
# This shell.nix file is designed for use with cabal build
|
||||
# It aims to leverage the nix cache in as much as possible
|
||||
# while reducing Nix maintenance costs.
|
||||
# It does **not** aim to replace Cabal/Stack with Nix
|
||||
# It does **not** aim to replace Cabal
|
||||
|
||||
# Maintaining this file:
|
||||
#
|
||||
# - Dealing with broken nix-shell
|
||||
#
|
||||
# 1. Bump the nixpkgs version using `niv update nixpkgs`
|
||||
# 2. Comment out any remaining failing packages
|
||||
#
|
||||
# - Dealing with broken cabal build inside nix-shell:
|
||||
#
|
||||
# If my understanding of cabal new-build is correct this should never happen,
|
||||
# assuming that cabal new-build does succeed outside nix-shell
|
||||
# - Bump the nixpkgs version using `niv update nixpkgs`
|
||||
|
||||
{ sources ? import nix/sources.nix,
|
||||
nixpkgs ? import sources.nixpkgs {},
|
||||
compiler ? "default",
|
||||
hoogle ? false
|
||||
{ compiler ? "default",
|
||||
withHoogle ? false,
|
||||
nixpkgs ? import ./nix {}
|
||||
}:
|
||||
|
||||
with nixpkgs;
|
||||
|
||||
let defaultCompiler = "ghc" + lib.replaceStrings ["."] [""] haskellPackages.ghc.version;
|
||||
haskellPackagesForProject = p:
|
||||
if compiler == "default" || compiler == defaultCompiler
|
||||
then if hoogle
|
||||
then haskellPackages.ghcWithHoogle p
|
||||
else haskellPackages.ghcWithPackages p
|
||||
# for all other compilers there is no Nix cache so dont bother building deps
|
||||
else if hoogle
|
||||
then haskell.packages.${compiler}.ghcWithHoogle (_: [])
|
||||
else haskell.packages.${compiler}.ghcWithPackages (_: []);
|
||||
|
||||
compilerWithPackages = haskellPackagesForProject(p:
|
||||
with p;
|
||||
[ aeson
|
||||
async
|
||||
base16-bytestring
|
||||
Chart
|
||||
Chart-diagrams
|
||||
cryptohash-sha1
|
||||
data-default
|
||||
diagrams
|
||||
diagrams-svg
|
||||
extra
|
||||
fuzzy
|
||||
fingertree
|
||||
Glob
|
||||
ghc-check
|
||||
gitrev
|
||||
happy
|
||||
haskell-lsp
|
||||
haskell-lsp-types
|
||||
hie-bios
|
||||
hslogger
|
||||
lens
|
||||
lsp-test
|
||||
network
|
||||
optparse-applicative
|
||||
QuickCheck
|
||||
quickcheck-instances
|
||||
prettyprinter
|
||||
prettyprinter-ansi-terminal
|
||||
regex-tdfa
|
||||
rope-utf16-splay
|
||||
safe
|
||||
safe-exceptions
|
||||
shake
|
||||
sorted-list
|
||||
stm
|
||||
syb
|
||||
tasty
|
||||
tasty-expected-failure
|
||||
tasty-hunit
|
||||
tasty-rerun
|
||||
tasty-quickcheck
|
||||
temporary
|
||||
text
|
||||
time
|
||||
transformers
|
||||
typed-process
|
||||
unordered-containers
|
||||
utf8-string
|
||||
yaml
|
||||
]);
|
||||
haskellPackagesForProject =
|
||||
if compiler == "default"
|
||||
then ourHaskell.packages.${defaultCompiler}
|
||||
else ourHaskell.packages.${compiler};
|
||||
ghcide = p: haskell.lib.doCheck
|
||||
(p.callCabal2nixWithOptions "ghcide" ./. "--benchmark" {});
|
||||
isSupported = compiler == "default" || compiler == defaultCompiler;
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
name = "ghcide";
|
||||
haskellPackagesForProject.shellFor {
|
||||
inherit withHoogle;
|
||||
doBenchmark = true;
|
||||
packages = p: [ (if isSupported then ghcide p else p.ghc-paths) ];
|
||||
buildInputs = [
|
||||
gmp
|
||||
zlib
|
||||
@ -97,9 +34,6 @@ stdenv.mkDerivation {
|
||||
haskellPackages.hlint
|
||||
haskellPackages.ormolu
|
||||
haskellPackages.stylish-haskell
|
||||
|
||||
compilerWithPackages
|
||||
|
||||
];
|
||||
src = null;
|
||||
shellHook = ''
|
||||
|
Loading…
Reference in New Issue
Block a user