packages feed

travis-meta-yaml (empty) → 0.0.1.0

raw patch · 10 files changed

+425/−0 lines, 10 filesdep +aesondep +basedep +bytestringsetup-changed

Dependencies added: aeson, base, bytestring, extra, file-embed, lens, lens-aeson, optparse-applicative, regex-applicative, tasty, tasty-quickcheck, text, travis-meta-yaml, yaml

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2015, Oleg Grenrus++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 Oleg Grenrus 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,64 @@+# travis-meta-yaml++[![Build Status](https://travis-ci.org/phadej/travis-meta-yaml.svg?branch=master)](https://travis-ci.org/phadej/travis-meta-yaml)+[![Hackage](https://img.shields.io/hackage/v/travis-meta-yaml.svg)](http://hackage.haskell.org/package/travis-meta-yaml)++## Motivation++Turn++```yaml+env:+  - CABALVER=1.18 GHCVER=7.8.4+  - CABALVER=1.22 GHCVER=7.10.1+  - CABALVER=1.22 GHCVER=head++addons:+  apt:+    sources:+      - hvr-ghc+    packages:+      - cabal-install-$CABALVER+      - ghc-$GHCVER++matrix:+  allow_failures:+    - env: CABALVER=1.22 GHCVER=head+```++into++```yaml+matrix:+  include:+  - env: CABALVER=1.18 GHCVER=7.8.4+    addons:+      apt:+        sources:+        - hvr-ghc+        packages:+        - cabal-install-1.18+        - ghc-7.8.4+  - env: CABALVER=1.22 GHCVER=7.10.1+    addons:+      apt:+        sources:+        - hvr-ghc+        packages:+        - cabal-install-1.22+        - ghc-7.10.1+  - env: CABALVER=1.22 GHCVER=head+    addons:+      apt:+        sources:+        - hvr-ghc+        packages:+        - cabal-install-1.22+        - ghc-head+  allow_failures:+  - env: CABALVER=1.22 GHCVER=head+```++## Features++Currently only expanding of `addons.apt`. Any feature requests are welcome.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ cli/Main.hs view
@@ -0,0 +1,30 @@+module Main (main) where++import Travis.Meta+import Options.Applicative++data Opts = Opts+  { _source :: FilePath+  , _target :: FilePath+  }+  deriving (Eq, Show)++sample :: Parser Opts+sample = Opts+  <$> strArgument+      ( metavar "SOURCE"+     <> value ".travis.meta.yml"+     <> showDefault+     <> help "Source, travis meta file" )+  <*> strArgument+      ( metavar "TARGET"+     <> value ".travis.yml"+     <> showDefault+     <> help "Target, travis yaml" )++main :: IO ()+main = execParser opts >>= \(Opts source target) -> preprocessIO source target+  where+    opts = info (helper <*> sample)+      ( fullDesc+     <> header "travis-meta-yaml - .travis.yml preprocessor" )
+ fixtures/matrix-include.yml view
@@ -0,0 +1,4 @@+matrix:+  include:+    - env: FOO=foo+    - env: FOO=bar
+ fixtures/without-matrix-processed.yml view
@@ -0,0 +1,39 @@+script:+- cabal configure --enable-tests+- cabal test -j2+matrix:+  include:+  - env: CABALVER=1.18 GHCVER=7.8.4+    addons:+      apt:+        sources:+        - hvr-ghc+        packages:+        - cabal-1.18+        - ghc-7.8.4+  - env: CABALVER=1.22 GHCVER=7.10.1+    addons:+      apt:+        sources:+        - hvr-ghc+        packages:+        - cabal-1.22+        - ghc-7.10.1+  - env: CABALVER=1.22 GHCVER=head+    addons:+      apt:+        sources:+        - hvr-ghc+        packages:+        - cabal-1.22+        - ghc-head+install:+- cabal install -j2 --only-dependencies --enable-tests+before_install:+- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH+- stack +RTS -N1 -RTS --version+- echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo+  '?')]"+- cabal --version+- cabal install -j2 --only-dependencies --enable-tests+sudo: false
+ fixtures/without-matrix.yml view
@@ -0,0 +1,30 @@+sudo: false++env:+  - CABALVER=1.18 GHCVER=7.8.4+  - CABALVER=1.22 GHCVER=7.10.1+  - CABALVER=1.22 GHCVER=head++addons:+  apt:+    sources:+      - hvr-ghc+    packages:+      - cabal-$CABALVER+      - ghc-$GHCVER++before_install:+  # ghc+  - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH+  # versions+  - stack +RTS -N1 -RTS --version+  - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"+  - cabal --version+  - cabal install -j2 --only-dependencies --enable-tests++install:+  - cabal install -j2 --only-dependencies --enable-tests++script:+  - cabal configure --enable-tests+  - cabal test -j2
+ src/Travis/Meta.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+module Travis.Meta (+  -- * High level+    preprocessIO+  , preprocess+  , preprocessYaml+  -- * Internal+  , Env+  , parseEnv+  , interpolateEnv+  ) where++import Control.Lens+import Control.Monad hiding (sequence)+import Data.Aeson.Types+import Data.Aeson.Lens+import Data.ByteString as BS+import Data.Char+import Data.Maybe+import Data.Monoid+import Data.Text as T+import Data.Traversable+import Data.Yaml+import Prelude hiding (sequence)+import Text.Regex.Applicative++type Env = [(Text, Text)]++-- | Parse environment string.+--+-- > >>> parseEnv "CABALVER=1.18 GHCVER=7.8.4"+-- > Right [("CABALVER","1.18"),("GHCVER","7.8.4")]+parseEnv :: Text -> Either String Env+parseEnv = traverse (f . T.splitOn "=") . T.words+  where f [k, n] = Right (k, n)+        f _      = Left "Cannot parse"++-- > match (interpolationRe $ flip lookup [("foo", "bar")]) "$foo"+-- Just (Just "bar")+interpolationRe :: (String -> Maybe String) -> RE Char (Maybe String)+interpolationRe l = comb <$> many (interpolationChar l)+  where comb :: [Maybe [a]] -> Maybe [a]+        comb = fmap Prelude.concat . sequence++interpolationChar :: (String -> Maybe String) -> RE Char (Maybe String)+interpolationChar l = var <|> other+  where var = l <$ sym '$' <*> many (psym isAlpha)+        other = (\x -> Just [x]) <$> anySym++-- | Interpolate env. Substitute all @$VAR@ occurrences with values from 'Env'.+-- If variable is not in the environment, return 'Nothing'.+--+-- > >>> interpolateEnv [("FOO", "foo")] "res-$FOO-bar"+-- > Just "res-foo-bar"+--+-- > >>> interpolateEnv [("FOO","foo")] "yes-$FOOBAR-$FOO"+-- > Nothing+interpolateEnv :: Env -> Text -> Either String Text+interpolateEnv env = hoist . fmap T.pack . join . match (interpolationRe l) . T.unpack+  where l = fmap T.unpack . flip lookup env . T.pack++hoist :: Maybe a -> Either String a+hoist Nothing = Left "error in interpolation"+hoist (Just a) = Right a++preprocessYaml :: Value -> Either String Value+preprocessYaml v = do+  assertNoMatrixInclude v+  matrixInclude <- buildMatrixInclude v+  let v' = v & _Object . at "env" .~ Nothing+             & _Object . at "addons" .~ Nothing+             & _Object . at "matrix" ?~ (fromMaybe (Object mempty) (v ^? key "matrix"))+             & key "matrix" . _Object . at "include" ?~ matrixInclude+  return v'++buildMatrixInclude :: Value -> Either String Value+buildMatrixInclude v = toJSON <$> mk `traverse` envs+  where addons  = v ^? key "addons"+        envs    = v ^.. key "env" . values . _String+        mk env  = do env' <- parseEnv env+                     addons' <- traverseOf (deep _String) (interpolateEnv env') `traverse` addons+                     case addons' of+                       Just addons'' -> return $ object [ "env" Data.Yaml..= env, "addons" Data.Yaml..= addons'' ]+                       Nothing       -> return $ object [ "env" Data.Yaml..= env ]+                     ++assertNoMatrixInclude :: Value -> Either String ()+assertNoMatrixInclude v =+  case v ^? key "matrix" . key "include" of+    Nothing -> Right ()+    Just v' -> Left $ "matrix.include specified: " ++ show v'++preprocess :: ByteString -> Either String ByteString+preprocess = fmap encode . preprocessYaml <=< decodeEither++preprocessIO :: FilePath -> FilePath -> IO ()+preprocessIO source target = do+  contents <- BS.readFile source+  case preprocess contents of+    Left err -> error err+    Right bs -> BS.writeFile target bs++-- Right v <- decodeEither <$> BS.readFile ".travis.meta.yml"  :: IO (Either String Value)+-- BS.putStr $ encode $ preprocessYaml v
+ tests/Tests.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE RankNTypes #-}+module Main (main) where++import Data.Either.Extra+import Data.FileEmbed+import Data.Yaml+import Test.Tasty+import Test.Tasty.QuickCheck++import Travis.Meta++main :: IO ()+main = Test.Tasty.defaultMain tests++tests :: TestTree+tests = testGroup "Tests"+  [ selfTest+  , withoutMatrix+  , errorCases+  ]++selfTest :: TestTree+selfTest = testProperty "Self test" $ once $ actual === processed+  where actual     = decodeEither $(embedFile ".travis.yml")+        processed  = preprocessYaml =<< decodeEither $(embedFile ".travis.meta.yml")++withoutMatrix :: TestTree+withoutMatrix = testProperty "Self test without matrix" $ once $ actual === processed+  where actual     = decodeEither $(embedFile "fixtures/without-matrix-processed.yml")+        processed  = preprocessYaml =<< decodeEither $(embedFile "fixtures/without-matrix.yml")++errorCases :: TestTree+errorCases = testGroup "Error cases"+  [ c "matrix.include specified" $(embedFile "fixtures/matrix-include.yml")+  ]+  where c name bs = testProperty name $ once $ isLeft $ preprocess bs
+ travis-meta-yaml.cabal view
@@ -0,0 +1,84 @@+-- This file has been generated from package.yaml by hpack version 0.5.2.+--+-- see: https://github.com/sol/hpack++name:           travis-meta-yaml+version:        0.0.1.0+synopsis:       .travis.yml preprocessor+description:    .travis.yml preprocessor+category:       Development+homepage:       https://github.com/phadej/travis-meta-yaml#readme+bug-reports:    https://github.com/phadej/travis-meta-yaml/issues+author:         Oleg Grenrus <oleg.grenrus@iki.fi>+maintainer:     Oleg Grenrus <oleg.grenrus@iki.fi>+license:        BSD3+license-file:   LICENSE+build-type:     Simple+cabal-version:  >= 1.10++extra-source-files:+    fixtures/matrix-include.yml+    fixtures/without-matrix-processed.yml+    fixtures/without-matrix.yml+    README.md++source-repository head+  type: git+  location: https://github.com/phadej/travis-meta-yaml++library+  hs-source-dirs:+      src+  ghc-options: -Wall+  build-depends:+      base >=4.7 && <4.9+    , aeson+    , bytestring+    , lens-aeson+    , lens+    , text+    , regex-applicative+    , yaml+  exposed-modules:+      Travis.Meta+  default-language: Haskell2010++executable travis-meta-yaml+  main-is: Main.hs+  hs-source-dirs:+      cli+  ghc-options: -Wall+  build-depends:+      base >=4.7 && <4.9+    , aeson+    , bytestring+    , lens-aeson+    , lens+    , text+    , regex-applicative+    , yaml+    , travis-meta-yaml+    , optparse-applicative+  default-language: Haskell2010++test-suite tests+  type: exitcode-stdio-1.0+  main-is: Tests.hs+  hs-source-dirs:+      tests+  ghc-options: -Wall+  build-depends:+      base >=4.7 && <4.9+    , aeson+    , bytestring+    , lens-aeson+    , lens+    , text+    , regex-applicative+    , yaml+    , extra+    , file-embed+    , travis-meta-yaml+    , tasty+    , tasty-quickcheck+  default-language: Haskell2010