on master help sign in
Merge branch 'develop' into extra-local-packages
commit246445bda545cd029dda08149d21265e6bbb1ba7 authorAli Abrar <aliabrar@gmail.com> dateThu 3 Oct 2019, 20:02 (7 years ago) parent6a76a9bb85c9ee
14 files changed+76−44
README.md+40−9 default.nix+1−1 dep/reflex-platform/github.json+3−3 lib/backend/src/Obelisk/Backend.hs+2−1 lib/command/src/Obelisk/Command/Deploy.hs+1−1 lib/command/src/Obelisk/Command/Project.hs+1 lib/command/src/Obelisk/Command/Run.hs+9 lib/selftest/src/Obelisk/SelfTest.hs+4−8 release.nix+3−6 skeleton/backend/src/Backend.hs−2 skeleton/common/src/Common/Route.hs+4−6 skeleton/default.nix+6−6 skeleton/frontend/src/Frontend.hs+1−1 skeleton/shell.nix+1
README.md+40−9
@@ -60,6 +60,28 @@ Or to launch ghcid for `lib/command` project:
6060nix-shell -A obeliskEnvs.obelisk-command --run "cd lib/command && ghcid -c 'cabal new-repl'"
6161```
6262
63+To re-install `ob` from source do
64+```
65+nix-env -f /path/to/obelisk -iA command
66+```
67+
68+Note that `ob` will defer to the version found in your project's `.obelisk/impl` directory. To update that version specifically:
69+
70+```shell
71+ob thunk unpack ./obelisk/impl
72+cd ./obelisk/impl
73+# apply your changes
74+```
75+
76+If you want to commit your changes, first push them to your fork of obelisk and then
77+
78+```shell
79+cd /your/project/root
80+ob thunk pack .obelisk/impl
81+git add .obelisk/impl
82+git commit -m "Bump obelisk"
83+```
84+
6385### Accessing private repositories
6486
6587To allow the Nix builder to access private git repositories, you must be set up
@@ -99,14 +121,14 @@ In order to add package dependencies, declare them under the build-depends field
99121
100122### Adding package overrides
101123
102−To add a version override to any Haskell package, or to add a Haskell package that doesn't exist in the nixpkgs used by Obelisk, use the `overrides` attribute in your project's `default.nix`. For example, to use a specific version of the `aeson` package, your `default.nix` will look like:
124+To add a version override to any Haskell package, or to add a Haskell package that doesn't exist in the nixpkgs used by Obelisk, use the `overrides` attribute in your project's `default.nix`. For example, to use a specific version of the `aeson` package fetched from GitHub and a specific version of the `waargonaut` package fetched from Hackage, your `default.nix` will look like:
103125
104126```nix
105127# ...
106128project ./. ({ pkgs, ... }: {
107129# ...
108130 overrides = self: super: let
109− aeson = pkgs.fetchFromGitHub {
131+ aesonSrc = pkgs.fetchFromGitHub {
110132 owner = "obsidiansystems";
111133 repo = "aeson-gadt-th";
112134 rev = "ed573c2cccf54d72aa6279026752a3fecf9c1383";
@@ -114,7 +136,12 @@ project ./. ({ pkgs, ... }: {
114136 };
115137 in
116138 {
117− aeson = self.callCabal2nix "aeson" aeson {};
139+ aeson = self.callCabal2nix "aeson" aesonSrc {};
140+ waargonaut = self.callHackageDirect {
141+ pkg = "waargonaut";
142+ ver = "0.8.0.1";
143+ sha256 = "1zv28np3k3hg378vqm89v802xr0g8cwk7gy3mr77xrzy5jbgpa39";
144+ } {};
118145 };
119146# ...
120147```
@@ -145,14 +172,16 @@ project ./. ({ pkgs, ... }: {
145172Build everything:
146173
147174```
148−nix-build -A exe -o result-exe
175+nix-build -A exe --no-out-link
149176```
150177
151−Run the server:
178+Copy the result to a new directory, add configuration, and run!
152179
153180```
154−cd result-exe
155−./backend
181+mkdir test-app
182+ln -s $(nix-build -A exe --no-out-link)/* test-app/
183+cp -r config test-app
184+(cd test-app && ./backend)
156185```
157186
158187### EC2
@@ -184,9 +213,11 @@ ob deploy init \
184213 ~/code/myapp-deploy
185214```
186215
187−NOTE: HTTPS is enabled by default; to disable https, pass `--disable-https` to the `ob deploy init` command above.
216+HTTPS is enabled by default; to disable https, pass `--disable-https` to the `ob deploy init` command above.
217+
218+This step will also require that you manually verify the authenticity of the host `$SERVER`. Obelisk will save the fingerprint in a deployment-specific configuration. **Obelisk deployments do *not* rely on the `known_hosts` of your local machine.** This is because, in the event that you need to switch from one deploy machine / bastion host to another, you want to be absolutely sure that you're still connecting to the machines you think you are, even if that deploy machine / bastion host has never connected to them before. Obelisk explicitly avoids a workflow that encourages people to accept host keys without checking them, since that could result in leaking production secrets to anyone who manages to MITM you, e.g. via DNS spoofing or cache poisoning. (Note that an active attack is a circumstance where you may need to quickly switch bastion hosts, e.g. because the attacker has taken one down or you have taken it down in case it was compromised. In this circumstance you might need to deploy to production to fix an exploit or rotate keys, etc.) When you run `ob deploy` later it will rely on the saved verification in this step.
188219
189−Then go to that created deployment configuration directory, and initiate the deployment:
220+Next, go to the deployment directory that you just initialized and deploy!
190221
191222```
192223cd ~/code/myapp-deploy
default.nix+1−1
@@ -128,7 +128,7 @@ in rec {
128128 obelisk = ghcObelisk;
129129 obeliskEnvs = ghcObeliskEnvs;
130130 command = ghcObelisk.obelisk-command;
131− shell = pinBuildInputs "obelisk-shell" ([command] ++ commandRuntimeDeps pkgs) [];
131+ shell = pinBuildInputs "obelisk-shell" ([command] ++ commandRuntimeDeps pkgs);
132132
133133 selftest = pkgs.writeScript "selftest" ''
134134 #!/usr/bin/env bash
dep/reflex-platform/github.json+3−3
@@ -1,7 +1,7 @@
11{
22 "owner": "reflex-frp",
33 "repo": "reflex-platform",
4− "branch": "aa-split-these",
5− "rev": "4b4a2c8679d6f3042180d2974b31c43bfc506b91",
6− "sha256": "185i8ccqk0xc05ckd921fs7nnaj88gihmlazny1dk004hxq78cj2"
4+ "branch": "develop",
5+ "rev": "9e306f72ed0dbcdccce30a4ba0eb37aa03cf91e3",
6+ "sha256": "1crlwfw6zsx2izwsd57i5651p5pfyrpkfjwp6fc1yd4q4d4n7g2m"
77}
lib/backend/src/Obelisk/Backend.hs+2−1
@@ -47,7 +47,7 @@ import Obelisk.Snap.Extras (doNotCache, serveFileIfExistsAs)
4747import Reflex.Dom
4848import Snap (MonadSnap, Snap, commandLineConfig, defaultConfig, getsRequest, httpServe, modifyResponse
4949 , rqPathInfo, rqQueryString, setContentType, writeBS, writeText
50− , rqCookies, Cookie(..))
50+ , rqCookies, Cookie(..) , setHeader)
5151import Snap.Internal.Http.Server.Config (Config (accessLog, errorLog), ConfigLog (ConfigIoLog))
5252import System.IO (BufferMode (..), hSetBuffering, stderr, stdout)
5353
@@ -167,6 +167,7 @@ serveGhcjsApp
167167serveGhcjsApp urlEnc app config = \case
168168 GhcjsAppRoute_App appRouteComponent :=> Identity appRouteRest -> do
169169 modifyResponse $ setContentType staticRenderContentType
170+ modifyResponse $ setHeader "Cache-Control" "no-store private"
170171 writeBS <=< renderGhcjsFrontend urlEnc (appRouteComponent :/ appRouteRest) config $ _ghcjsApp_value app
171172 GhcjsAppRoute_Resource :=> Identity pathSegments -> serveStaticAssets (_ghcjsApp_compiled app) pathSegments
172173
lib/command/src/Obelisk/Command/Deploy.hs+1−1
@@ -275,7 +275,7 @@ instance ToJSON KeytoolConfig
275275createKeystore :: MonadObelisk m => FilePath -> KeytoolConfig -> m ()
276276createKeystore root config = do
277277 let expr = "with (import " <> toImplDir root <> ").reflex-platform.nixpkgs; pkgs.mkShell { buildInputs = [ pkgs.jdk ]; }"
278− callProcessAndLogOutput (Notice,Notice) $ (proc "nix-shell" ["-E" , expr, "--run" , keytoolCmd]) { cwd = Just root }
278+ callProcessAndLogOutput (Notice,Notice) $ (proc "nix-shell" ["default.nix", "-E" , expr, "--run" , keytoolCmd]) { cwd = Just root }
279279 where
280280 keytoolCmd = processToShellString "keytool"
281281 [ "-genkeypair", "-noprompt"
lib/command/src/Obelisk/Command/Project.hs+1
@@ -205,6 +205,7 @@ inImpureProjectShell shellName command = withProjectRoot "." $ \root ->
205205projectShell :: MonadObelisk m => FilePath -> Bool -> String -> Maybe String -> m ()
206206projectShell root isPure shellName command = do
207207 (_, _, _, ph) <- createProcess_ "runNixShellAttr" $ setCtlc $ setCwd (Just root) $ proc "nix-shell" $
208+ [ "default.nix"] <>
208209 [ "--pure" | isPure ] <>
209210 [ "-A"
210211 , "shells." <> shellName
lib/command/src/Obelisk/Command/Run.hs+9
@@ -14,6 +14,7 @@ import qualified Data.List as L
1414import qualified Data.List.NonEmpty as NE
1515import Data.Maybe
1616import qualified Data.Text as T
17+import Distribution.Compiler (CompilerFlavor(..))
1718import Distribution.PackageDescription.Parsec (parseGenericPackageDescription)
1819import Distribution.Parsec.ParseResult (runParseResult)
1920import Distribution.Pretty
@@ -48,6 +49,8 @@ data CabalPackageInfo = CabalPackageInfo
4849 -- ^ List of globally enable extensions of the library component
4950 , _cabalPackageInfo_defaultLanguage :: Maybe Language
5051 -- ^ List of globally set languages of the library component
52+ , _cabalPackageInfo_compilerOptions :: [(CompilerFlavor, [String])]
53+ -- ^ List of compiler-specific options (e.g., the "ghc-options" field of the cabal file)
5154 }
5255
5356-- NOTE: `run` is not polymorphic like the rest because we use StaticPtr to invoke it.
@@ -165,6 +168,7 @@ parseCabalPackage dir = do
165168 defaultExtensions $ libBuildInfo lib
166169 , _cabalPackageInfo_defaultLanguage =
167170 defaultLanguage $ libBuildInfo lib
171+ , _cabalPackageInfo_compilerOptions = options $ libBuildInfo lib
168172 }
169173 Left (_, errors) -> do
170174 putLog Error $ T.pack $ "Failed to parse " <> cabalFp <> ":"
@@ -200,8 +204,13 @@ withGhciScript pkgs f = do
200204 extensionsLine = if extensions == mempty
201205 then ""
202206 else ":set " <> intercalate " " ((("-X" <>) . prettyShow) <$> extensions)
207+ ghcOptions = concat $ mapMaybe (\case (GHC, xs) -> Just xs; _ -> Nothing) $
208+ packageInfos >>= _cabalPackageInfo_compilerOptions
203209 dotGhci = unlines $
204210 [ ":set -i" <> intercalate ":" (packageInfos >>= rootedSourceDirs)
211+ , case ghcOptions of
212+ [] -> ""
213+ xs -> ":set " <> intercalate " " xs
205214 , extensionsLine
206215 , ":set " <> intercalate " " (("-X" <>) . prettyShow <$> language)
207216 , ":load Backend Frontend"
lib/selftest/src/Obelisk/SelfTest.hs+4−8
@@ -129,8 +129,8 @@ main = do
129129 ls tmp >>= liftIO . assertEqual "" []
130130
131131 it "produces a valid route config" $ inTmpObInit $ \tmp -> liftIO $ do
132− configs <- getConfigs
133− withCurrentDirectory (T.unpack $ toTextIgnore tmp) $
132+ withCurrentDirectory (T.unpack $ toTextIgnore tmp) $ do
133+ configs <- getConfigs
134134 return (either (const Nothing) Just $ getConfigRoute configs) `shouldNotReturn` Nothing
135135
136136 -- These tests fail with "Could not find module 'Obelisk.Generated.Static'"
@@ -145,8 +145,7 @@ main = do
145145 it "can build obelisk command" $ inTmpObInit $ \_ -> nixBuild ["-A", "command" , obeliskImpl]
146146 it "can build obelisk skeleton" $ inTmpObInit $ \_ -> nixBuild ["-A", "skeleton", obeliskImpl]
147147 it "can build obelisk shell" $ inTmpObInit $ \_ -> nixBuild ["-A", "shell", obeliskImpl]
148− -- See https://github.com/obsidiansystems/obelisk/issues/101
149− -- it "can build everything" $ shelly_ $ nixBuild [obeliskImpl]
148+ it "can build everything" $ inTmpObInit $ \_ -> nixBuild [obeliskImpl]
150149
151150 describe "blank initialized project" $ parallel $ do
152151
@@ -162,13 +161,10 @@ main = do
162161 forM_ ["ghc", "ghcjs"] $ \compiler -> do
163162 let
164163 shell = "shells." <> compiler
165− inShell cmd' = run "nix-shell" ["-A", fromString shell, "--run", cmd']
164+ inShell cmd' = run "nix-shell" ["default.nix", "-A", fromString shell, "--run", cmd']
166165 it ("can enter " <> shell) $ inTmpObInit $ \_ -> inShell "exit"
167166 it ("can build in " <> shell) $ inTmpObInit $ \_ -> inShell $ "cabal new-build --" <> fromString compiler <> " all"
168167
169− it "can build reflex project" $ inTmpObInit $ \_ -> do
170− nixBuild []
171−
172168 it "has idempotent thunk update" $ inTmpObInit $ \_ -> do
173169 u <- update
174170 uu <- update
release.nix+3−6
@@ -58,6 +58,7 @@ let
5858 (builtins.attrValues ghcjs)
5959 (concatDepends ghc)
6060 (concatDepends ghcjs)
61+ [command serverExeSkeleton iosSkeleton androidSkeleton]
6162 ];
6263 command = local-self.command;
6364 serverExeSkeleton = (import ./skeleton { obelisk = local-self; }).exe;
@@ -77,15 +78,11 @@ let
7778 serverExeSkeleton
7879 iosSkeleton
7980 androidSkeleton;
80− cache = reflex-platform.pinBuildInputs
81− "obelisk-${system}"
82− cachePackages
83− [command serverExeSkeleton iosSkeleton androidSkeleton];
81+ cache = reflex-platform.pinBuildInputs "obelisk-${system}" cachePackages;
8482 });
8583
8684 metaCache = local-self.pinBuildInputs
8785 "obelisk-everywhere"
88− (map (a: a.cache) (builtins.attrValues perPlatform))
89− [];
86+ (map (a: a.cache) (builtins.attrValues perPlatform));
9087
9188in perPlatform // { inherit metaCache; }
skeleton/backend/src/Backend.hs−2
@@ -1,6 +1,4 @@
1−{-# LANGUAGE EmptyCase #-}
21{-# LANGUAGE FlexibleContexts #-}
3−{-# LANGUAGE LambdaCase #-}
42{-# LANGUAGE RankNTypes #-}
53{-# LANGUAGE TypeFamilies #-}
64module Backend where
skeleton/common/src/Common/Route.hs+4−6
@@ -1,15 +1,13 @@
11{-# LANGUAGE EmptyCase #-}
22{-# LANGUAGE FlexibleContexts #-}
3+{-# LANGUAGE FlexibleInstances #-}
34{-# LANGUAGE GADTs #-}
4−{-# LANGUAGE LambdaCase #-}
5−{-# LANGUAGE RankNTypes #-}
6−{-# LANGUAGE TemplateHaskell #-}
75{-# LANGUAGE KindSignatures #-}
8−{-# LANGUAGE EmptyCase #-}
6+{-# LANGUAGE LambdaCase #-}
97{-# LANGUAGE MultiParamTypeClasses #-}
10−{-# LANGUAGE FlexibleInstances #-}
118{-# LANGUAGE OverloadedStrings #-}
12−
9+{-# LANGUAGE RankNTypes #-}
10+{-# LANGUAGE TemplateHaskell #-}
1311module Common.Route where
1412
1513{- -- You will probably want these imports for composing Encoders.
skeleton/default.nix+6−6
@@ -1,10 +1,10 @@
11{ obelisk ? import ./.obelisk/impl {
2− system = builtins.currentSystem;
3− iosSdkVersion = "10.2";
4− # You must accept the Android Software Development Kit License Agreement at
5− # https://developer.android.com/studio/terms in order to build Android apps.
6− # Uncomment and set this to `true` to indicate your acceptance:
7− # config.android_sdk.accept_license = false;
2+ system = builtins.currentSystem;
3+ iosSdkVersion = "10.2";
4+ # You must accept the Android Software Development Kit License Agreement at
5+ # https://developer.android.com/studio/terms in order to build Android apps.
6+ # Uncomment and set this to `true` to indicate your acceptance:
7+ # config.android_sdk.accept_license = false;
88 }
99}:
1010with obelisk;
skeleton/frontend/src/Frontend.hs+1−1
@@ -22,7 +22,7 @@ frontend = Frontend
2222 el "p" $ text $ T.pack commonStuff
2323 elAttr "img" ("src" =: static @"obelisk.jpg") blank
2424 el "div" $ do
25− exampleConfig <- getConfig "common/example"
25+ exampleConfig <- getConfig "common/example"
2626 case exampleConfig of
2727 Nothing -> text "No config file found in config/common/example"
2828 Just s -> text (T.decodeUtf8 s)
skeleton/shell.nixnew file+1
@@ -0,0 +1 @@
1+(import ./. {}).shells.ghc