packages feed

nemesis-titan (empty) → 2013.6.13

raw patch · 8 files changed

+340/−0 lines, 8 filesdep +HStringTemplatedep +airdep +basesetup-changed

Dependencies added: HStringTemplate, air, base, bytestring, directory, filepath, hspec, nemesis, random, uuid

Files

+ LICENSE view
@@ -0,0 +1,31 @@+Copyright (c) 2013, Jinjing Wang++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Jinjing Wang nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Nemesis view
@@ -0,0 +1,25 @@+import System.Nemesis.Env+import Air.Env ((-))+import Prelude hiding ((-))+import System.Nemesis.Titan+import System.Nemesis.Jinjing++main = run nemesis++nemesis = do+  +  clean+    [ "**/*.hi"+    , "**/*.o"+    , "manifest"+    , "main"+    , "nemesis-tmp.*"+    , "config/Test"+    , "src/Test.hs"+    ]+  +  cabal_dist++  console ["-isrc", "-Wall"] "src/System/Nemesis/Titan"++  titan "Main.hs"
+ Setup.lhs view
@@ -0,0 +1,4 @@+#! /usr/bin/env runhaskell++> import Distribution.Simple+> main = defaultMain
+ changelog.md view
+ known-issues.md view
+ nemesis-titan.cabal view
@@ -0,0 +1,23 @@+Name:                 nemesis-titan+Version:              2013.6.13+Build-type:           Simple+Synopsis:             A collection of Nemesis tasks to bootstrap a Haskell project with a focus on continuous integration+Description:          ++License:              BSD3+License-file:         LICENSE+Author:               Jinjing Wang+Maintainer:           Jinjing Wang <nfjinjing@gmail.com>+Build-Depends:        base+Cabal-version:        >= 1.2+category:             Web+homepage:             http://github.com/nfjinjing/nemesis-titan+data-files:           readme.md, changelog.md, known-issues.md, Nemesis++library+  ghc-options: -Wall+  build-depends:      base >= 4 && < 100, nemesis, air >= 2011.6.19, uuid, random, directory, bytestring, filepath, HStringTemplate, hspec+                      +  hs-source-dirs: src/+  exposed-modules:  +                      System.Nemesis.Titan
+ readme.md view
@@ -0,0 +1,50 @@+Requirements+============++* [Guard](https://github.com/guard/guard)+* [Angel](https://github.com/MichaelXavier/Angel)++Install+=======+  +    cabal install nemesis-titan+    cabal install air-extra++Usage+=====++    mkdir my_project+    cd my_project+++Bootstrap+---------++    curl https://raw.github.com/nfjinjing/nemesis-titan/master/vendor/Nemesis -o Nemesis+    ++List available tasks+--------------------++    runghc Nemesis+    ++Generate "Main.hs"+-------------------++    runghc Nemesis Main/init+++Start the continuous integration process+------------------------------------------++    runghc Nemesis Main/titan+++Check+=====++Make some changes in `src/Main.hs` and see your code gets auto compiled and tested in the console.+    ++    
+ src/System/Nemesis/Titan.hs view
@@ -0,0 +1,207 @@+{-# LANGUAGE QuasiQuotes #-}++module System.Nemesis.Titan where+  +import System.Nemesis.Env+import System.Nemesis (Unit)++import Air.Env+import Prelude ()+import qualified Data.ByteString.Char8 as B+import qualified Data.UUID as UUID+import System.Directory+import System.Random++import System.Environment (getArgs)+import System.FilePath++import Air.TH (here)++import Test.Hspec+import Text.StringTemplate++angel_template :: StringTemplate String+angel_template = newSTMP - [here|+server {+    exec = "runghc Nemesis $label$/run"+    stdout = "/dev/stdout"+    stderr = "/dev/stderr"+    delay = 0+}++code-reload {+    exec = "runghc Nemesis $label$/guard"+    stdout = "/dev/stdout"+    stderr = "/dev/stderr"+    delay = 0+}++|]+++guard_template :: StringTemplate String+guard_template = newSTMP - [here|+guard :shell do+  watch(%r{^src/.+hs\$}) do |m|+    puts "Changed #{m[0]}"+    `runghc Nemesis $label$/compile && runghc Nemesis $label$/kill`+  end+end++|]+++haskell_template :: StringTemplate String+haskell_template = newSTMP - [here|+module Main where++import Air.Extra (with_spec, halt)+import System.Nemesis.Jinjing.Angel+import Test.Hspec++spec :: IO ()+spec = hspec \$ do+  describe "$label$" \$ do+    it "should run spec" True++main = do+  with_spec spec halt++|]++titan_spec :: IO ()+titan_spec = hspec - do+  describe "Titan" - do+    it "should run spec" True+    +    it "should use templates" - do+      let text = render - setAttribute "label" "Main" angel_template+      +      -- puts text+      +      text `shouldSatisfy` (null > not)+      ++get_label_file_name :: IO (Maybe (String, String))+get_label_file_name = do+  xs <- io getArgs++  case xs of+    (_:file_name:[]) -> +      let label = file_name.takeBaseName+      in+      return - Just (label, file_name)+      +    (_:label:file_name:[]) ->+      return - Just (label, file_name)+    +    _ -> return Nothing+    +  ++titan :: String -> Unit+titan file_name = do+  let label = file_name.takeBaseName+  titan_with_label_file_name label file_name++titan_with_label_file_name :: String -> String -> Unit+titan_with_label_file_name label file_name = titan_with_label_file_name_custom_task label file_name (return ())+++titan_with_label_file_name_custom_task :: String -> String -> Unit -> Unit+titan_with_label_file_name_custom_task label file_name custom_tasks = do+  namespace label - do+    +    let  +      pid_name = "uuid.txt"+      bin_directory = ".bin"+      config_name = "config"+      config_directory = config_name / label+      angel_path = config_directory / "Angel.conf"+      guard_path = config_directory / "Guardfile"+      +      pid_directory = bin_directory / label+      pid_path = pid_directory / pid_name++    desc "Initialize a Titan node"+    task "init" - io - do+      let+        haskell_source_directory = "src"+        haskell_path = haskell_source_directory / file_name+      ++      createDirectoryIfMissing True config_directory+      createDirectoryIfMissing True haskell_source_directory+      +      let +        angel_file_content = render - setAttribute "label" label angel_template+        guard_file_content = render - setAttribute "label" label guard_template+        haskell_file_content = render - setAttribute "label" label haskell_template+      +      let {+        write_if_not_exist file_path str = do+          file_exist <- doesFileExist file_path+          if not - file_exist+            then+              B.writeFile file_path - B.pack str+            else do+              puts - file_path + " already exists!"+              return ()+      }+      write_if_not_exist angel_path angel_file_content +      write_if_not_exist guard_path guard_file_content +      write_if_not_exist haskell_path haskell_file_content+    +                      +    let { get_and_create_if_missing_upid = do+      createDirectoryIfMissing True pid_directory++      pid_exist <- doesFileExist pid_path+++      if pid_exist+        then do+          uuid <- B.readFile pid_path ^ B.unpack+          puts - "UPID: " + uuid+          return uuid      +        else do+          uuid <- randomIO ^ UUID.toString+          puts - "Created UPID: " + uuid+          B.writeFile pid_path - uuid.B.pack+          return - uuid+      }+          +    let { get_bin = do+      uuid <- get_and_create_if_missing_upid+      return - pid_directory / uuid+    }++    desc "Start the Titan managed process"+    task "titan:uuid compile" - do+      sh - "angel " + angel_path++  +    desc "Create a uuid for this process if not already exist"+    task "uuid" - do+      io - void - get_and_create_if_missing_upid++    desc "Compile the binary"+    task "compile" - do+      bin <- get_bin+      sh - "ghc --make -isrc -threaded src/" + file_name + " -o " + bin++    desc "Start the process"+    task "run" - do+      bin <- get_bin+      sh - bin++    desc "Kill the process"+    task "kill" - do+      upid <- get_and_create_if_missing_upid+      sh - "killall " + upid + "; true"+  +    desc "Start the Guard proceses"+    task "guard" - do+      sh - "guard --no-bundler-warning -G " + guard_path+  +    custom_tasks