on master help sign in
Merge pull request #631 from obsidiansystems/ls-selftest-ux-improvement

selftest developer UX improvement

commit2f77546a09319cb4a06a557953f98587deea77af authorElliot Cameron <3noch@users.noreply.github.com> dateThu 30 Jan 2020, 18:26 (7 years ago) parent256428d427d690
5 files changed+107−65
default.nix+3−2 lib/command/src/Obelisk/Command/Project.hs+5−4 lib/command/src/Obelisk/Command/Run.hs+22−17 lib/selftest/src/Obelisk/SelfTest.hs+76−41 lib/snap-extras/obelisk-snap-extras.cabal+1−1
default.nix+3−2
@@ -71,6 +71,8 @@ let
7171 librarySystemDepends = [
7272 pkgs.cabal-install
7373 pkgs.coreutils
74+ pkgs.git
75+ pkgs.nix
7476 ];
7577 };
7678 obelisk-snap-extras = self.callCabal2nix "obelisk-snap-extras" (cleanSource ./lib/snap-extras) {};
@@ -130,8 +132,7 @@ in rec {
130132 set -euo pipefail
131133
132134 PATH="${command}/bin:$PATH"
133− export OBELISK_IMPL="$(mktemp -d)"
134− ${pkgs.git}/bin/git clone file://${pathGit} $OBELISK_IMPL
135+ cd ${./.}
135136 "${ghcObelisk.obelisk-selftest}/bin/obelisk-selftest" +RTS -N -RTS "$@"
136137 '';
137138 skeleton = pkgs.runCommand "skeleton" {
lib/command/src/Obelisk/Command/Project.hs+5−4
@@ -253,13 +253,14 @@ toNixPath :: FilePath -> FilePath
253253toNixPath root | "/" `isInfixOf` root = root
254254 | otherwise = "./" <> root
255255
256−nixShellWithPkgs :: MonadObelisk m => FilePath -> Bool -> Map Text FilePath -> Maybe String -> m ()
257−nixShellWithPkgs root isPure packageNamesAndPaths command = do
256+nixShellWithPkgs :: MonadObelisk m => FilePath -> Bool -> Bool -> Map Text FilePath -> Maybe String -> m ()
257+nixShellWithPkgs root isPure chdirToRoot packageNamesAndPaths command = do
258258 packageNamesAndAbsPaths <- liftIO $ for packageNamesAndPaths makeAbsolute
259259 nixpkgsPath <- fmap T.strip $ readProcessAndLogStderr Debug $ setCwd (Just root) $
260260 proc nixExePath ["eval", "(import .obelisk/impl {}).nixpkgs.path"]
261+ let setCwd_ = if chdirToRoot then setCwd (Just root) else id
261262 nixRemote <- liftIO $ lookupEnv "NIX_REMOTE"
262− (_, _, _, ph) <- createProcess_ "runNixShellAttr" $ setDelegateCtlc True $ setCwd (Just root) $ proc "nix-shell" $
263+ (_, _, _, ph) <- createProcess_ "runNixShellAttr" $ setDelegateCtlc True $ setCwd_ $ proc "nix-shell" $
263264 runNixShellConfig $ def
264265 & nixShellConfig_pure .~ isPure
265266 & nixShellConfig_common . nixCmdConfig_target .~ (def
@@ -270,7 +271,7 @@ nixShellWithPkgs root isPure packageNamesAndPaths command = do
270271 \).project.shells.ghc"
271272 )
272273 & nixShellConfig_common . nixCmdConfig_args .~
273− [ rawArg "root" $ toNixPath root
274+ [ rawArg "root" $ toNixPath $ if chdirToRoot then "." else root
274275 , strArg "pkgs" (T.unpack $ decodeUtf8 $ BSL.toStrict $ Json.encode packageNamesAndAbsPaths)
275276 ]
276277 & nixShellConfig_run .~ (command <&> \c -> mconcat
lib/command/src/Obelisk/Command/Run.hs+22−17
@@ -72,7 +72,7 @@ preprocessorIdentifier = "__preprocessor-apply-packages"
7272run :: MonadObelisk m => m ()
7373run = withProjectRoot "." $ \root -> do
7474 pkgs <- fmap toList . parsePackagesOrFail =<< getLocalPkgs root
75− withGhciScript pkgs $ \dotGhciPath -> do
75+ withGhciScript pkgs root $ \dotGhciPath -> do
7676 freePort <- getFreePort
7777 assets <- do
7878 let importableRoot = toNixPath root
@@ -96,7 +96,7 @@ run = withProjectRoot "." $ \root -> do
9696 else readProcessAndLogStderr Debug $
9797 proc nixExePath ["eval", "-f", root, "passthru.staticFilesImpure", "--raw"]
9898 putLog Debug $ "Assets impurely loaded from: " <> assets
99− runGhcid dotGhciPath pkgs $ Just $ unwords
99+ runGhcid root True dotGhciPath pkgs $ Just $ unwords
100100 [ "Obelisk.Run.run"
101101 , show freePort
102102 , "(Obelisk.Run.runServeAsset " ++ show assets ++ ")"
@@ -105,15 +105,16 @@ run = withProjectRoot "." $ \root -> do
105105 ]
106106
107107runRepl :: MonadObelisk m => m ()
108−runRepl = do
109− pkgs <- fmap toList . parsePackagesOrFail =<< withProjectRoot "." getLocalPkgs
110− withGhciScript pkgs $ \dotGhciPath -> do
111− runGhciRepl pkgs dotGhciPath
108+runRepl = withProjectRoot "." $ \root -> do
109+ pkgs <- fmap toList . parsePackagesOrFail =<< getLocalPkgs root
110+ withGhciScript pkgs "." $ \dotGhciPath ->
111+ runGhciRepl root pkgs dotGhciPath
112112
113113runWatch :: MonadObelisk m => m ()
114−runWatch = do
115− pkgs <- fmap toList . parsePackagesOrFail =<< withProjectRoot "." getLocalPkgs
116− withGhciScript pkgs $ \dotGhciPath -> runGhcid dotGhciPath pkgs Nothing
114+runWatch = withProjectRoot "." $ \root -> do
115+ pkgs <- fmap toList . parsePackagesOrFail =<< getLocalPkgs root
116+ withGhciScript pkgs root $ \dotGhciPath ->
117+ runGhcid root True dotGhciPath pkgs Nothing
117118
118119-- | Relative paths to local packages of an obelisk project.
119120--
@@ -254,9 +255,10 @@ packageInfoToNamePathMap = Map.fromList . map (_cabalPackageInfo_packageName &&&
254255withGhciScript
255256 :: MonadObelisk m
256257 => [CabalPackageInfo] -- ^ List of packages to load into ghci
258+ -> FilePath -- ^ All paths written to the .ghci file will be relative to this path
257259 -> (FilePath -> m ()) -- ^ Action to run with the path to generated temporary .ghci
258260 -> m ()
259−withGhciScript packageInfos f = do
261+withGhciScript packageInfos pathBase f = do
260262 selfExe <- liftIO getExecutablePath
261263 let
262264 packageNames = Set.fromList $ map _cabalPackageInfo_packageName packageInfos
@@ -281,28 +283,31 @@ withGhciScript packageInfos f = do
281283
282284 where
283285 rootedSourceDirs pkg = NE.toList $
284− (_cabalPackageInfo_packageRoot pkg </>) <$> _cabalPackageInfo_sourceDirs pkg
286+ makeRelative pathBase . (_cabalPackageInfo_packageRoot pkg </>) <$> _cabalPackageInfo_sourceDirs pkg
285287
286288-- | Run ghci repl
287289runGhciRepl
288290 :: MonadObelisk m
289− => [CabalPackageInfo]
291+ => FilePath -- ^ Path to project root
292+ -> [CabalPackageInfo]
290293 -> FilePath -- ^ Path to .ghci
291294 -> m ()
292−runGhciRepl packages dotGhci = withProjectRoot "." $ \root ->
295+runGhciRepl root packages dotGhci =
293296 -- NOTE: We do *not* want to use $(staticWhich "ghci") here because we need the
294297 -- ghc that is provided by the shell in the user's project.
295− nixShellWithPkgs root True (packageInfoToNamePathMap packages) $ Just $ "ghci " <> makeBaseGhciOptions dotGhci -- TODO: Shell escape
298+ nixShellWithPkgs root True False (packageInfoToNamePathMap packages) $ Just $ "ghci " <> makeBaseGhciOptions dotGhci -- TODO: Shell escape
296299
297300-- | Run ghcid
298301runGhcid
299302 :: MonadObelisk m
300− => FilePath -- ^ Path to .ghci
303+ => FilePath -- ^ Path to project root
304+ -> Bool -- ^ Should we chdir to root when running this process?
305+ -> FilePath -- ^ Path to .ghci
301306 -> [CabalPackageInfo]
302307 -> Maybe String -- ^ Optional command to run at every reload
303308 -> m ()
304−runGhcid dotGhci packages mcmd = withProjectRoot "." $ \root ->
305− nixShellWithPkgs root True (packageInfoToNamePathMap packages) (Just $ unwords $ ghcidExePath : opts) -- TODO: Shell escape
309+runGhcid root chdirToRoot dotGhci packages mcmd =
310+ nixShellWithPkgs root True chdirToRoot (packageInfoToNamePathMap packages) (Just $ unwords $ ghcidExePath : opts) -- TODO: Shell escape
306311 where
307312 opts =
308313 [ "-W"
lib/selftest/src/Obelisk/SelfTest.hs+76−41
@@ -1,3 +1,4 @@
1+{-# LANGUAGE DoAndIfThenElse #-}
12{-# LANGUAGE EmptyCase #-}
23{-# LANGUAGE LambdaCase #-}
34{-# LANGUAGE OverloadedStrings #-}
@@ -23,13 +24,13 @@ import qualified Network.HTTP.Client as HTTP
2324import qualified Network.HTTP.Types as HTTP
2425import qualified Network.Socket as Socket
2526import Shelly hiding (cp)
26−import System.Directory (withCurrentDirectory, getDirectoryContents)
27+import System.Directory (getCurrentDirectory, withCurrentDirectory, getDirectoryContents)
2728import System.Environment
2829import System.Exit (ExitCode (..))
2930import System.FilePath (replaceBaseName, takeBaseName)
3031import System.Which (staticWhich)
3132import qualified System.Info
32−import System.IO (Handle, hClose)
33+import System.IO (Handle, hClose, hIsEOF, hGetContents)
3334import System.IO.Temp
3435import System.Process (readProcessWithExitCode, CreateProcess(cwd), readCreateProcessWithExitCode, proc)
3536import Test.Hspec
@@ -52,11 +53,32 @@ cp = $(staticWhich "cp")
5253cabalPath :: FilePath
5354cabalPath = $(staticWhich "cabal")
5455
56+gitPath :: FilePath
57+gitPath = $(staticWhich "git")
58+
59+chownPath :: FilePath
60+chownPath = $(staticWhich "chown")
61+
62+chmodPath :: FilePath
63+chmodPath = $(staticWhich "chmod")
64+
65+whoamiPath :: FilePath
66+whoamiPath = $(staticWhich "whoami")
67+
68+nixBuildPath :: FilePath
69+nixBuildPath = $(staticWhich "nix-build")
70+
71+lnPath :: FilePath
72+lnPath = $(staticWhich "ln")
73+
74+rmPath :: FilePath
75+rmPath = $(staticWhich "rm")
76+
5577gitUserConfig :: [Text]
5678gitUserConfig = ["-c", "user.name=Obelisk Selftest", "-c", "user.email=noreply@example.com"]
5779
5880commit :: Text -> Sh ()
59−commit msg = void $ run "git" $ gitUserConfig <> [ "commit"
81+commit msg = void $ run gitPath $ gitUserConfig <> [ "commit"
6082 , "--no-gpg-sign"
6183 , "--allow-empty"
6284 , "-m"
@@ -92,20 +114,26 @@ main = do
92114 unless isVerbose $
93115 putStrLn "Tests may take longer to run if there are unbuilt derivations: use -v for verbose output"
94116 let verbosity = bool silently verbosely isVerbose
95− nixBuild args = run "nix-build" ("--no-out-link" : args)
96− obeliskImplRaw <- fromString <$> getEnv "OBELISK_IMPL"
117+ nixBuild args = run nixBuildPath ("--no-out-link" : args)
118+ obeliskImplDirtyReadOnly <- fromString <$> getCurrentDirectory
97119 let runOb_ = augmentWithVerbosity run_ ob isVerbose
98120 let runOb = augmentWithVerbosity run ob isVerbose
99121 let testObRunInDir' = augmentWithVerbosity testObRunInDir ob isVerbose ["run"]
100122 let testThunkPack' = augmentWithVerbosity testThunkPack ob isVerbose []
101123 let
102− withObeliskImpl f =
124+ withObeliskImplClean f =
125+ withSystemTempDirectory "obelisk-impl-clean" $ \(fromString -> obeliskImpl) -> do
126+ void . shellyOb verbosity $ chdir obeliskImpl $ do
127+ run_ gitPath ["clone", "file://" <> toTextIgnore obeliskImplDirtyReadOnly, toTextIgnore obeliskImpl]
128+ f obeliskImpl
129+
130+ withObeliskImplDirty f =
103131 withSystemTempDirectory "obelisk-impl-copy" $ \(fromString -> obeliskImpl) -> do
104132 void . shellyOb verbosity $ chdir obeliskImpl $ do
105− user <- T.strip <$> run "whoami" []
106− run_ cp ["-rT", toTextIgnore obeliskImplRaw, toTextIgnore obeliskImpl]
107− run_ "chown" ["-R", user, toTextIgnore obeliskImpl]
108− run_ "chmod" ["-R", "g-rw,o-rw", toTextIgnore obeliskImpl]
133+ user <- T.strip <$> run whoamiPath []
134+ run_ cp ["-rT", "--no-preserve=mode", toTextIgnore obeliskImplDirtyReadOnly, toTextIgnore obeliskImpl]
135+ run_ chownPath ["-R", user, toTextIgnore obeliskImpl]
136+ run_ chmodPath ["-R", "g-rw,o-rw", toTextIgnore obeliskImpl]
109137 f obeliskImpl
110138
111139 withInitCache f obeliskImpl =
@@ -113,16 +141,16 @@ main = do
113141 -- Setup the ob init cache
114142 void . shellyOb verbosity $ chdir initCache $ do
115143 runOb_ ["init", "--symlink", toTextIgnore obeliskImpl]
116− run_ "git" ["init"]
144+ run_ gitPath ["init"]
117145
118146 f initCache
119147
120− withObeliskImplAndInitCache f =
121− withObeliskImpl $ \impl -> withInitCache (f impl) impl
148+ withObeliskImplDirtyAndInitCache f =
149+ withObeliskImplDirty $ \impl -> withInitCache (f impl) impl
122150
123151 httpManager <- HTTP.newManager HTTP.defaultManagerSettings
124152
125− withObeliskImplAndInitCache $ \obeliskImpl initCache ->
153+ withObeliskImplDirtyAndInitCache $ \obeliskImplDirty initCache ->
126154 hspec $ parallel $ do
127155 let shelly_ = void . shellyOb verbosity
128156
@@ -142,18 +170,18 @@ main = do
142170
143171 -- To be used in tests that change the obelisk impl directory
144172 inTmpObInitWithImplCopy f = inTmpObInit $ \dir ->
145− withObeliskImpl $ \(fromString -> implCopy) -> do
146− run_ "rm" [thunk]
147− run_ "ln" ["-s", implCopy, thunk]
173+ withObeliskImplClean $ \(fromString -> implClean) -> do
174+ run_ rmPath [thunk]
175+ run_ lnPath ["-s", implClean, thunk]
148176 f dir
149177
150178 assertRevEQ a b = liftIO . assertEqual "" "" =<< diff a b
151179 assertRevNE a b = liftIO . assertBool "" . (/= "") =<< diff a b
152180
153− revParseHead = T.strip <$> run "git" ["rev-parse", "HEAD"]
181+ revParseHead = T.strip <$> run gitPath ["rev-parse", "HEAD"]
154182
155183 commitAll = do
156− run_ "git" ["add", "."]
184+ run_ gitPath ["add", "."]
157185 commit "checkpoint"
158186 revParseHead
159187
@@ -162,12 +190,12 @@ main = do
162190 pack = runOb ["thunk", "pack", thunk] >> commitAll
163191 unpack = runOb ["thunk", "unpack", thunk] >> commitAll
164192
165− diff a b = run "git" ["diff", a, b]
193+ diff a b = run gitPath ["diff", a, b]
166194
167195 describe "ob init" $ parallel $ do
168196 it "works with default impl" $ inTmp $ \_ -> runOb ["init"]
169197 it "works with master branch impl" $ inTmp $ \_ -> runOb ["init", "--branch", "master"]
170− it "works with symlink" $ inTmp $ \_ -> runOb ["init", "--symlink", toTextIgnore obeliskImpl]
198+ it "works with symlink" $ inTmp $ \_ -> runOb ["init", "--symlink", toTextIgnore obeliskImplDirty]
171199 it "doesn't silently overwrite existing files" $ withSystemTempDirectory "ob-init λ" $ \dir -> do
172200 let p force = (System.Process.proc ob $ "--no-handoff" : "-v" : "init" : ["--force"|force]) { cwd = Just dir }
173201 (ExitSuccess, _, _) <- readCreateProcessWithExitCode (p False) ""
@@ -194,10 +222,10 @@ main = do
194222 testObRunInDir' Nothing httpManager
195223
196224 describe "obelisk project" $ parallel $ do
197− it "can build obelisk command" $ inTmpObInit $ \_ -> nixBuild ["-A", "command" , toTextIgnore obeliskImpl]
198− it "can build obelisk skeleton" $ inTmpObInit $ \_ -> nixBuild ["-A", "skeleton", toTextIgnore obeliskImpl]
199− it "can build obelisk shell" $ inTmpObInit $ \_ -> nixBuild ["-A", "shell", toTextIgnore obeliskImpl]
200− it "can build everything" $ inTmpObInit $ \_ -> nixBuild [toTextIgnore obeliskImpl]
225+ it "can build obelisk command" $ inTmpObInit $ \_ -> nixBuild ["-A", "command" , toTextIgnore obeliskImplDirty]
226+ it "can build obelisk skeleton" $ inTmpObInit $ \_ -> nixBuild ["-A", "skeleton", toTextIgnore obeliskImplDirty]
227+ it "can build obelisk shell" $ inTmpObInit $ \_ -> nixBuild ["-A", "shell", toTextIgnore obeliskImplDirty]
228+ it "can build everything" $ inTmpObInit $ \_ -> nixBuild [toTextIgnore obeliskImplDirty]
201229
202230 describe "blank initialized project" $ parallel $ do
203231
@@ -247,16 +275,16 @@ main = do
247275
248276 it "unpacks the correct branch" $ withTmp $ \dir -> do
249277 let branch = "master"
250− run_ "git" ["clone", "https://github.com/reflex-frp/reflex.git", toTextIgnore dir, "--branch", branch]
278+ run_ gitPath ["clone", "https://github.com/reflex-frp/reflex.git", toTextIgnore dir, "--branch", branch]
251279 runOb_ ["thunk", "pack", toTextIgnore dir]
252280 runOb_ ["thunk", "unpack", toTextIgnore dir]
253− branch' <- chdir dir $ run "git" ["rev-parse", "--abbrev-ref", "HEAD"]
281+ branch' <- chdir dir $ run gitPath ["rev-parse", "--abbrev-ref", "HEAD"]
254282 liftIO $ assertEqual "" branch (T.strip branch')
255283
256284 it "can pack and unpack plain git repos" $
257285 shelly_ $ withSystemTempDirectory "git-repo" $ \dir -> do
258286 let repo = toTextIgnore $ dir </> ("repo" :: String)
259− run_ "git" ["clone", "https://github.com/haskell/process.git", repo]
287+ run_ gitPath ["clone", "https://github.com/haskell/process.git", repo]
260288 origHash <- chdir (fromText repo) revParseHead
261289
262290 runOb_ ["thunk", "pack", repo]
@@ -271,20 +299,20 @@ main = do
271299
272300 testThunkPack' $ fromText repo
273301
274− it "aborts thunk pack when there are uncommitted files" $ inTmpObInit $ \dir -> do
302+ it "aborts thunk pack when there are uncommitted files" $ inTmpObInitWithImplCopy $ \dir -> do
275303 testThunkPack' (dir </> thunk)
276304
277305 describe "ob thunk update --branch" $ parallel $ do
278306 it "can change a thunk to the latest version of a desired branch" $ withTmp $ \dir -> do
279307 let branch1 = "master"
280308 branch2 = "develop"
281− run_ "git" ["clone", "https://github.com/reflex-frp/reflex.git", toTextIgnore dir, "--branch", branch1]
309+ run_ gitPath ["clone", "https://github.com/reflex-frp/reflex.git", toTextIgnore dir, "--branch", branch1]
282310 runOb_ ["thunk" , "pack", toTextIgnore dir]
283311 runOb_ ["thunk", "update", toTextIgnore dir, "--branch", branch2]
284312
285313 it "doesn't create anything when given an invalid branch" $ withTmp $ \dir -> do
286314 let checkDir dir' = liftIO $ getDirectoryContents $ T.unpack $ toTextIgnore dir'
287− run_ "git" ["clone", "https://github.com/reflex-frp/reflex.git", toTextIgnore dir, "--branch", "master"]
315+ run_ gitPath ["clone", "https://github.com/reflex-frp/reflex.git", toTextIgnore dir, "--branch", "master"]
288316 runOb_ ["thunk" , "pack", toTextIgnore dir]
289317 startingContents <- checkDir dir
290318 void $ errExit False $ runOb ["thunk", "update", toTextIgnore dir, "--branch", "dumble-palooza"]
@@ -297,13 +325,13 @@ testObRunInDir executable extraArgs mdir httpManager = handle_sh (\case ExitSucc
297325 [p0, p1] <- liftIO $ getFreePorts 2
298326 let uri p = "http://localhost:" <> T.pack (show p) <> "/" -- trailing slash required for comparison
299327 writefile "config/common/route" $ uri p0
300− maybe id chdir mdir $ runHandle executable extraArgs $ \stdout -> do
301− firstUri <- handleObRunStdout httpManager stdout
328+ maybe id chdir mdir $ runHandles executable extraArgs [] $ \_stdin stdout stderr -> do
329+ firstUri <- handleObRunStdout httpManager stdout stderr
302330 let newUri = uri p1
303331 when (firstUri == newUri) $ errorExit $
304332 "Startup URI (" <> firstUri <> ") is the same as test URI (" <> newUri <> ")"
305333 maybe id (\_ -> chdir "..") mdir $ alterRouteTo newUri stdout
306− runningUri <- handleObRunStdout httpManager stdout
334+ runningUri <- handleObRunStdout httpManager stdout stderr
307335 if runningUri /= newUri
308336 then errorExit $ "Reloading failed: expected " <> newUri <> " but got " <> runningUri
309337 else exit 0
@@ -313,10 +341,10 @@ testThunkPack executable args path' = withTempFile (T.unpack $ toTextIgnore path
313341 let pack' = readProcessWithExitCode executable (T.unpack <$> ["thunk", "pack", toTextIgnore path'] ++ args) ""
314342 ensureThunkPackFails q = liftIO $ pack' >>= \case
315343 (code, out, err)
316− | code == ExitSuccess -> fail "ob thunk pack succeeded when it should have failed"
344+ | code == ExitSuccess -> fail $ "ob thunk pack succeeded when it should have failed with error '" <> show q <> "'"
317345 | q `T.isInfixOf` T.pack (out <> err) -> pure ()
318− | otherwise -> fail $ "ob thunk pack failed for an unexpected reason: " <> show out <> "\nstderr: " <> err
319− git = chdir path' . run "git"
346+ | otherwise -> fail $ "ob thunk pack failed for an unexpected reason, expecting '" <> show q <> "', received: " <> show out <> "\nstderr: " <> err
347+ git = chdir path' . run gitPath
320348 -- Untracked files
321349 ensureThunkPackFails "Untracked files"
322350 void $ git ["add", T.pack file]
@@ -350,9 +378,12 @@ alterRouteTo uri stdout = do
350378 "Reloading failed: " <> T.pack (show t)
351379
352380-- | Handle stdout of `ob run`: check that the frontend and backend servers are started correctly
353−handleObRunStdout :: HTTP.Manager -> Handle -> Sh Text
354−handleObRunStdout httpManager stdout = flip fix (ObRunState_Init, []) $ \loop (state, msgs) ->
355− liftIO (T.hGetLine stdout) >>= \t -> case state of
381+handleObRunStdout :: HTTP.Manager -> Handle -> Handle -> Sh Text
382+handleObRunStdout httpManager stdout stderr = flip fix (ObRunState_Init, []) $ \loop (state, msgs) -> do
383+ isEOF <- liftIO $ hIsEOF stdout
384+ if isEOF
385+ then handleObRunError msgs
386+ else liftIO (T.hGetLine stdout) >>= \t -> case state of
356387 ObRunState_Init
357388 | "Running test..." `T.isPrefixOf` t -> loop (ObRunState_BackendStarted, msgs)
358389 ObRunState_Startup
@@ -364,8 +395,12 @@ handleObRunStdout httpManager stdout = flip fix (ObRunState_Init, []) $ \loop (s
364395 obRunCheck httpManager stdout uri
365396 pure uri
366397 | not (T.null t) -> errorExit $ "Started: " <> t -- If theres any other output here, startup failed
367− _ | "Failed" `T.isPrefixOf` t -> errorExit $ "ob run failed: " <> T.unlines (reverse $ t : msgs)
398+ _ | "Failed" `T.isPrefixOf` t -> handleObRunError (t : msgs)
368399 | otherwise -> loop (state, t : msgs)
400+ where
401+ handleObRunError msgs = do
402+ stderrContent <- liftIO $ hGetContents stderr
403+ errorExit $ "ob run failed: " <> T.unlines (reverse msgs) <> " stderr: " <> T.pack stderrContent
369404
370405-- | Make requests to frontend/backend servers to check they are working properly
371406obRunCheck :: HTTP.Manager -> Handle -> Text -> Sh ()
lib/snap-extras/obelisk-snap-extras.cabal+1−1
@@ -1,6 +1,6 @@
11name: obelisk-snap-extras
22version: 0.1
3−synopsys: Extra functionality for Snap that should be considered for upstreaming
3+synopsis: Extra functionality for Snap that should be considered for upstreaming
44license: BSD3
55build-type: Simple
66cabal-version: >=1.2