mudbath-0.0.3: Executor.hs
{-# LANGUAGE OverloadedStrings #-}
module Executor
( executeDeploymentScript
) where
import Data.List
import Data.Text (Text)
import qualified Data.Text as T
import Data.Monoid
import Control.Applicative
import Control.Arrow
import System.Directory
import System.Exit
import System.Process (CreateProcess, createProcess, proc, waitForProcess)
import System.Random
import GitHub
import GitHub.Types
executeDeploymentScript :: DeploymentEvent -> IO ()
executeDeploymentScript ev = do
updateDeploymentStatus ev Pending
tmp <- buildDirectory
deploy ev tmp
randomString :: RandomGen d => Int -> d -> (String, d)
randomString len =
first (Data.List.map toChar) . sequence' (Data.List.replicate len (randomR (0, 61)))
where
sequence' [] g = ([], g)
sequence' (f:fs) g =
let (f', g') = f g
(fs', g'') = sequence' fs g'
in (f' : fs', g'')
toChar i
| i < 26 = toEnum $ i + fromEnum 'A'
| i < 52 = toEnum $ i + fromEnum 'a' - 26
| otherwise = toEnum $ i + fromEnum '0' - 52
generateRandomString :: IO Text
generateRandomString = do
stdgen <- newStdGen
return $ T.pack $ fst $ randomString 20 stdgen
buildDirectory :: IO Text
buildDirectory = mappend "/tmp/mudbath/build/" <$> generateRandomString
setupScript :: Text -> Text -> Text -> Text -> String
setupScript cachePath buildPath url commit = T.unpack $ mconcat $ Data.List.intersperse ";"
[ "set -e"
, "if test -d " <> cachePath
, "then cd " <> cachePath <> " && git fetch --all --quiet"
, "else git clone --mirror --quiet " <> url <> " " <> cachePath
, "fi"
, "rm -rf " <> buildPath
, "git clone --quiet --reference " <> cachePath <> " " <> url <> " " <> buildPath
, "cd " <> buildPath
, "git checkout -q " <> commit
]
spawn :: CreateProcess -> IO ExitCode
spawn x = do
(_, _, _, p) <- createProcess x
waitForProcess p
deploy :: DeploymentEvent -> Text -> IO ()
deploy de tmp = do
clone >>= test >>= updateDeploymentStatus de >> cleanup
where
d = deploymentEventDeployment de
sha = deploymentSha d
repo = deploymentEventRepository de
dEnv = deploymentEnvironment d
repoName = repositoryFullName repo
clone = do
let cachePath = "/tmp/mudbath/cache/" <> repoName
let url = "git@github.com:" <> repoName <> ".git"
exitCode <- spawn $ proc "sh" [ "-c", setupScript cachePath tmp url sha ]
print $ "clone " ++ show exitCode
case exitCode of
ExitSuccess -> return Success
_ -> return Error
test Error = return Error
test _ = do
let script = "./config/" <> repoName <> "/" <> dEnv
print $ show $ "executing " <> script
exitCode <- spawn $ proc (T.unpack script) [T.unpack tmp]
print $ "test " ++ show exitCode
case exitCode of
ExitSuccess -> return Success
_ -> return Failure
cleanup = removeDirectoryRecursive $ T.unpack tmp