-- | -- Module : System.Hapistrano.Types -- Copyright : © 2015-2017 Stack Builders -- License : MIT -- -- Maintainer : Justin Leitgeb -- Stability : experimental -- Portability : portable -- -- Type definitions for the Hapistrano tool. module System.Hapistrano.Types ( Hapistrano , Failure (..) , Config (..) , Task (..) , ReleaseFormat(..) , SshOptions (..) , OutputDest (..) , Release , mkRelease , releaseTime , renderRelease , parseRelease ) where import Control.Applicative import Control.Monad.Except import Control.Monad.Reader import Data.Time import Path -- | Hapistrano monad. type Hapistrano a = ExceptT Failure (ReaderT Config IO) a -- | Failure with status code and a message. data Failure = Failure Int (Maybe String) -- | Hapistrano configuration options. data Config = Config { configSshOptions :: !(Maybe SshOptions) -- ^ 'Nothing' if we are running locally, or SSH options to use. , configPrint :: !(OutputDest -> String -> IO ()) -- ^ How to print messages } -- | The records describes deployment task. data Task = Task { taskDeployPath :: Path Abs Dir -- ^ The root of the deploy target on the remote host , taskRepository :: String -- ^ The URL of remote Git repo to deploy , taskRevision :: String -- ^ A SHA1 or branch to release , taskReleaseFormat :: ReleaseFormat -- ^ The 'ReleaseFormat' to use } deriving (Show, Eq, Ord) -- | Release format mode. data ReleaseFormat = ReleaseShort -- ^ Standard release path following Capistrano's format | ReleaseLong -- ^ Long release path including picoseconds deriving (Show, Read, Eq, Ord, Enum, Bounded) -- | SSH options. data SshOptions = SshOptions { sshHost :: String -- ^ Host to use , sshPort :: Word -- ^ Port to use } deriving (Show, Read, Eq, Ord) -- | Output destination. data OutputDest = StdoutDest | StderrDest deriving (Eq, Show, Read, Ord, Bounded, Enum) -- | Release indentifier. data Release = Release ReleaseFormat UTCTime deriving (Eq, Show, Ord) -- | Create a 'Release' indentifier. mkRelease :: ReleaseFormat -> UTCTime -> Release mkRelease = Release -- | Extract deployment time from 'Release'. releaseTime :: Release -> UTCTime releaseTime (Release _ time) = time -- | Render 'Release' indentifier as a 'String'. renderRelease :: Release -> String renderRelease (Release rfmt time) = formatTime defaultTimeLocale fmt time where fmt = case rfmt of ReleaseShort -> releaseFormatShort ReleaseLong -> releaseFormatLong -- | Parse 'Release' identifier from a 'String'. parseRelease :: String -> Maybe Release parseRelease s = (Release ReleaseLong <$> p releaseFormatLong s) <|> (Release ReleaseShort <$> p releaseFormatShort s) where p = parseTimeM False defaultTimeLocale releaseFormatShort, releaseFormatLong :: String releaseFormatShort = "%Y%m%d%H%M%S" releaseFormatLong = "%Y%m%d%H%M%S%q"