on master help sign in
Merge remote-tracking branch 'origin/master' into ss-reader
commitcc86360b34526be968f77085971d4d79c03db758 authorSridhar Ratnakumar <srid@srid.ca> dateFri 11 May 2018, 15:10 (8 years ago) parent6086d9a8e8ec1f
5 files changed+99−10
README.md+4−2 default.nix+27−1 lib/command/src/Obelisk/Command.hs+1−5 lib/command/src/Obelisk/Command/Deploy.hs+58−1 lib/command/src/Obelisk/Command/Nix.hs+9−1
README.md+4−2
@@ -19,7 +19,9 @@
1919 1. `hub clone obsidiansystems/obelisk`
2020 * NOTE: you must authenticate with hub at least once, because the `ob` command uses `hub` for authentication
2121 #TODO: Make ob do this itself (either invoke hub automatically or not depend on hub)
22−1. Install `ob`: `nix-env -f obelisk -iA command`
22+1. Install `ob`: `nix-env -f obelisk -iA command`.
23+ Alternatively, if you prefer not to install to your user nix environment, you can
24+ enter a shell with the `ob` command available: `nix-shell -A shell`.
2325
2426## Building
2527Build the frontend by running
@@ -36,7 +38,7 @@ ob repl backend
3638and then typing
3739
3840```bash
39−main
41+backend
4042```
4143
4244at the GHCi prompt.
default.nix+27−1
@@ -11,7 +11,13 @@ let #TODO: Upstream
1111 # automatically if the resulting derivation is installed, e.g. by
1212 # `nix-env -i`.
1313
14− justStaticExecutables' = drvOrig: overrideCabal (justStaticExecutables drvOrig) (drv: { configureFlags = drvOrig.configureFlags or [];});
14+ # TODO: Remove this after updating nixpkgs: https://github.com/NixOS/nixpkgs/issues/37750
15+ justStaticExecutables' = drv: let
16+ drv' = justStaticExecutables drv;
17+ in if pkgs.stdenv.isDarwin
18+ then removeConfigureFlag drv' "--ghc-option=-optl=-dead_strip"
19+ else drv';
20+
1521
1622 addOptparseApplicativeCompletionScripts = exeName: pkg: overrideCabal pkg (drv: {
1723 postInstall = (drv.postInstall or "") + ''
@@ -86,6 +92,11 @@ rec {
8692 inherit (reflex-platform) nixpkgs;
8793 path = reflex-platform.filterGit ./.;
8894 command = ghcObelisk.obelisk-command;
95+ shell = nixpkgs.stdenv.mkDerivation {
96+ name = "obelisk-shell";
97+ src = null;
98+ nativeBuildInputs = [command];
99+ };
89100
90101 selftest = pkgs.writeScript "selftest" ''
91102 #!/usr/bin/env bash
@@ -127,11 +138,26 @@ rec {
127138 server = exe: hostName:
128139 let system = "x86_64-linux";
129140 nixos = import (pkgs.path + /nixos);
141+ https = import (pkgs.fetchFromGitHub {
142+ owner = "obsidiansystems";
143+ repo = "obelisk-https";
144+ rev = "999e36b4ab14cbe31be6815cdbc3a1223a7b4617";
145+ sha256 = "0qxi7hg751ikkp4r5j7d706gjrsl26lzlrnh905havij10plcg1l";
146+ private = true;
147+ } + "/module.nix") {} {
148+ backendPort = 8000; # TODO read from config
149+ # sslConfig = {
150+ # hostName = "example.com";
151+ # adminEmail = "webmaster@example.com";
152+ # subdomains = [ "www" ];
153+ # };
154+ };
130155 in nixos {
131156 inherit system;
132157 configuration = args: {
133158 imports = [
134159 (pkgs.path + /nixos/modules/virtualisation/amazon-image.nix)
160+ https
135161 ];
136162 networking = { inherit hostName; };
137163 systemd.services.backend = {
lib/command/src/Obelisk/Command.hs+1−5
@@ -29,7 +29,6 @@ import Obelisk.Command.Project
2929import Obelisk.Command.Repl
3030import Obelisk.Command.Run
3131import Obelisk.Command.Thunk
32−import Obelisk.Command.Utils
3332
3433data Args = Args
3534 { _args_noHandOffPassed :: Bool
@@ -212,10 +211,7 @@ ob = \case
212211 sshKeyPath = _deployInitOpts_sshKey deployOpts
213212 hostname = _deployInitOpts_hostname deployOpts
214213 liftIO $ deployInit thunkPtr (root </> "config") deployDir sshKeyPath hostname
215− DeployCommand_Push -> liftIO $ do
216− checkGitCleanStatus "." >>= \case
217− True -> return ()
218− False -> failWith "ob push: Commit any changes to the deployment configuration before proceeding"
214+ DeployCommand_Push -> deployPush "."
219215 ObCommand_Run -> inNixShell' $ static run
220216 -- inNixShell ($(mkClosure 'ghcidAction) ())
221217 ObCommand_Thunk tc -> case tc of
lib/command/src/Obelisk/Command/Deploy.hs+58−1
@@ -1,13 +1,27 @@
1+{-# LANGUAGE FlexibleContexts #-}
2+{-# LANGUAGE LambdaCase #-}
13{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE ScopedTypeVariables #-}
25module Obelisk.Command.Deploy where
36
47import Control.Monad
8+import Control.Monad.Catch (finally)
9+import Control.Monad.Reader (liftIO)
10+import Data.Default
11+import Data.Maybe
12+import Data.Monoid
13+import qualified Data.Text as T
14+import qualified Data.Text.IO as T
515import System.Directory
616import System.FilePath
717import System.Posix.Files
18+import System.Process
819
9−import Obelisk.Command.Utils
20+import Obelisk.App (MonadObelisk)
21+import Obelisk.Command.CLI (failWith)
22+import Obelisk.Command.Nix
1023import Obelisk.Command.Thunk
24+import Obelisk.Command.Utils
1125
1226deployInit :: ThunkPtr -> FilePath -> FilePath -> FilePath -> [String] -> IO ()
1327deployInit thunkPtr configDir deployDir sshKeyPath hostnames = do
@@ -28,3 +42,46 @@ deployInit thunkPtr configDir deployDir sshKeyPath hostnames = do
2842 writeFile (deployDir </> "backend_hosts") $ unlines hostnames
2943 initGit deployDir
3044
45+deployPush :: MonadObelisk m => FilePath -> m ()
46+deployPush deployPath = do
47+ liftIO $ callProcess "ssh-add" [deployPath </> "ssh_key"]
48+ host <- liftIO $ fmap (T.unpack . T.strip) $ T.readFile $ deployPath </> "backend_hosts"
49+ let srcPath = deployPath </> "src"
50+ build = do
51+ buildOutput <- nixBuild $ def
52+ { _nixBuildConfig_target = Target
53+ { _target_path = srcPath
54+ , _target_attr = Just "server"
55+ }
56+ , _nixBuildConfig_outLink = OutLink_None
57+ , _nixBuildConfig_args = pure $ Arg "hostName" host
58+ }
59+ return $ listToMaybe $ lines buildOutput
60+ result <- readThunk srcPath >>= \case
61+ Right (ThunkData_Packed _) -> do
62+ unpackThunk srcPath
63+ build `finally` packThunk srcPath "origin" -- get upstream
64+ Right (ThunkData_Checkout _) -> do
65+ liftIO (checkGitCleanStatus srcPath) >>= \case
66+ True -> do
67+ result <- build
68+ packThunk srcPath "origin" -- get upstream
69+ return result
70+ False -> do
71+ _ <- failWith $ T.pack $ "ob deploy push: ensure " <> srcPath <> " has no pending changes and latest is pushed upstream."
72+ return Nothing
73+ _ -> return Nothing
74+ liftIO $ forM_ result $ \res -> do
75+ callProcess "nix-copy-closure" ["-v", "--to", "root@" <> host, "--gzip", res]
76+ callProcess "ssh"
77+ [ "root@" <> host
78+ , unwords
79+ [ "nix-env -p /nix/var/nix/profiles/system --set " <> res
80+ , "&&"
81+ , "/nix/var/nix/profiles/system/bin/switch-to-configuration switch"
82+ ]
83+ ]
84+ isClean <- liftIO $ checkGitCleanStatus deployPath
85+ when (not isClean) $ liftIO $ do
86+ callProcess "git" ["-C", deployPath, "add", "--update"]
87+ callProcess "git" ["-C", deployPath, "commit", "-m", "New deployment"]
lib/command/src/Obelisk/Command/Nix.hs+9−1
@@ -8,6 +8,7 @@ module Obelisk.Command.Nix
88 , NixBuildConfig (..)
99 , Target (..)
1010 , OutLink (..)
11+ , Arg (..)
1112 ) where
1213
1314import Control.Monad.Reader (liftIO)
@@ -43,13 +44,19 @@ instance Default Target where
4344 , _target_attr = Nothing
4445 }
4546
47+data Arg = Arg
48+ { _arg_key :: String
49+ , _arg_value :: String
50+ }
51+
4652data NixBuildConfig = NixBuildConfig
4753 { _nixBuildConfig_target :: Target
4854 , _nixBuildConfig_outLink :: OutLink
55+ , _nixBuildConfig_args :: [Arg]
4956 }
5057
5158instance Default NixBuildConfig where
52− def = NixBuildConfig def def
59+ def = NixBuildConfig def def mempty
5360
5461nixBuild :: MonadObelisk m => NixBuildConfig -> m FilePath
5562nixBuild cfg = do
@@ -58,6 +65,7 @@ nixBuild cfg = do
5865 , case _target_attr $ _nixBuildConfig_target cfg of
5966 Nothing -> []
6067 Just attr -> ["-A", attr]
68+ , mconcat [["--argstr", k, v] | Arg k v <- _nixBuildConfig_args cfg]
6169 , case _nixBuildConfig_outLink cfg of
6270 OutLink_Default -> []
6371 OutLink_None -> ["--no-out-link"]