hackmanager (empty) → 0.1.0.0
raw patch · 15 files changed
+760/−0 lines, 15 filesdep +Cabaldep +Globdep +basesetup-changed
Dependencies added: Cabal, Glob, base, bytestring, directory, file-embed, hackmanager, hastache, http-client, http-client-tls, http-types, mtl, optparse-applicative, process, text
Files
- LICENSE +30/−0
- README.md +90/−0
- Setup.hs +2/−0
- app/Main.hs +64/−0
- examples/ReadmePrinter.hs +15/−0
- hackmanager.cabal +60/−0
- src/Hack/Manager/Collector.hs +167/−0
- src/Hack/Manager/Gitignore.hs +30/−0
- src/Hack/Manager/Readme.hs +30/−0
- src/Hack/Manager/Travis.hs +56/−0
- src/Hack/Manager/Types.hs +41/−0
- templates/README.mustache +67/−0
- templates/gitignore.mustache +22/−0
- templates/travis-cabal.mustache +40/−0
- templates/travis-stack.mustache +46/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2015 Alexander Thiemann++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 Alexander Thiemann 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.
+ README.md view
@@ -0,0 +1,90 @@+hackmanager+=====++[](https://travis-ci.org/agrafix/hackmanager)+++## Intro+++Generate useful files for Haskell projects++## Cli Usage: hackmanager++```sh+$ hackmanager --help+hackmanager - Generate useful files for Haskell projects++Usage: hackmanager COMMAND+ Simplify managing Haskell projects by generating files like README.md,+ .travis.yml, etc.++Available options:+ -h,--help Show this help text++Available commands:+ readme + travis + gitignore ++(c) 2015 Alexander Thiemann - BSD3 License++```++## Library Usage Example++```haskell+module Main where++import Hack.Manager.Collector+import Hack.Manager.Readme++import qualified Data.Text as T++main :: IO ()+main =+ do pi <- getProjectInfo+ case pi of+ Left err -> putStrLn err+ Right info ->+ do rm <- renderReadme info+ putStrLn (T.unpack rm)++```++## Install++* From Source (cabal): `git clone https://github.com/agrafix/hackmanager.git && cd hackmanager && cabal install`+* From Source (stack): `git clone https://github.com/agrafix/hackmanager.git && cd hackmanager && stack build`++## Features++* Automagically collect package information such as+ * package name+ * GHC compatibility+ * stack Project+ * Hackage / Stackage status+ * License+ * Examples+ * Cli Usage+* Typecheck examples+* Generate informative README.md (Can be extended using a MORE.md)+* Generate .travis.yml (cabal or stack based)+* Generate .gitignore++The generated `.travis.yml` and `.gitignore` are intended as starting templates, while the generated `README.md` should not be modified by hand. Rerun `hackmanager readme` before every commit (commit hook?) to keep it up to date. If you would like to add custom sections, create a `MORE.md`.++## Roadmap++There's no real roadmap - I will add features as needed. I am open to any contributions!++## Misc++### Supported GHC Versions++* 7.10.2++### License++Released under the BSD3 license.+(c) 2015 Alexander Thiemann
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE OverloadedStrings #-}+module Main where++import Hack.Manager.Collector+import Hack.Manager.Gitignore+import Hack.Manager.Readme+import Hack.Manager.Travis+import Hack.Manager.Types++import Control.Monad+import Options.Applicative+import qualified Data.Text as T+import qualified Data.Text.IO as T++main :: IO ()+main = join $ execParser optParser++withProjectInfo :: (ProjectInfo -> IO ()) -> IO ()+withProjectInfo cont =+ do raw <- getProjectInfo+ case raw of+ Left err ->+ putStrLn err+ Right pinfo ->+ cont pinfo++makeReadme :: IO ()+makeReadme =+ withProjectInfo $ \pinfo ->+ do rm <- renderReadme pinfo+ T.writeFile "README.md" rm++makeTravis :: TravisOpts -> IO ()+makeTravis to =+ withProjectInfo $ \pinfo ->+ do travis <- renderTravis to pinfo+ T.writeFile ".travis.yml" travis++travisOptsParser :: Parser TravisOpts+travisOptsParser =+ TravisOpts+ <$> (T.pack <$> argument str (metavar "GHC-RELEASE_VERSION"))+ <*> switch (long "use-stack" <> help "Use stack to run travis build")++makeGitignore :: IO ()+makeGitignore =+ withProjectInfo $ \pinfo ->+ do gitignore <- renderGitignore pinfo+ T.writeFile ".gitignore" gitignore++commands :: Mod CommandFields (IO ())+commands =+ command "readme" (info (pure makeReadme) idm)+ <> command "travis" (info (makeTravis <$> travisOptsParser) idm)+ <> command "gitignore" (info (pure makeGitignore) idm)++optParser :: ParserInfo (IO ())+optParser =+ info (helper <*> subparser commands)+ ( fullDesc+ <> progDesc "Simplify managing Haskell projects by generating files like README.md, .travis.yml, etc."+ <> header "hackmanager - Generate useful files for Haskell projects"+ <> footer "(c) 2015 Alexander Thiemann - BSD3 License"+ )
+ examples/ReadmePrinter.hs view
@@ -0,0 +1,15 @@+module Main where++import Hack.Manager.Collector+import Hack.Manager.Readme++import qualified Data.Text as T++main :: IO ()+main =+ do pi <- getProjectInfo+ case pi of+ Left err -> putStrLn err+ Right info ->+ do rm <- renderReadme info+ putStrLn (T.unpack rm)
+ hackmanager.cabal view
@@ -0,0 +1,60 @@+name: hackmanager+version: 0.1.0.0+synopsis: Generate useful files for Haskell projects+description: Simplify managing Haskell projects by generating files like README.md, .travis.yml, etc.+homepage: http://github.com/agrafix/hackmanager+license: BSD3+license-file: LICENSE+author: Alexander Thiemann <mail@athiemann.net>+maintainer: Alexander Thiemann <mail@athiemann.net>+copyright: (c) 2015 Alexander Thiemann+category: Development+build-type: Simple+cabal-version: >=1.10+tested-with: GHC==7.10.*+extra-source-files:+ README.md+ templates/README.mustache+ templates/travis-stack.mustache+ templates/travis-cabal.mustache+ templates/gitignore.mustache+ examples/ReadmePrinter.hs++library+ hs-source-dirs: src+ exposed-modules:+ Hack.Manager.Readme+ Hack.Manager.Types+ Hack.Manager.Collector+ Hack.Manager.Travis+ Hack.Manager.Gitignore+ build-depends:+ base >= 4.7 && < 5,+ hastache >=0.6,+ file-embed >=0.0.8,+ bytestring >=0.10,+ Glob >=0.7,+ Cabal >=1.20,+ text >=1.2,+ mtl >=2.2,+ process >=1.2,+ http-client >=0.4,+ http-client-tls >=0.2,+ http-types >=0.8.6,+ directory >=1.2+ default-language: Haskell2010++executable hackmanager+ hs-source-dirs: app+ main-is: Main.hs+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base,+ hackmanager,+ text >=1.2,+ optparse-applicative >=0.11+ default-language: Haskell2010++source-repository head+ type: git+ location: https://github.com/agrafix/hackmanager
+ src/Hack/Manager/Collector.hs view
@@ -0,0 +1,167 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+module Hack.Manager.Collector where++import Hack.Manager.Types++import Control.Exception+import Control.Monad.Except+import System.Directory+import System.Exit+import System.Process+import qualified Data.List as L+import qualified Data.Text as T+import qualified Distribution.Compiler as Comp+import qualified Distribution.Package as Pkg+import qualified Distribution.PackageDescription as PD+import qualified Distribution.PackageDescription.Parse as PD+import qualified Distribution.Text as DT+import qualified Distribution.Version as Vers+import qualified Network.HTTP.Client as C+import qualified Network.HTTP.Client.TLS as C+import qualified Network.HTTP.Types.Status as Http+import qualified System.FilePath.Glob as G++getProjectInfo :: IO (Either String ProjectInfo)+getProjectInfo =+ runExceptT $+ do cabalFiles <- liftIO $ G.glob "*.cabal"+ case cabalFiles of+ [] -> throwError "No cabal file in working directory!"+ (f1:_) ->+ do cabalData <- liftIO $ readFile f1+ case PD.parsePackageDescription cabalData of+ PD.ParseFailed err -> throwError (show err)+ PD.ParseOk _ val -> compileProjectInfo val++onStackageCheck :: T.Text -> IO Bool+onStackageCheck projectName =+ do mgr <- C.newManager C.tlsManagerSettings+ initReq <- C.parseUrl ("https://www.stackage.org/package/" ++ T.unpack projectName)+ let tryGet =+ do resp <- C.httpNoBody initReq mgr+ return $ C.responseStatus resp == Http.ok200+ tryGet `catch` \(_ :: SomeException) -> return False++onHackageCheck :: T.Text -> IO Bool+onHackageCheck projectName =+ do mgr <- C.newManager C.tlsManagerSettings+ initReq <- C.parseUrl ("https://hackage.haskell.org/package/" ++ T.unpack projectName)+ let tryGet =+ do resp <- C.httpNoBody initReq mgr+ return $ C.responseStatus resp == Http.ok200+ tryGet `catch` \(_ :: SomeException) -> return False++findGhcVersions :: [(Comp.CompilerFlavor, Vers.VersionRange)] -> ExceptT String IO [T.Text]+findGhcVersions origVersions =+ forM versions $ \vers ->+ let loop [] = throwError ("Unknown ghc version: " ++ show vers)+ loop (x:xs) =+ if Vers.withinRange x vers then return x else loop xs+ in liftM (T.pack . DT.display) $ loop ghcLatest+ where+ versions = map snd $ filter (\(flavor, _) -> flavor == Comp.GHC) origVersions+ ghcLatest =+ [ Vers.Version [7, 4, 2] []+ , Vers.Version [7, 6, 3] []+ , Vers.Version [7, 8, 4] []+ , Vers.Version [7, 10, 2] []+ ]++getCliUsage :: Bool -> [String] -> ExceptT String IO [CliExecutable]+getCliUsage hasStack exec =+ forM exec $ \program ->+ do (ec, stdOut, stdErr) <-+ liftIO $+ if hasStack+ then readProcessWithExitCode "/bin/bash" ["-c", "stack exec -- " ++ program ++ " --help"] ""+ else readProcessWithExitCode "/bin/bash" ["-c", "cabal run -- " ++ program ++ " --help"] ""+ when (ec /= ExitSuccess) $+ throwError $ "Failed to run " ++ program ++ " --help to retrieve cli usage. StdOut was: " ++ stdOut ++ " \n StdErr was: " ++ stdErr+ return+ CliExecutable+ { ce_name = T.pack program+ , ce_help = T.pack stdOut+ }++moreFile :: ExceptT String IO (Maybe T.Text)+moreFile =+ liftIO $+ do more <- doesFileExist "MORE.md"+ if more+ then do ct <- readFile "MORE.md"+ return (Just $ T.pack ct)+ else return Nothing++compileProjectInfo :: PD.GenericPackageDescription -> ExceptT String IO ProjectInfo+compileProjectInfo gpd =+ do let pkgName = T.pack $ Pkg.unPackageName $ Pkg.pkgName $ PD.package pd+ ghInfo <-+ case filter repoFilter $ PD.sourceRepos pd of+ [] -> throwError "No head github source-repository given in cabal file!"+ (repo:_) ->+ case PD.repoLocation repo of+ Nothing ->+ throwError "Missing source-repository location"+ Just loc -> extractGithub loc+ hasStack <- liftM (not . L.null) $ liftIO $ G.glob "stack*.yaml"+ (example, hasMoreEx) <-+ do files <- liftIO $ G.glob "examples/*.hs"+ forM_ files $ \file ->+ do res <-+ liftIO $+ if hasStack+ then system $ "stack exec -- ghc -fno-code " ++ file+ else system $ "cabal exec -- ghc -fno-code " ++ file+ when (res /= ExitSuccess) $ throwError $ "Failed to compile " ++ file+ case files of+ [] -> return (Nothing, False)+ (file:xs) ->+ do ex <- liftIO $ readFile file+ return (Just $ T.pack ex, not $ L.null xs)+ onStackage <- liftIO $ onStackageCheck pkgName+ onHackage <- liftIO $ onHackageCheck pkgName+ ghcVers <- findGhcVersions (PD.testedWith pd)+ cliUsage <- getCliUsage hasStack (map fst $ PD.condExecutables gpd)+ moreFile <- moreFile+ return+ ProjectInfo+ { pi_name = pkgName+ , pi_pkgName = pkgName+ , pi_pkgDesc = T.pack $ PD.synopsis pd+ , pi_stackFile = hasStack+ , pi_onStackage = onStackage+ , pi_onHackage = onHackage+ , pi_example = example+ , pi_moreExamples = hasMoreEx+ , pi_github = ghInfo+ , pi_license =+ LicenseInfo+ { li_copyright = T.pack $ PD.copyright pd+ , li_type = T.pack $ DT.display $ PD.license pd+ }+ , pi_ghcVersions = ghcVers+ , pi_cliUsage = cliUsage+ , pi_moreInfo = moreFile+ }+ where+ pd = PD.packageDescription gpd+ repoFilter rep =+ PD.repoKind rep == PD.RepoHead+ && PD.repoType rep == Just PD.Git+ && checkGithub (PD.repoLocation rep)+ checkGithub r =+ case r of+ Nothing -> False+ Just str -> "github.com" `L.isInfixOf` str+ extractGithub loc =+ case L.stripPrefix "https://github.com/" loc of+ Nothing ->+ throwError "source-repository location must start with https://github.com/"+ Just rest ->+ let (usr, slashedRepo) = L.break (=='/') rest+ in return+ GithubInfo+ { gi_user = T.pack usr+ , gi_project = T.pack $ L.drop 1 slashedRepo+ }
+ src/Hack/Manager/Gitignore.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}+module Hack.Manager.Gitignore+ ( renderGitignore )+where++import Hack.Manager.Types++import Control.Monad+import Data.FileEmbed+import qualified Data.ByteString as BS+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Data.Text.Lazy as TL+import qualified Text.Hastache as H+import qualified Text.Hastache.Context as H++giTemplate :: BS.ByteString+giTemplate = $(embedFile "templates/gitignore.mustache")++renderGitignore :: ProjectInfo -> IO T.Text+renderGitignore pinfo =+ liftM TL.toStrict $ H.hastacheStr cfg (T.decodeUtf8 giTemplate) ctx+ where+ ctx = H.mkGenericContext pinfo+ cfg =+ H.defaultConfig+ { H.muTemplateFileDir = Nothing+ , H.muEscapeFunc = H.emptyEscape+ }
+ src/Hack/Manager/Readme.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}+module Hack.Manager.Readme+ ( renderReadme )+where++import Hack.Manager.Types++import Control.Monad+import Data.FileEmbed+import qualified Data.ByteString as BS+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Data.Text.Lazy as TL+import qualified Text.Hastache as H+import qualified Text.Hastache.Context as H++readmeTemplate :: BS.ByteString+readmeTemplate = $(embedFile "templates/README.mustache")++renderReadme :: ProjectInfo -> IO T.Text+renderReadme pinfo =+ liftM TL.toStrict $ H.hastacheStr cfg (T.decodeUtf8 readmeTemplate) ctx+ where+ ctx = H.mkGenericContext pinfo+ cfg =+ H.defaultConfig+ { H.muTemplateFileDir = Nothing+ , H.muEscapeFunc = H.emptyEscape+ }
+ src/Hack/Manager/Travis.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE DeriveDataTypeable #-}+module Hack.Manager.Travis+ ( renderTravis+ , TravisOpts (..)+ )+where++import Hack.Manager.Types++import Control.Monad+import Data.Data+import Data.FileEmbed+import qualified Data.ByteString as BS+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Data.Text.Lazy as TL+import qualified Text.Hastache as H+import qualified Text.Hastache.Context as H++data TravisOpts+ = TravisOpts+ { to_ghcRelease :: T.Text+ , to_useStack :: Bool+ } deriving (Show, Eq, Data, Typeable)++data TravisCtx+ = TravisCtx+ { tc_project :: ProjectInfo+ , tc_opts :: TravisOpts+ } deriving (Show, Eq, Data, Typeable)++stackTemplate :: BS.ByteString+stackTemplate = $(embedFile "templates/travis-stack.mustache")++cabalTemplate :: BS.ByteString+cabalTemplate = $(embedFile "templates/travis-cabal.mustache")++renderTravis :: TravisOpts -> ProjectInfo -> IO T.Text+renderTravis to pinfo =+ liftM TL.toStrict $ H.hastacheStr cfg (T.decodeUtf8 tpl) ctx+ where+ tpl =+ if to_useStack to then stackTemplate else cabalTemplate+ ctx =+ H.mkGenericContext $+ TravisCtx+ { tc_project = pinfo+ , tc_opts = to+ }+ cfg =+ H.defaultConfig+ { H.muTemplateFileDir = Nothing+ , H.muEscapeFunc = H.emptyEscape+ }
+ src/Hack/Manager/Types.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE DeriveDataTypeable #-}+module Hack.Manager.Types where++import Data.Data+import Data.Typeable+import qualified Data.Text as T++data GithubInfo+ = GithubInfo+ { gi_user :: T.Text+ , gi_project :: T.Text+ } deriving (Show, Eq, Data, Typeable)++data LicenseInfo+ = LicenseInfo+ { li_type :: T.Text+ , li_copyright :: T.Text+ } deriving (Show, Eq, Data, Typeable)++data CliExecutable+ = CliExecutable+ { ce_name :: T.Text+ , ce_help :: T.Text+ } deriving (Show, Eq, Data, Typeable)++data ProjectInfo+ = ProjectInfo+ { pi_name :: T.Text+ , pi_pkgName :: T.Text+ , pi_pkgDesc :: T.Text+ , pi_stackFile :: Bool+ , pi_onStackage :: Bool+ , pi_onHackage :: Bool+ , pi_example :: Maybe T.Text+ , pi_moreExamples :: Bool+ , pi_cliUsage :: [CliExecutable]+ , pi_github :: GithubInfo+ , pi_license :: LicenseInfo+ , pi_ghcVersions :: [T.Text]+ , pi_moreInfo :: Maybe T.Text+ } deriving (Show, Eq, Data, Typeable)
+ templates/README.mustache view
@@ -0,0 +1,67 @@+{{pi_name}}+=====++[](https://travis-ci.org/{{pi_github.gi_user}}/{{pi_github.gi_project}})+{{#pi_onHackage}}[](http://hackage.haskell.org/package/{{pi_pkgName}}){{/pi_onHackage}}++## Intro++{{#pi_onHackage}}+Hackage: [{{pi_pkgName}}](http://hackage.haskell.org/package/{{pi_pkgName}})+{{/pi_onHackage}}+{{#pi_onStackage}}+Stackage: [{{pi_pkgName}}](https://www.stackage.org/package/{{pi_pkgName}})+{{/pi_onStackage}}++{{pi_pkgDesc}}++{{#pi_cliUsage}}+## Cli Usage: {{ce_name}}++```sh+$ {{ce_name}} --help+{{ce_help}}+```+{{/pi_cliUsage}}++{{#pi_example}}+## Library Usage Example++```haskell+{{.}}+```+{{#pi_moreExamples}}++For more examples check the examples/ directory.+{{/pi_moreExamples}}++{{/pi_example}}+## Install++{{#pi_onHackage}}+* Using cabal: `cabal install {{pi_pkgName}}`+{{/pi_onHackage}}+{{#pi_onStackage}}+* Using Stack: `stack install {{pi_pkgName}}`+{{/pi_onStackage}}+* From Source (cabal): `git clone https://github.com/{{pi_github.gi_user}}/{{pi_github.gi_project}}.git && cd {{pi_github.gi_project}} && cabal install`+{{#pi_stackFile}}+* From Source (stack): `git clone https://github.com/{{pi_github.gi_user}}/{{pi_github.gi_project}}.git && cd {{pi_github.gi_project}} && stack build`+{{/pi_stackFile}}++{{#pi_moreInfo}}+{{.}}+{{/pi_moreInfo}}++## Misc++### Supported GHC Versions++{{#pi_ghcVersions}}+* {{.}}+{{/pi_ghcVersions}}++### License++Released under the {{pi_license.li_type}} license.+{{pi_license.li_copyright}}
+ templates/gitignore.mustache view
@@ -0,0 +1,22 @@+{{^pi_stackFile}}+dist+cabal-dev+{{/pi_stackFile}}+*.o+*.hi+*.chi+*.chs.h+*.dyn_o+*.dyn_hi+.hpc+.hsenv+{{^pi_stackFile}}+.cabal-sandbox/+cabal.sandbox.config+{{/pi_stackFile}}+*.prof+*.aux+*.hp+{{#pi_stackFile}}+.stack-work/+{{/pi_stackFile}}
+ templates/travis-cabal.mustache view
@@ -0,0 +1,40 @@+language: haskell+env:+{{#tc_project.pi_ghcVersions}}+- GHCVER={{.}}+{{/tc_project.pi_ghcVersions}}+- GHCVER=head+matrix:+ allow_failures:+ - env: GHCVER=head+before_install:+- |+ if [ $GHCVER = `ghc --numeric-version` ]; then+ travis/cabal-apt-install --enable-tests $MODE+ export CABAL=cabal+ else+ travis_retry sudo add-apt-repository -y ppa:hvr/ghc+ travis_retry sudo apt-get update+ travis_retry sudo apt-get install cabal-install-1.22 ghc-$GHCVER happy+ export CABAL=cabal-1.22+ export PATH=/opt/ghc/$GHCVER/bin:$PATH+ fi+- $CABAL update+- |+ $CABAL install happy alex+ export PATH=$HOME/.cabal/bin:$PATH+install:+- $CABAL install --dependencies-only --enable-tests+- $CABAL configure -flib-Werror --enable-tests $MODE+script:+- ghc --numeric-version+- $CABAL check+- $CABAL build+- $CABAL test --show-details=always+deploy:+ provider: hackage+ username: AlexanderThiemann+ skip_cleanup: true+ on:+ condition: "$GHCVER = {{tc_opts.to_ghcRelease}}"+ tags: true
+ templates/travis-stack.mustache view
@@ -0,0 +1,46 @@+# NB: don't set `language: haskell` here++sudo: false++matrix:+ include:+ {{#tc_project.pi_ghcVersions}}+ - env: GHCVER={{.}} STACK_YAML=stack.yaml+ addons:+ apt:+ sources:+ - hvr-ghc+ packages:+ - ghc-{{.}}+ {{/tc_project.pi_ghcVersions}}++before_install:+ # ghc+ - export PATH=/opt/ghc/$GHCVER/bin:$PATH+ # stack+ - mkdir -p ~/.local/bin+ - export PATH=~/.local/bin:$PATH+ - travis_retry curl -L https://github.com/commercialhaskell/stack/releases/download/v0.1.2.0/stack-0.1.2.0-x86_64-linux.gz | gunzip > ~/.local/bin/stack+ - chmod a+x ~/.local/bin/stack+ # versions+ - stack +RTS -N1 -RTS --version+ - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"++install:+ - ./travis_long stack +RTS -N1 -RTS --no-terminal --skip-ghc-check setup+ - ./travis_long stack +RTS -N1 -RTS --no-terminal --skip-ghc-check test --only-snapshot++script:+ - stack +RTS -N2 -RTS --no-terminal --skip-ghc-check test++cache:+ directories:+ - $HOME/.stack++deploy:+ provider: hackage+ username: AlexanderThiemann+ skip_cleanup: true+ on:+ condition: "$GHCVER = {{tc_opts.to_ghcRelease}}"+ tags: true