on master help sign in
Merge pull request #272 from obsidiansystems/ts-version-route

Add /version route

commit876394d3c322b11ded19a9cae9b1c85663a1b74d authorLuigy Leon <luichi.19@gmail.com> dateTue 30 Oct 2018, 12:28 (8 years ago) parent10bd75169caaf0
7 files changed+49−40
README.md+1−1 default.nix+15−7 lib/backend/obelisk-backend.cabal+1 lib/backend/src/Obelisk/Backend.hs+2 lib/command/src/Obelisk/Command/Deploy.hs+24−29 lib/command/src/Obelisk/Command/Thunk.hs+4−3 lib/route/src/Obelisk/Route.hs+2
README.md+1−1
@@ -140,7 +140,7 @@ ob deploy push
140140
141141`ob deploy push` will locally build your app and then transfer it, along with all the Nix package dependencies, via ssh to the EC2 instance. The backend will live in `/var/lib/backend`.
142142
143−At this point you are done. Your app will be accessible at `${ROUTE}`.
143+At this point you are done. Your app will be accessible at `${ROUTE}`. The currently deployed version - the git commit hash of the source repo - can be found at `${ROUTE}/version`.
144144
145145### From macOS
146146
default.nix+15−7
@@ -232,7 +232,7 @@ in rec {
232232 };
233233 };
234234
235− serverExe = backend: frontend: assets: config: optimizationLevel:
235+ serverExe = backend: frontend: assets: config: optimizationLevel: version:
236236 pkgs.runCommand "serverExe" {} ''
237237 mkdir $out
238238 set -eux
@@ -240,9 +240,10 @@ in rec {
240240 ln -s "${mkAssets assets}" $out/static.assets
241241 cp -r ${config} $out/config
242242 ln -s ${mkAssets (compressedJs frontend optimizationLevel)} $out/frontend.jsexe.assets
243+ echo ${version} > $out/version
243244 '';
244245
245− server = { exe, hostName, adminEmail, routeHost, enableHttps, config }@args:
246+ server = { exe, hostName, adminEmail, routeHost, enableHttps, config, version }@args:
246247 let
247248 nixos = import (pkgs.path + /nixos);
248249 in nixos {
@@ -328,15 +329,22 @@ in rec {
328329 passthru = { inherit android ios packages overrides tools shellToolOverrides withHoogle staticFiles __closureCompilerOptimizationLevel; };
329330 };
330331 in mkProject (projectDefinition args));
331− serverOn = sys: config: serverExe (projectOut sys).ghc.backend (projectOut system).ghcjs.frontend (projectOut sys).passthru.staticFiles config (projectOut sys).passthru.__closureCompilerOptimizationLevel;
332+ serverOn = sys: config: version: serverExe
333+ (projectOut sys).ghc.backend
334+ (projectOut system).ghcjs.frontend
335+ (projectOut sys).passthru.staticFiles
336+ config
337+ (projectOut sys).passthru.__closureCompilerOptimizationLevel
338+ version;
332339 linuxExe = serverOn "x86_64-linux";
340+ dummyVersion = "Version number is only available for deployments";
333341 in projectOut system // {
334342 linuxExeConfigurable = linuxExe;
335− linuxExe = linuxExe (base + "/config");
336− exe = serverOn system (base + "/config") ;
337− server = args@{ hostName, adminEmail, routeHost, enableHttps, config }: let
343+ linuxExe = linuxExe (base + "/config") dummyVersion;
344+ exe = serverOn system (base + "/config") dummyVersion;
345+ server = args@{ hostName, adminEmail, routeHost, enableHttps, config, version }: let
338346 injectableConfig = builtins.filterSource (path: _: !(lib.hasPrefix (toString config + "/backend") (toString path))) config;
339− in server (args // { exe = linuxExe injectableConfig; });
347+ in server (args // { exe = linuxExe injectableConfig version; });
340348 obelisk = import (base + "/.obelisk/impl") {};
341349 };
342350 haskellPackageSets = {
lib/backend/obelisk-backend.cabal+1
@@ -17,6 +17,7 @@ library
1717 obelisk-executable-config-inject,
1818 obelisk-frontend,
1919 obelisk-route,
20+ obelisk-snap-extras,
2021 reflex-dom,
2122 snap,
2223 snap-server,
lib/backend/src/Obelisk/Backend.hs+2
@@ -40,6 +40,7 @@ import Obelisk.Asset.Serve.Snap (serveAsset)
4040import Obelisk.ExecutableConfig.Inject (injectExecutableConfigs)
4141import Obelisk.Frontend
4242import Obelisk.Route
43+import Obelisk.Snap.Extras (doNotCache, serveFileIfExistsAs)
4344import Reflex.Dom
4445import Snap (MonadSnap, Snap, commandLineConfig, defaultConfig, getsRequest, httpServe, modifyResponse
4546 , rqPathInfo, rqQueryString, setContentType, writeBS, writeText)
@@ -121,6 +122,7 @@ serveObeliskApp urlEnc serveStaticAsset frontendApp = \case
121122 let msg = "Error: Obelisk.Backend received jsaddle request"
122123 liftIO $ putStrLn $ T.unpack msg
123124 writeText msg
125+ ResourceRoute_Version :=> Identity () -> doNotCache >> serveFileIfExistsAs "text/plain" "version"
124126
125127serveStaticAssets :: MonadSnap m => StaticAssets -> [Text] -> m ()
126128serveStaticAssets assets pathSegments = serveAsset (_staticAssets_processed assets) (_staticAssets_unprocessed assets) $ T.unpack $ T.intercalate "/" pathSegments
lib/command/src/Obelisk/Command/Deploy.hs+24−29
@@ -88,37 +88,32 @@ deployPush deployPath getNixBuilders = do
8888 route <- readDeployConfig deployPath $ "config" </> "common" </> "route"
8989 routeHost <- getHostFromRoute enableHttps route
9090 let srcPath = deployPath </> "src"
91− build = do
92− builders <- getNixBuilders
93− buildOutput <- nixBuild $ def
94− { _nixBuildConfig_target = Target
95− { _target_path = srcPath
96− , _target_attr = Just "server.system"
97− }
98− , _nixBuildConfig_outLink = OutLink_None
99− , _nixBuildConfig_args =
100− [ strArg "hostName" host
101− , strArg "adminEmail" adminEmail
102− , strArg "routeHost" routeHost
103− , boolArg "enableHttps" enableHttps
104− , rawArg "config" $ deployPath </> "config"
105− ]
106− , _nixBuildConfig_builders = builders
107− }
108− return $ listToMaybe $ lines buildOutput
109− result <- readThunk srcPath >>= \case
110− Right (ThunkData_Packed _) ->
111− build
91+ thunkPtr <- readThunk srcPath >>= \case
92+ Right (ThunkData_Packed ptr) -> return ptr
11293 Right (ThunkData_Checkout _) -> do
11394 checkGitCleanStatus srcPath True >>= \case
114− True -> do
115− result <- build
116− packThunk srcPath
117− return result
118− False -> do
119− _ <- failWith $ T.pack $ "ob deploy push: ensure " <> srcPath <> " has no pending changes and latest is pushed upstream."
120− return Nothing
121− _ -> return Nothing
95+ True -> packThunk srcPath
96+ False -> failWith $ T.pack $ "ob deploy push: ensure " <> srcPath <> " has no pending changes and latest is pushed upstream."
97+ Left err -> failWith $ "ob deploy push: couldn't read src thunk: " <> T.pack (show err)
98+ let version = show . _thunkRev_commit $ _thunkPtr_rev thunkPtr
99+ builders <- getNixBuilders
100+ buildOutput <- nixBuild $ def
101+ { _nixBuildConfig_target = Target
102+ { _target_path = srcPath
103+ , _target_attr = Just "server.system"
104+ }
105+ , _nixBuildConfig_outLink = OutLink_None
106+ , _nixBuildConfig_args =
107+ [ strArg "hostName" host
108+ , strArg "adminEmail" adminEmail
109+ , strArg "routeHost" routeHost
110+ , strArg "version" version
111+ , boolArg "enableHttps" enableHttps
112+ , rawArg "config" $ deployPath </> "config"
113+ ]
114+ , _nixBuildConfig_builders = builders
115+ }
116+ let result = listToMaybe $ lines buildOutput
122117 forM_ result $ \res -> do
123118 let knownHostsPath = deployPath </> "backend_known_hosts"
124119 sshOpts = sshArgs knownHostsPath (deployPath </> "ssh_key") False
lib/command/src/Obelisk/Command/Thunk.hs+4−3
@@ -553,7 +553,7 @@ updateThunk p f = withSystemTempDirectory "obelisk-thunkptr-" $ \tmpDir -> do
553553 return tmpThunk
554554 Right _ -> failWith $ "Thunk is not packed"
555555 updateThunkFromTmp p' = do
556− packThunk' True p'
556+ _ <- packThunk' True p'
557557 callProcessAndLogOutput (Notice, Error) $
558558 proc "cp" ["-r", "-T", p', p]
559559
@@ -605,10 +605,10 @@ unpackThunk' noTrail thunkDir = checkThunkDirectory thunkDir >> readThunk thunkD
605605
606606--TODO: add force mode to pack even if changes are present
607607--TODO: add a rollback mode to pack to the original thunk
608−packThunk :: MonadObelisk m => FilePath -> m ()
608+packThunk :: MonadObelisk m => FilePath -> m ThunkPtr
609609packThunk = packThunk' False
610610
611−packThunk' :: MonadObelisk m => Bool -> FilePath -> m ()
611+packThunk' :: MonadObelisk m => Bool -> FilePath -> m ThunkPtr
612612packThunk' noTrail thunkDir = checkThunkDirectory thunkDir >> readThunk thunkDir >>= \case
613613 Left err -> failWith $ T.pack $ "thunk pack: " <> show err
614614 Right (ThunkData_Packed _) -> failWith "pack: thunk is already packed"
@@ -618,6 +618,7 @@ packThunk' noTrail thunkDir = checkThunkDirectory thunkDir >> readThunk thunkDir
618618 thunkPtr <- getThunkPtr thunkDir
619619 callProcessAndLogOutput (Debug, Error) $ proc "rm" ["-rf", thunkDir]
620620 liftIO $ createThunk thunkDir thunkPtr
621+ pure thunkPtr
621622
622623getThunkPtr :: MonadObelisk m => FilePath -> m ThunkPtr
623624getThunkPtr = getThunkPtr' True
lib/route/src/Obelisk/Route.hs+2
@@ -721,6 +721,7 @@ data ResourceRoute :: * -> * where
721721 ResourceRoute_Static :: ResourceRoute [Text] -- This [Text] represents the *path in our static files directory*, not necessarily the URL path that the asset gets served at (although that will often be "/static/this/text/thing")
722722 ResourceRoute_Ghcjs :: ResourceRoute [Text]
723723 ResourceRoute_JSaddleWarp :: ResourceRoute (R JSaddleWarpRoute)
724+ ResourceRoute_Version :: ResourceRoute ()
724725
725726-- | If there are no additional backend routes in your app (i.e. ObeliskRoute gives you all the routes you need),
726727-- this constructs a suitable 'Encoder' to use for encoding routes to 'PageName's. If you do have additional backend routes,
@@ -757,6 +758,7 @@ resourceRouteSegment = \case
757758 ResourceRoute_Static -> PathSegment "static" $ pathOnlyEncoderIgnoringQuery
758759 ResourceRoute_Ghcjs -> PathSegment "ghcjs" $ pathOnlyEncoder
759760 ResourceRoute_JSaddleWarp -> PathSegment "jsaddle" $ jsaddleWarpRouteEncoder
761+ ResourceRoute_Version -> PathSegment "version" $ unitEncoder mempty
760762
761763data JSaddleWarpRoute :: * -> * where
762764 JSaddleWarpRoute_JavaScript :: JSaddleWarpRoute ()