From c9b0e3051cd13b925dc5e9edb8fb9c352052b3b8 Mon Sep 17 00:00:00 2001 From: Greg Hale Date: Mon, 18 Jun 2018 08:17:17 -0400 Subject: [PATCH] Try using nix for running tests on travis and improve nix shell --- .gitmodules | 12 ----- .travis.yml | 47 +++--------------- default.nix | 34 +++++++++++++ deps/http-api-data | 1 - deps/reflex-platform | 1 - deps/servant | 1 - deps/servant-snap | 1 - nix.conf | 3 ++ nix/reflex-platform.nix | 9 ++++ nix/servant-reflex.nix | 14 ++++++ nix/testdriver.nix | 3 ++ nix/testresults.nix | 22 +++++++++ nix/testserver.nix | 25 ++++++++++ release.nix | 27 +++++++++++ shell.nix | 3 ++ testdriver/default.nix | 16 ++++++ testdriver/shell.nix | 1 + testdriver/test/Servant/ReflexSpec.hs | 2 +- testserver/API.hs | 70 ++++++++++++++++++++++++++- testserver/Main.hs | 11 +++-- testserver/default.nix | 14 ++++++ testserver/shell.nix | 1 + testserver/testserver.cabal | 1 + 23 files changed, 259 insertions(+), 60 deletions(-) create mode 100644 default.nix delete mode 160000 deps/http-api-data delete mode 160000 deps/reflex-platform delete mode 160000 deps/servant delete mode 160000 deps/servant-snap create mode 100644 nix.conf create mode 100644 nix/reflex-platform.nix create mode 100644 nix/servant-reflex.nix create mode 100644 nix/testdriver.nix create mode 100644 nix/testresults.nix create mode 100644 nix/testserver.nix create mode 100644 release.nix create mode 100644 shell.nix create mode 100644 testdriver/default.nix create mode 100644 testdriver/shell.nix mode change 120000 => 100644 testserver/API.hs create mode 100644 testserver/default.nix create mode 100644 testserver/shell.nix diff --git a/.gitmodules b/.gitmodules index 84884b3..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +0,0 @@ -[submodule "deps/http-api-data"] - path = deps/http-api-data - url = https://github.com/fizruk/http-api-data -[submodule "deps/servant"] - path = deps/servant - url = https://github.com/haskell-servant/servant -[submodule "deps/servant-snap"] - path = deps/servant-snap - url = https://github.com/haskell-servant/servant-snap -[submodule "deps/reflex-platform"] - path = deps/reflex-platform - url = https://github.com/reflex-frp/reflex-platform diff --git a/.travis.yml b/.travis.yml index 28eb6a5..e0478ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,53 +1,22 @@ -sudo: required - -before_cache: - - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log - - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar - -addons: - apt: - - phantomjs - -matrix: - include: - - env: CABALVER=1.24 GHCVER=7.10.3 - compiler: ": #GHC 7.10.3" - addons: {apt: {packages: [cabal-install-1.24,ghc-7.10.3], sources: [hvr-ghc]}} - - env: CABALVER=1.24 GHCVER=8.0.1 - compiler: ": #GHC 8.0.1" - addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1], sources: [hvr-ghc]}} +language: nix +cache: false before_install: - unset CC - - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH - - git submodule update --init --recursive install: - - cabal --version - - BENCH=${BENCH---enable-benchmarks} - - TEST=${TEST---enable-tests} - - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]" - - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ]; - then - zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz > - $HOME/.cabal/packages/hackage.haskell.org/00-index.tar; - fi - - travis_retry cabal update -v - - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config - - deps/reflex-platform/work-on ./overrides-ghc.nix ./testserver --command "cd testserver && cabal configure -fExample && cabal build" - - deps/reflex-platform/work-on ghc ./testdriver --command "cd testdriver && cabal configure && cabal build" - - cd testserver && dist/build/back/back -p 8000 & - - sleep 3 - - phantomjs --webdriver=127.0.0.1:4444 & - - sleep 3 script: + - git clone https://github.com/reflex-frp/reflex-platform + - cd reflex-platform && sudo echo "Yes" | ./try-reflex --command "exit 0" + - strace nix build -f ../release.nix servant-reflex + + - nix build -f ./release.nix servant-reflex --substituters https://cache.nixos.org --substituters https://nixcache.reflex-frp.org + - nix build -f ./release.nix testresults - git config --global user.email "travis-ci@example.com" - git config --global user.name "Travis-CI" - - ./build.sh - # - testdriver/dist/build/spec/spec cache: directories: diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..c9b95ae --- /dev/null +++ b/default.nix @@ -0,0 +1,34 @@ +{ mkDerivation, aeson, base, bytestring, case-insensitive +, containers, data-default, exceptions, ghcjs-dom, http-api-data +, http-media, jsaddle, mtl, network-uri, reflex, reflex-dom +, reflex-dom-core, safe, scientific, servant, servant-auth, stdenv +, string-conversions, text, transformers +}: +mkDerivation { + pname = "servant-reflex"; + version = "0.3.3"; + # src = ./.; + src = builtins.filterSource + (path: type: + baseNameOf path != "result" + && baseNameOf path != "nix" + # baseNameOf (toString path) == "src" || + # baseNameOf (toString path) == "exec" || + # baseNameOf (toString path) == "servant-reflex.cabal" + + ) ./.; + configureFlags = [ "-fexample" ]; + isLibrary = true; + isExecutable = true; + libraryHaskellDepends = [ + base bytestring case-insensitive containers data-default exceptions + ghcjs-dom http-api-data http-media jsaddle mtl network-uri reflex + reflex-dom-core safe servant servant-auth string-conversions text + transformers + ]; + executableHaskellDepends = [ + aeson base reflex reflex-dom scientific servant text + ]; + description = "Servant reflex API generator"; + license = stdenv.lib.licenses.bsd3; +} diff --git a/deps/http-api-data b/deps/http-api-data deleted file mode 160000 index dde6af3..0000000 --- a/deps/http-api-data +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dde6af363d2be6521d1d085ffbab0ea8dbe14f5d diff --git a/deps/reflex-platform b/deps/reflex-platform deleted file mode 160000 index 1670c5b..0000000 --- a/deps/reflex-platform +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1670c5b899658babeda58329d3df6b943cf6aeca diff --git a/deps/servant b/deps/servant deleted file mode 160000 index 2a21e14..0000000 --- a/deps/servant +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2a21e14e6e4ec01a7eed2f0c617162adaa803ab7 diff --git a/deps/servant-snap b/deps/servant-snap deleted file mode 160000 index 31acff4..0000000 --- a/deps/servant-snap +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 31acff4641c228fe5295388166bda485d583295d diff --git a/nix.conf b/nix.conf new file mode 100644 index 0000000..f607f5d --- /dev/null +++ b/nix.conf @@ -0,0 +1,3 @@ +substituters = https://cache.nixos.org https://cache.nixos.org https://nixcache.reflex-frp.org +trusted-substituters = https://cache.nixos.org https://cache.nixos.org https://nixcache.reflex-frp.org +trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI= diff --git a/nix/reflex-platform.nix b/nix/reflex-platform.nix new file mode 100644 index 0000000..dde5a3a --- /dev/null +++ b/nix/reflex-platform.nix @@ -0,0 +1,9 @@ +{ fetchFromGitHub }: + + +import (fetchFromGitHub { + owner = "reflex-frp"; + repo = "reflex-platform"; + rev = "a4d679629b52f80ecae857864591d79d902a5c5d"; + sha256 = "1p34qc3ryar81jh01g4jm0svr05yri83vlswm2jbxiabigy47652"; + }) {} \ No newline at end of file diff --git a/nix/servant-reflex.nix b/nix/servant-reflex.nix new file mode 100644 index 0000000..f7ffb58 --- /dev/null +++ b/nix/servant-reflex.nix @@ -0,0 +1,14 @@ +{ pkgs ? import {}, reflexPlatform, compiler ? "ghcjs" }: + +let + + ghcjsPackages = reflexPlatform.${compiler}.override { + overrides = self: super: { + servant = super.servant; + wai = super.wai; + servant-reflex = pkgs.haskell.lib.appendConfigureFlag + (self.callPackage ../. {}) "-fExample"; + }; + }; + +in ghcjsPackages.servant-reflex \ No newline at end of file diff --git a/nix/testdriver.nix b/nix/testdriver.nix new file mode 100644 index 0000000..57c9744 --- /dev/null +++ b/nix/testdriver.nix @@ -0,0 +1,3 @@ +{ reflexPlatform }: + +reflexPlatform.ghc.callPackage ../testdriver/default.nix {} \ No newline at end of file diff --git a/nix/testresults.nix b/nix/testresults.nix new file mode 100644 index 0000000..3d6cab3 --- /dev/null +++ b/nix/testresults.nix @@ -0,0 +1,22 @@ +{ curl, reflexPlatform, testdriver, testserver, phantomjs }: + +reflexPlatform.nixpkgs.pkgs.runCommand "runWebdriveTest.sh" {} '' + echo About to phantom + ${phantomjs}/bin/phantomjs --webdriver=127.0.0.1:4444 & + sleep 3 + + echo About to server + cd ${testserver} && ./back -q --no-access-log --no-error-log & + sleep 3 + + ${curl}/bin/curl localhost:8000 + ${curl}/bin/curl localhost:8000/runmain.js + + echo About to testdrive + ${testdriver}/bin/spec + echo Done + mkdir $out + echo Done > $out/out.txt + trap "exit" INT TERM + trap "kill 0" EXIT + '' \ No newline at end of file diff --git a/nix/testserver.nix b/nix/testserver.nix new file mode 100644 index 0000000..13012ac --- /dev/null +++ b/nix/testserver.nix @@ -0,0 +1,25 @@ +{ servant-reflex, reflexPlatform }: + +let + ghcPackages = reflexPlatform.ghc.override { + overrides = self: super: { + snap = reflexPlatform.lib.doJailbreak (self.callCabal2nix "snap" ../../snap {}); + hspec-snap = reflexPlatform.lib.doJailbreak (super.hspec-snap); + servant-snap = reflexPlatform.lib.doJailbreak (super.servant-snap); + skylighting = reflexPlatform.lib.dontCheck super.skylighting; + testserver = (self.callPackage ../testserver/default.nix {}).overrideDerivation (old: + { postInstall = '' + echo "SOURCE IS: $src" + echo "ls IS: $ls" + echo "EXAMPLE IS: ${servant-reflex}" + cp dist/build/back/back $out/back + mkdir $out/static + cp ${servant-reflex}/bin/example.jsexe/* $out/static/ + ''; + } + ); + heist = reflexPlatform.lib.doJailbreak super.heist; + }; + }; + +in ghcPackages.testserver \ No newline at end of file diff --git a/release.nix b/release.nix new file mode 100644 index 0000000..c8df90c --- /dev/null +++ b/release.nix @@ -0,0 +1,27 @@ +{ pkgs ? import {}, compiler ? "ghcjs" }: + +let + reflexPlatform = + import ./nix/reflex-platform.nix { + fetchFromGitHub = pkgs.fetchFromGitHub; + }; + +in rec { + + servant-reflex = import ./nix/servant-reflex.nix { + reflexPlatform = reflexPlatform; + compiler = compiler; + }; + testserver = import ./nix/testserver.nix + { reflexPlatform = reflexPlatform; + servant-reflex = servant-reflex ; + }; + testdriver = import ./nix/testdriver.nix + { reflexPlatform = reflexPlatform; + }; + testresults = import ./nix/testresults.nix + { inherit reflexPlatform testserver testdriver; + inherit (pkgs) curl; + phantomjs = pkgs.phantomjs2; + }; + } diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..a2758a2 --- /dev/null +++ b/shell.nix @@ -0,0 +1,3 @@ +{ compiler ? "ghcjs" }: + +(import ./release.nix { inherit compiler; }).servant-reflex.env diff --git a/testdriver/default.nix b/testdriver/default.nix new file mode 100644 index 0000000..421eb20 --- /dev/null +++ b/testdriver/default.nix @@ -0,0 +1,16 @@ +{ mkDerivation, base, hspec, hspec-webdriver, stdenv, text +, webdriver +}: +mkDerivation { + pname = "testdriver"; + version = "0.2"; + src = ./.; + isLibrary = false; + isExecutable = true; + executableHaskellDepends = [ + base hspec hspec-webdriver text webdriver + ]; + description = "Selenium test driver for Servant reflex"; + license = stdenv.lib.licenses.bsd3; + hydraPlatforms = stdenv.lib.platforms.none; +} diff --git a/testdriver/shell.nix b/testdriver/shell.nix new file mode 100644 index 0000000..a504b7e --- /dev/null +++ b/testdriver/shell.nix @@ -0,0 +1 @@ +(import ../release3.nix {}).testdriver.env diff --git a/testdriver/test/Servant/ReflexSpec.hs b/testdriver/test/Servant/ReflexSpec.hs index 3c4cefc..66bc0ae 100644 --- a/testdriver/test/Servant/ReflexSpec.hs +++ b/testdriver/test/Servant/ReflexSpec.hs @@ -28,7 +28,7 @@ spec :: Spec spec = do describe "servant-reflex tests" $ do - session "test page" $ using Chrome $ do + session "test page" $ using [chromeCaps] $ do it "opens the page" $ runWD $ openPage "http://localhost:8000" diff --git a/testserver/API.hs b/testserver/API.hs deleted file mode 120000 index 738c313..0000000 --- a/testserver/API.hs +++ /dev/null @@ -1 +0,0 @@ -../exec/API.hs \ No newline at end of file diff --git a/testserver/API.hs b/testserver/API.hs new file mode 100644 index 0000000..8812065 --- /dev/null +++ b/testserver/API.hs @@ -0,0 +1,69 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TypeOperators #-} + +module API where + +import Data.Aeson +import Data.Aeson.Types (typeMismatch) +import Data.Text (Text) +import Servant.API + +newtype Question = Question { unQuestion :: Text } deriving (Show) + +instance ToJSON Question where + toJSON (Question txt) = object ["question" .= txt] + +instance FromJSON Question where + parseJSON (Object v) = Question <$> v .: "question" + parseJSON x = typeMismatch "Couldn't find key 'question'" x + +newtype Answer = Answer { unAnswer :: Text } deriving (Show) + +instance ToJSON Answer where + toJSON (Answer txt) = object ["answer" .= txt] + +instance FromJSON Answer where + parseJSON (Object v) = Answer <$> v .: "answer" + parseJSON x = typeMismatch "Couldn't find key 'answer'" x + + +-- | API spec for server, client, and docs +type API = "getunit" :> Get '[JSON] () + :<|> "getint" :> Get '[JSON] Int + :<|> "sayhi" :> QueryParam "username" Text + :> QueryParams "greetings" Text + :> QueryFlag "gusto" + :> Get '[JSON] Text + :<|> "double" :> ReqBody '[JSON] Double + :> Post '[JSON] Double + :<|> "a" :> "b" :> QueryFlag "gusto" :> Get '[JSON] Text + :<|> "qna" :> ReqBody '[JSON] Question + :> Post '[JSON] Answer + :<|> "secret" :> BasicAuth "realm" () :> Get '[JSON] Int + :<|> Raw + +type GET = Get '[JSON] () + +-- Imported the comprehensive API example for testing. +-- https://github.com/haskell-servant/servant/blob/master/servant/src/Servant/API/Internal/Test/ComprehensiveAPI.hs +type ComprehensiveAPI = + GET :<|> + Get '[JSON] Int :<|> + Capture "foo" Int :> GET :<|> + Header "foo" Int :> GET :<|> + HttpVersion :> GET :<|> + IsSecure :> GET :<|> + QueryParam "foo" Int :> GET :<|> + QueryParams "foo" Int :> GET :<|> + QueryFlag "foo" :> GET :<|> +-- Raw :<|> + RemoteHost :> GET :<|> + ReqBody '[JSON] Int :> GET :<|> + Get '[JSON] (Headers '[Header "foo" Int] ()) :<|> + "foo" :> GET :<|> + Vault :> GET :<|> + Verb 'POST 204 '[JSON] () :<|> + Verb 'POST 204 '[JSON] Int +-- This one isn't in scope +-- :<|> WithNamedContext "foo" '[] GET diff --git a/testserver/Main.hs b/testserver/Main.hs index 85b339d..2508642 100644 --- a/testserver/Main.hs +++ b/testserver/Main.hs @@ -18,12 +18,12 @@ import Data.Text hiding (head, length, map, import qualified Data.Text as T import qualified Data.Text.IO as T import GHC.Generics -import Servant.Server.Internal.SnapShims import Snap.Core import Snap.Http.Server import Servant -import Servant.Server +import Servant.Server () +import System.Directory -- import Snap.Util.FileServe import API import Snap @@ -85,6 +85,8 @@ test = serveSnapWithContext testApi initApp :: SnapletInit App App initApp = makeSnaplet "myapp" "example" Nothing $ do + liftIO $ print =<< listDirectory "." + liftIO $ print =<< listDirectory "static" addRoutes [("", test) ,("", serveDirectory "static") ] @@ -92,4 +94,7 @@ initApp = makeSnaplet "myapp" "example" Nothing $ do -- Put this all to work! main :: IO () -main = serveSnaplet mempty initApp +main = commandLineConfig emptyConfig >>= \cfg -> print cfg >> serveSnaplet cfg initApp +-- main = serveSnaplet (defaultConfig { accessLog = "/tmp/log/testserver-access.log" +-- , errorLog = "/tmp/log/testserver-error.log" +-- }) initApp diff --git a/testserver/default.nix b/testserver/default.nix new file mode 100644 index 0000000..886751f --- /dev/null +++ b/testserver/default.nix @@ -0,0 +1,14 @@ +{ mkDerivation, aeson, base, servant, servant-snap, snap, snap-core +, snap-server, stdenv, text +}: +mkDerivation { + pname = "testserver"; + version = "0.1.0.0"; + src = ./.; + isLibrary = false; + isExecutable = true; + executableHaskellDepends = [ + aeson base servant servant-snap snap snap-core snap-server text + ]; + license = stdenv.lib.licenses.bsd3; +} diff --git a/testserver/shell.nix b/testserver/shell.nix new file mode 100644 index 0000000..4fbf389 --- /dev/null +++ b/testserver/shell.nix @@ -0,0 +1 @@ +(import ../release2.nix {}).testserver.env diff --git a/testserver/testserver.cabal b/testserver/testserver.cabal index 6a132f2..b29ae89 100644 --- a/testserver/testserver.cabal +++ b/testserver/testserver.cabal @@ -21,6 +21,7 @@ executable back -- other-extensions: build-depends: aeson >= 0.9 && < 1.4 , base >=4.8 && <4.11 + , directory >= 1.2 && < 1.4 , snap >= 1.0 && < 1.2 , snap-server >= 1.0 && < 1.1 , snap-core >= 1.0 && < 1.1