hapistrano 0.2.1.1 → 0.2.1.2
raw patch · 4 files changed
+195/−24 lines, 4 filesdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base
API changes (from Hackage documentation)
- System.Hapistrano: buildScript :: Config -> Maybe FilePath
- System.Hapistrano: deployPath :: Config -> String
- System.Hapistrano: host :: Config -> Maybe String
- System.Hapistrano: releaseFormat :: Config -> ReleaseFormat
- System.Hapistrano: repository :: Config -> String
- System.Hapistrano: restartCommand :: Config -> Maybe String
- System.Hapistrano: revision :: Config -> String
+ System.Hapistrano: [buildScript] :: Config -> Maybe FilePath
+ System.Hapistrano: [deployPath] :: Config -> String
+ System.Hapistrano: [host] :: Config -> Maybe String
+ System.Hapistrano: [releaseFormat] :: Config -> ReleaseFormat
+ System.Hapistrano: [repository] :: Config -> String
+ System.Hapistrano: [restartCommand] :: Config -> Maybe String
+ System.Hapistrano: [revision] :: Config -> String
Files
- README.md +84/−0
- app/Main.hs +95/−22
- changes.md +13/−0
- hapistrano.cabal +3/−2
+ README.md view
@@ -0,0 +1,84 @@+[](https://travis-ci.org/stackbuilders/hapistrano) [](http://hackage.haskell.org/package/hapistrano)++# Hapistrano++Hapistrano is a deployment library for Haskell applications similar to+Ruby's [Capistrano](http://capistranorb.com/).++## Purpose++We created Hapistrano because:++* Deploys should be simple, but as close to atomic as possible (eg,+ they shouldn't require much application downtime).+* Rollback should be trivial to achieve to bring the application back+ to the last-deployed state.+* Deploys shouldn't fail because of dependency problems.++## How it Works++Hapistrano (like Capistrano for Ruby) deploys applications to a new+directory marked with a timestamp on the remote host. It creates this+new directory quickly by placing a git repository for caching purposes+on the remote server.++When the build process completes, it switches a symlink to the+'current' release directory, and optionally restarts the web server.++By default, Hapistrano keeps the last five releases on the target host+filesystem and deletes previous releases to avoid filling up the disk.++## Usage++The deploy requires the following environment variables:++* `DEPLOY_PATH` - The root of the deploy target on the remote host+* `HOST` - The target host+* `REPOSITORY` - The origin repository+* `REVISION` - The SHA1 or branch to deploy. If a branch, you will need+ to specify it as origin/branch_name due to the way that the cache+ repo is configured.++The following environment variables are *optional* and affect the+deploy process:++* `BUILD_SCRIPT` - The local path to a file that should be executed on+ the remote server to build the application. The script isn't+ executed verbatim - instead, every line is joined with `&&` so that+ the script aborts if any component fails. See a sample script for a+ clean build of a Haskell/Cabal application in this project under+ [script/clean-build.sh].+* `RESTART_COMMAND` - If you need to restart a remote web server after a+ successful deploy, specify the command that you use in this+ variable. It will be run after both deploy and rollback.++You may want to save the environment variables that you need for your+deploy in a shell script that you `source` before deploy. Make sure+you `export` these variables so that they're available in the shell+after you run the script. For example, you could use the following to+configure your deploy:++ export DEPLOY_PATH="/var/project"+ export HOST="my-app-staging"+ export REPOSITORY="git@github.com:yourorg/yourrepo.com.git"+ export REVISION="origin/staging"+ export BUILD_SCRIPT="/home/you/Code/hapistrano/script/clean-build.sh"+ export RESTART_COMMAND="echo Replace me with your restart command"++After creating a configuration script as above, deploying is as simple as:++ source your-config-script.sh && hap deploy++# License++MIT, see [the LICENSE file](LICENSE).+++# Contributing++Pull requests for modifications to this program are welcome. Fork and+open a PR. Feel free to [email me](mailto:justin@stackbuilders.com) if+you have questions about what may be accepted before working on a PR.++If you're looking for a place to start, you may want to check the+[open issue](https://github.com/stackbuilders/hapistrano/issues).
app/Main.hs view
@@ -1,14 +1,21 @@-module Main where+{-# LANGUAGE RecordWildCards #-} +module Main (main) where+ import qualified System.Hapistrano as Hap import Control.Monad (void)-import System.Environment (getArgs, getEnv) import System.Environment.Compat (lookupEnv)-import System.IO (hPutStrLn, stderr)-import System.Exit (exitFailure) import System.Hapistrano (ReleaseFormat(..)) +import qualified Control.Monad as Monad+import qualified Data.Maybe as Maybe+import qualified System.Console.GetOpt as GetOpt+import qualified System.Environment as Environment+import qualified System.Exit as Exit+import qualified System.Exit.Compat as Exit+import qualified System.IO as IO+ -- | Rolls back to previous release. rollback :: Hap.Config -> IO () rollback cfg =@@ -36,15 +43,18 @@ -- | Retrieves the configuration from environment variables. configFromEnv :: IO Hap.Config configFromEnv = do- deployPath <- getEnv "DEPLOY_PATH"- repository <- getEnv "REPOSITORY"- revision <- getEnv "REVISION"+ maybeDeployPath <- lookupEnv "DEPLOY_PATH"+ maybeRepository <- lookupEnv "REPOSITORY"+ maybeRevision <- lookupEnv "REVISION" + deployPath <- maybe (Exit.die (noEnv "DEPLOY_PATH")) return maybeDeployPath+ repository <- maybe (Exit.die (noEnv "REPOSITORY")) return maybeRepository+ revision <- maybe (Exit.die (noEnv "REVISION")) return maybeRevision+ host <- lookupEnv "HOST" buildScript <- lookupEnv "BUILD_SCRIPT" restartCommand <- lookupEnv "RESTART_COMMAND" - return Hap.Config { Hap.deployPath = deployPath , Hap.host = host , Hap.releaseFormat = Short@@ -53,22 +63,85 @@ , Hap.buildScript = buildScript , Hap.restartCommand = restartCommand }+ where+ noEnv env = env ++ " environment variable does not exist" +data HapCommand+ = HapDeploy+ | HapRollback+ deriving Show++parseHapCommand :: String -> Maybe HapCommand+parseHapCommand "deploy" = Just HapDeploy+parseHapCommand "rollback" = Just HapRollback+parseHapCommand _ = Nothing++data HapOptions =+ HapOptions+ { hapCommand :: Maybe HapCommand+ , hapHelp :: Bool+ }+ deriving Show++defaultHapOptions :: HapOptions+defaultHapOptions =+ HapOptions+ { hapCommand = Nothing+ , hapHelp = False+ }++hapOptionDescriptions :: [GetOpt.OptDescr (HapOptions -> HapOptions)]+hapOptionDescriptions =+ [ GetOpt.Option+ ['h']+ ["help"]+ (GetOpt.NoArg (\hapOptions -> hapOptions { hapHelp = True }))+ "Show this help text"++ ]++parseHapOptions :: [String] -> Either String HapOptions+parseHapOptions args =+ case GetOpt.getOpt GetOpt.Permute hapOptionDescriptions args of+ (options, [], []) ->+ Right (foldl (flip id) defaultHapOptions options)++ (options, [command], []) ->+ case parseHapCommand command of+ Nothing ->+ Left ("Invalid argument: " ++ command)++ maybeHC ->+ Right (foldl (flip id) defaultHapOptions {hapCommand = maybeHC} options)++ _ ->+ Left "First argument must be either 'deploy' or 'rollback'."++hapHelpAction :: Maybe HapCommand -> IO ()+hapHelpAction _ =+ putStrLn hapUsage >> Exit.exitSuccess++hapUsage :: String+hapUsage =+ GetOpt.usageInfo hapUsageHeader hapOptionDescriptions++hapUsageHeader :: String+hapUsageHeader =+ "usage: hap [-h | --help] <command>\n"+ main :: IO () main = do- args <- getArgs- case args of- [] -> do- hPutStrLn stderr- "First argument must be either 'deploy' or 'rollback'."- exitFailure+ eitherHapOptions <- fmap parseHapOptions Environment.getArgs - arg1:_ -> do- cfg <- configFromEnv+ HapOptions{..} <- either Exit.die return eitherHapOptions - case arg1 of- "deploy" -> deploy cfg- "rollback" -> rollback cfg- _ -> do- hPutStrLn stderr $ "Invalid argument: " ++ arg1- exitFailure+ Monad.when hapHelp (hapHelpAction hapCommand)++ hapConfiguration <- configFromEnv++ case hapCommand of+ Just HapDeploy -> deploy hapConfiguration++ Just HapRollback -> rollback hapConfiguration++ Nothing -> hapHelpAction Nothing
+ changes.md view
@@ -0,0 +1,13 @@+## Unreleased changes++* Add change log (#23).++## 0.2.1.1++* Fix tests (#31).++## 0.2.1++* Use Stack (#17).+* Clean up package (#20).+* Fix tests (#25).
hapistrano.cabal view
@@ -1,5 +1,5 @@ name: hapistrano-version: 0.2.1.1+version: 0.2.1.2 synopsis: A deployment library for Haskell applications description: .@@ -28,12 +28,13 @@ bug-reports: https://github.com/stackbuilders/hapistrano/issues build-type: Simple cabal-version: >=1.10+extra-source-files: changes.md README.md library hs-source-dirs: src exposed-modules: System.Hapistrano other-modules: System.Hapistrano.Types- build-depends: base >=4.5 && <4.9+ build-depends: base >= 4.5 && < 4.10 , either , filepath , mtl