on master help sign in
Merge remote-tracking branch 'origin/qa' into extra-local-packages
commit36649151c9fb3ec33c676a18ab04286a46a531a1 authorElliot Cameron <eacameron@gmail.com> dateWed 15 Jan 2020, 14:38 (7 years ago) parentfe71024d523373
7 files changed+108−41
.github/pull_request_template.md+8 ChangeLog.md+2−1 README.md+4−3 all-tests.nix+41−3 default.nix+2−2 lib/route/src/Obelisk/Route.hs+11−4 lib/selftest/src/Obelisk/SelfTest.hs+40−28
.github/pull_request_template.mdnew file+8
@@ -0,0 +1,8 @@
1+[Provide a clear overview of your changes.]
2+
3+I have:
4+
5+ - [ ] Based work on latest `develop` branch
6+ - [ ] Looked for lint in my changes with `hlint .` (lint found code you did not write can be left alone)
7+ - [ ] Run the test suite: `$(nix-build -A selftest --no-out-link)`
8+ - [ ] (Optional) Run CI tests locally: `nix-build release.nix -A build.x86_64-linux --no-out-link` (or `x86_64-darwin` on macOS)
ChangeLog.md+2−1
@@ -4,7 +4,8 @@ This project's release branch is `master`. This log is written from the perspect
44
55## Unreleased
66
7−* Add local packages from the Nix `project { packages }` option to the GHCi config, so that they are auto-reloaded with `ob run`.
7+* Add `Obelisk.Route.(?/)`, a convenience function for constructing routes nested in `Maybe`. ([#457](https://github.com/obsidiansystems/obelisk/pull/457))
8+* Add local packages from the Nix `project { packages }` option to the GHCi config, so that they are auto-reloaded with `ob run`. ([#489](https://github.com/obsidiansystems/obelisk/pull/489))
89
910## v0.4.0.0 - 2020-01-10
1011
README.md+4−3
@@ -23,14 +23,15 @@ Obelisk provides an easy way to develop and deploy your [Reflex](https://github.
23231. Set up nix caches
2424 1. If you are running NixOS, add this to `/etc/nixos/configuration.nix`:
2525 ```
26− nix.binaryCaches = [ "https://cache.nixos.org/" "https://nixcache.reflex-frp.org" ];
26+ nix.binaryCaches = [ "https://nixcache.reflex-frp.org" ];
2727 nix.binaryCachePublicKeys = [ "ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=" ];
2828 ```
2929 and rebuild your NixOS configuration (e.g. `sudo nixos-rebuild switch`).
3030 1. If you are using another operating system or linux distribution, ensure that these lines are present in your Nix configuration file (`/etc/nix/nix.conf` on most systems; [see full list](https://nixos.org/nix/manual/#sec-conf-file)):
3131 ```
32− substituters = https://cache.nixos.org https://nixcache.reflex-frp.org
33− trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=
32+ binary-caches = https://cache.nixos.org https://nixcache.reflex-frp.org
33+ binary-cache-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=
34+ binary-caches-parallel-connections = 40
3435 ```
3536 * other Linux: enable sandboxing (see these [issue172](https://github.com/obsidiansystems/obelisk/issues/172#issuecomment-411507818) or [issue6](https://github.com/obsidiansystems/obelisk/issues/6) if you run into build problems)
3637 ```
all-tests.nix+41−3
@@ -46,6 +46,12 @@ in
4646 testScript =
4747 let
4848 privateKeyFile = pkgs.writeText "id_rsa" ''${snakeOilPrivateKey}'';
49+ thunkableSample = pkgs.writeText "default.nix" ''
50+ let pkgs = import <nixpkgs> {}; in pkgs.git
51+ '';
52+ invalidThunkableSample = pkgs.writeText "default.nix" ''
53+ let pkgs = import <nixpkgs> {}; in pkgtypo.git
54+ '';
4955 sshConfigFile = pkgs.writeText "ssh_config" ''
5056 Host *
5157 StrictHostKeyChecking no
@@ -83,7 +89,9 @@ in
8389 with subtest("test a git project can be configured with a remote using ssh"):
8490 client.succeed("mkdir -p ~/code/myapp")
8591 client.succeed("cd ~/code/myapp && git init")
86− client.succeed("cd ~/code/myapp && touch README")
92+ client.succeed(
93+ "cp ${thunkableSample} ~/code/myapp/default.nix"
94+ )
8795 client.succeed("cd ~/code/myapp && git add .")
8896 client.succeed('git config --global user.email "you@example.com"')
8997 client.succeed('git config --global user.name "Your Name"')
@@ -92,16 +100,46 @@ in
92100 "cd ~/code/myapp && git remote add origin root@githost:/root/myorg/myapp.git"
93101 )
94102
103+
95104 with subtest("test pushing code to the remote"):
96105 client.succeed("cd ~/code/myapp && git push -u origin master")
97106 client.succeed("cd ~/code/myapp && git status")
98107
99108 with subtest("test obelisk can pack"):
100− client.succeed("ob thunk pack ~/code/myapp")
109+ client.succeed("ob -v thunk pack ~/code/myapp")
101110 client.succeed("grep -qF 'git' ~/code/myapp/default.nix")
102111 client.succeed("grep -qF 'myorg' ~/code/myapp/git.json")
112+ client.succeed("ob -v thunk unpack ~/code/myapp")
103113
114+ with subtest("test obelisk can set the public / private flag"):
115+ client.succeed("ob -v thunk pack ~/code/myapp --private")
116+ client.fail("""grep -qF '"private": practice' ~/code/myapp/git.json""")
117+ client.succeed("""grep -qF '"private": true' ~/code/myapp/git.json""")
118+ client.succeed("nix-build ~/code/myapp")
119+ client.succeed("ob -v thunk unpack ~/code/myapp")
120+ client.succeed("ob -v thunk pack ~/code/myapp --public")
121+ client.succeed("""grep -qF '"private": false' ~/code/myapp/git.json""")
122+ client.succeed("nix-build ~/code/myapp")
123+ client.succeed("ob -v thunk unpack ~/code/myapp")
124+
125+ with subtest("test building an invalid thunk fails"):
126+ client.succeed("cd ~/code/myapp && git checkout -b bad")
127+ client.succeed(
128+ "cp ${invalidThunkableSample} ~/code/myapp/default.nix"
129+ )
130+ client.succeed("cd ~/code/myapp && git add .")
131+ client.succeed('git config --global user.email "you@example.com"')
132+ client.succeed('git config --global user.name "Your Name"')
133+ client.succeed('cd ~/code/myapp && git commit -m "Bad commit"')
134+ client.succeed("cd ~/code/myapp && git push -u origin bad")
135+ client.succeed("ob -v thunk pack ~/code/myapp --public")
136+ client.fail("nix-build ~/code/myapp")
137+ client.succeed("ob -v thunk unpack ~/code/myapp")
138+ client.succeed("cd ~/code/myapp && git checkout master")
139+
104140 with subtest("test obelisk can detect private repos"):
141+ client.succeed("ob -v thunk pack ~/code/myapp")
105142 client.succeed("""grep -qF '"private": false' ~/code/myapp/git.json""")
106− '';
143+ client.succeed("ob -v thunk unpack ~/code/myapp")
144+ '';
107145 }) {}
default.nix+2−2
@@ -126,12 +126,12 @@ in rec {
126126 shell = pinBuildInputs "obelisk-shell" ([command] ++ commandRuntimeDeps pkgs);
127127
128128 selftest = pkgs.writeScript "selftest" ''
129− #!/usr/bin/env bash
129+ #!${pkgs.runtimeShell}
130130 set -euo pipefail
131131
132132 PATH="${command}/bin:$PATH"
133133 export OBELISK_IMPL="$(mktemp -d)"
134− git clone file://${pathGit} $OBELISK_IMPL
134+ ${pkgs.git}/bin/git clone file://${pathGit} $OBELISK_IMPL
135135 "${ghcObelisk.obelisk-selftest}/bin/obelisk-selftest" +RTS -N -RTS "$@"
136136 '';
137137 skeleton = pkgs.runCommand "skeleton" {
lib/route/src/Obelisk/Route.hs+11−4
@@ -20,10 +20,11 @@
2020{-# LANGUAGE ViewPatterns #-}
2121module Obelisk.Route
2222 ( R
23− , pattern (:/)
2423 , (:.)
25− , pattern (:.)
24+ , (?/)
2625 , hoistR
26+ , pattern (:.)
27+ , pattern (:/)
2728 , PageName
2829 , PathQuery
2930 , Encoder
@@ -194,10 +195,16 @@ import Data.Aeson (FromJSON, ToJSON)
194195
195196type R f = DSum f Identity --TODO: Better name
196197
197−{-# COMPLETE (:/) #-}
198−infixr 5 :/
198+-- | Convenience builder for an 'R' using 'Identity' for the functor.
199199pattern (:/) :: f a -> a -> R f
200200pattern a :/ b = a :=> Identity b
201+{-# COMPLETE (:/) #-}
202+infixr 5 :/
203+
204+-- | Like '(:/)' but adds a 'Just' wrapper around the right-hand side.
205+(?/) :: f (Maybe a) -> a -> R f
206+r ?/ a = r :/ Just a
207+infixr 5 ?/
201208
202209mapSome :: (forall a. f a -> g a) -> Some f -> Some g
203210mapSome f (Some a) = Some $ f a
lib/selftest/src/Obelisk/SelfTest.hs+40−28
@@ -76,6 +76,14 @@ tshow = T.pack . show
7676shellyOb :: MonadIO m => (Sh a -> Sh a) -> Sh a -> m a
7777shellyOb f obTest = shelly $ f obTest
7878
79+-- Set "ob" in a single place so it can be replaced with a
80+-- link to obelisk in the nix store in the future,
81+-- and avoid PATH hacking before calling this script.
82+ob :: FilePath
83+ob = "ob"
84+
85+augmentWithVerbosity :: (String -> [Text] -> a) -> String -> Bool -> [Text] -> a
86+augmentWithVerbosity runner executable isVerbose args = runner executable $ (if isVerbose then ("-v" :) else id) args
7987
8088main :: IO ()
8189main = do
@@ -86,6 +94,10 @@ main = do
8694 let verbosity = bool silently verbosely isVerbose
8795 nixBuild args = run "nix-build" ("--no-out-link" : args)
8896 obeliskImplRaw <- fromString <$> getEnv "OBELISK_IMPL"
97+ let runOb_ = augmentWithVerbosity run_ ob isVerbose
98+ let runOb = augmentWithVerbosity run ob isVerbose
99+ let testObRunInDir' = augmentWithVerbosity testObRunInDir ob isVerbose ["run"]
100+ let testThunkPack' = augmentWithVerbosity testThunkPack ob isVerbose []
89101 let
90102 withObeliskImpl f =
91103 withSystemTempDirectory "obelisk-impl-copy" $ \(fromString -> obeliskImpl) -> do
@@ -100,7 +112,7 @@ main = do
100112 withSystemTempDirectory "init Cache λ" $ \initCache -> do
101113 -- Setup the ob init cache
102114 void . shellyOb verbosity $ chdir initCache $ do
103− run_ "ob" ["init", "--symlink", toTextIgnore obeliskImpl]
115+ runOb_ ["init", "--symlink", toTextIgnore obeliskImpl]
104116 run_ "git" ["init"]
105117
106118 f initCache
@@ -146,25 +158,25 @@ main = do
146158 revParseHead
147159
148160 thunk = ".obelisk/impl"
149− update = run "ob" ["thunk", "update", thunk] >> commitAll
150− pack = run "ob" ["thunk", "pack", thunk] >> commitAll
151− unpack = run "ob" ["thunk", "unpack", thunk] >> commitAll
161+ update = runOb ["thunk", "update", thunk] >> commitAll
162+ pack = runOb ["thunk", "pack", thunk] >> commitAll
163+ unpack = runOb ["thunk", "unpack", thunk] >> commitAll
152164
153165 diff a b = run "git" ["diff", a, b]
154166
155167 describe "ob init" $ parallel $ do
156− it "works with default impl" $ inTmp $ \_ -> run "ob" ["init"]
157− it "works with master branch impl" $ inTmp $ \_ -> run "ob" ["init", "--branch", "master"]
158− it "works with symlink" $ inTmp $ \_ -> run "ob" ["init", "--symlink", toTextIgnore obeliskImpl]
168+ it "works with default impl" $ inTmp $ \_ -> runOb ["init"]
169+ it "works with master branch impl" $ inTmp $ \_ -> runOb ["init", "--branch", "master"]
170+ it "works with symlink" $ inTmp $ \_ -> runOb ["init", "--symlink", toTextIgnore obeliskImpl]
159171 it "doesn't silently overwrite existing files" $ withSystemTempDirectory "ob-init λ" $ \dir -> do
160− let p force = (System.Process.proc "ob" $ "--no-handoff" : "init" : ["--force"|force]) { cwd = Just dir }
172+ let p force = (System.Process.proc ob $ "--no-handoff" : "-v" : "init" : ["--force"|force]) { cwd = Just dir }
161173 (ExitSuccess, _, _) <- readCreateProcessWithExitCode (p False) ""
162174 (ExitFailure _, _, _) <- readCreateProcessWithExitCode (p False) ""
163175 (ExitSuccess, _, _) <- readCreateProcessWithExitCode (p True) ""
164176 pure ()
165177
166178 it "doesn't create anything when given an invalid impl" $ inTmp $ \tmp -> do
167− void $ errExit False $ run "ob" ["init", "--symlink", "/dev/null"]
179+ void $ errExit False $ runOb ["init", "--symlink", "/dev/null"]
168180 ls tmp >>= liftIO . assertEqual "" []
169181
170182 it "produces a valid route config" $ inTmpObInit $ \tmp -> liftIO $
@@ -175,11 +187,11 @@ main = do
175187 -- These tests fail with "Could not find module 'Obelisk.Generated.Static'"
176188 -- when not run by 'nix-build --attr selftest'
177189 describe "ob run" $ {- NOT parallel $ -} do
178− it "works in root directory" $ inTmpObInit $ \_ -> testObRunInDir Nothing httpManager
179− it "works in sub directory" $ inTmpObInit $ \_ -> testObRunInDir (Just "frontend") httpManager
190+ it "works in root directory" $ inTmpObInit $ \_ -> testObRunInDir' Nothing httpManager
191+ it "works in sub directory" $ inTmpObInit $ \_ -> testObRunInDir' (Just "frontend") httpManager
180192 it "works with differently named cabal files" $ inTmpObInit $ \_ -> do
181193 changeCabalPackageName "backend/backend.cabal" "new-backend"
182− testObRunInDir Nothing httpManager
194+ testObRunInDir' Nothing httpManager
183195
184196 describe "obelisk project" $ parallel $ do
185197 it "can build obelisk command" $ inTmpObInit $ \_ -> nixBuild ["-A", "command" , toTextIgnore obeliskImpl]
@@ -236,8 +248,8 @@ main = do
236248 it "unpacks the correct branch" $ withTmp $ \dir -> do
237249 let branch = "master"
238250 run_ "git" ["clone", "https://github.com/reflex-frp/reflex.git", toTextIgnore dir, "--branch", branch]
239− run_ "ob" ["thunk", "pack", toTextIgnore dir]
240− run_ "ob" ["thunk", "unpack", toTextIgnore dir]
251+ runOb_ ["thunk", "pack", toTextIgnore dir]
252+ runOb_ ["thunk", "unpack", toTextIgnore dir]
241253 branch' <- chdir dir $ run "git" ["rev-parse", "--abbrev-ref", "HEAD"]
242254 liftIO $ assertEqual "" branch (T.strip branch')
243255
@@ -247,45 +259,45 @@ main = do
247259 run_ "git" ["clone", "https://github.com/haskell/process.git", repo]
248260 origHash <- chdir (fromText repo) revParseHead
249261
250− run_ "ob" ["thunk", "pack", repo]
262+ runOb_ ["thunk", "pack", repo]
251263 packedFiles <- Set.fromList <$> ls (fromText repo)
252264 liftIO $ assertEqual "" packedFiles $ Set.fromList $ (repo </>) <$>
253265 ["default.nix", "github.json", ".attr-cache" :: String]
254266
255− run_ "ob" ["thunk", "unpack", repo]
267+ runOb_ ["thunk", "unpack", repo]
256268 chdir (fromText repo) $ do
257269 unpackHash <- revParseHead
258270 assertRevEQ origHash unpackHash
259271
260− testThunkPack $ fromText repo
272+ testThunkPack' $ fromText repo
261273
262274 it "aborts thunk pack when there are uncommitted files" $ inTmpObInit $ \dir -> do
263− testThunkPack (dir </> thunk)
275+ testThunkPack' (dir </> thunk)
264276
265277 describe "ob thunk update --branch" $ parallel $ do
266278 it "can change a thunk to the latest version of a desired branch" $ withTmp $ \dir -> do
267279 let branch1 = "master"
268280 branch2 = "develop"
269281 run_ "git" ["clone", "https://github.com/reflex-frp/reflex.git", toTextIgnore dir, "--branch", branch1]
270− run_ "ob" ["thunk" , "pack", toTextIgnore dir]
271− run_ "ob" ["thunk", "update", toTextIgnore dir, "--branch", branch2]
282+ runOb_ ["thunk" , "pack", toTextIgnore dir]
283+ runOb_ ["thunk", "update", toTextIgnore dir, "--branch", branch2]
272284
273285 it "doesn't create anything when given an invalid branch" $ withTmp $ \dir -> do
274286 let checkDir dir' = liftIO $ getDirectoryContents $ T.unpack $ toTextIgnore dir'
275287 run_ "git" ["clone", "https://github.com/reflex-frp/reflex.git", toTextIgnore dir, "--branch", "master"]
276− run_ "ob" ["thunk" , "pack", toTextIgnore dir]
288+ runOb_ ["thunk" , "pack", toTextIgnore dir]
277289 startingContents <- checkDir dir
278− void $ errExit False $ run "ob" ["thunk", "update", toTextIgnore dir, "--branch", "dumble-palooza"]
290+ void $ errExit False $ runOb ["thunk", "update", toTextIgnore dir, "--branch", "dumble-palooza"]
279291 checkDir dir >>= liftIO . assertEqual "" startingContents
280292
281293
282294-- | Run `ob run` in the given directory (maximum of one level deep)
283−testObRunInDir :: Maybe FilePath -> HTTP.Manager -> Sh ()
284−testObRunInDir mdir httpManager = handle_sh (\case ExitSuccess -> pure (); e -> throw e) $ do
295+testObRunInDir :: String -> [Text] -> Maybe FilePath -> HTTP.Manager -> Sh ()
296+testObRunInDir executable extraArgs mdir httpManager = handle_sh (\case ExitSuccess -> pure (); e -> throw e) $ do
285297 [p0, p1] <- liftIO $ getFreePorts 2
286298 let uri p = "http://localhost:" <> T.pack (show p) <> "/" -- trailing slash required for comparison
287299 writefile "config/common/route" $ uri p0
288− maybe id chdir mdir $ runHandle "ob" ["run", "-v"] $ \stdout -> do
300+ maybe id chdir mdir $ runHandle executable extraArgs $ \stdout -> do
289301 firstUri <- handleObRunStdout httpManager stdout
290302 let newUri = uri p1
291303 when (firstUri == newUri) $ errorExit $
@@ -296,9 +308,9 @@ testObRunInDir mdir httpManager = handle_sh (\case ExitSuccess -> pure (); e ->
296308 then errorExit $ "Reloading failed: expected " <> newUri <> " but got " <> runningUri
297309 else exit 0
298310
299−testThunkPack :: FilePath -> Sh ()
300−testThunkPack path' = withTempFile (T.unpack $ toTextIgnore path') "test-file" $ \file handle -> do
301− let pack' = readProcessWithExitCode "ob" ["thunk", "pack", T.unpack $ toTextIgnore path'] ""
311+testThunkPack :: String -> [Text] -> FilePath -> Sh ()
312+testThunkPack executable args path' = withTempFile (T.unpack $ toTextIgnore path') "test-file" $ \file handle -> do
313+ let pack' = readProcessWithExitCode executable (T.unpack <$> ["thunk", "pack", toTextIgnore path'] ++ args) ""
302314 ensureThunkPackFails q = liftIO $ pack' >>= \case
303315 (code, out, err)
304316 | code == ExitSuccess -> fail "ob thunk pack succeeded when it should have failed"