language-dockerfile 0.3.5.0 → 0.3.6.0
raw patch · 4 files changed
+184/−14 lines, 4 filesdep +aesondep +textdep +unordered-containersPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: aeson, text, unordered-containers, yaml
API changes (from Hackage documentation)
+ Language.Dockerfile.Predef: addGlob :: (MonadIO m, MonadFree EInstruction m) => String -> Destination -> m ()
+ Language.Dockerfile.Predef: appendLnIfMissing :: FilePath -> Text -> IO ()
+ Language.Dockerfile.Predef: copyGlob :: (MonadIO m, MonadFree EInstruction m) => String -> Destination -> m ()
+ Language.Dockerfile.Predef: dockerIgnore :: Text -> IO ()
+ Language.Dockerfile.Predef: nodejs :: (Monad m, MonadIO m, MonadFree EInstruction m) => m ()
+ Language.Dockerfile.Predef: nodejs' :: (Monad m, MonadIO m, MonadFree EInstruction m) => String -> m () -> m ()
+ Language.Dockerfile.Predef: stackBuild :: (Monad m, MonadIO m, MonadFree EInstruction m) => m ()
+ Language.Dockerfile.Predef: stackBuild' :: (Monad m, MonadIO m, MonadFree EInstruction m) => String -> m () -> m ()
- Language.Dockerfile: add :: forall m_asPi. MonadFree EInstruction m_asPi => Source -> Destination -> m_asPi ()
+ Language.Dockerfile: add :: forall m_atJ6. MonadFree EInstruction m_atJ6 => Source -> Destination -> m_atJ6 ()
- Language.Dockerfile: arg :: forall m_asPX. MonadFree EInstruction m_asPX => String -> m_asPX ()
+ Language.Dockerfile: arg :: forall m_atJL. MonadFree EInstruction m_atJL => String -> m_atJL ()
- Language.Dockerfile: cmdArgs :: forall m_asPC. MonadFree EInstruction m_asPC => Arguments -> m_asPC ()
+ Language.Dockerfile: cmdArgs :: forall m_atJq. MonadFree EInstruction m_atJq => Arguments -> m_atJq ()
- Language.Dockerfile: comment :: forall m_asQ0. MonadFree EInstruction m_asQ0 => String -> m_asQ0 ()
+ Language.Dockerfile: comment :: forall m_atJO. MonadFree EInstruction m_atJO => String -> m_atJO ()
- Language.Dockerfile: copy :: forall m_asPv. MonadFree EInstruction m_asPv => Source -> Destination -> m_asPv ()
+ Language.Dockerfile: copy :: forall m_atJj. MonadFree EInstruction m_atJj => Source -> Destination -> m_atJj ()
- Language.Dockerfile: embed :: forall m_asQ6. MonadFree EInstruction m_asQ6 => [InstructionPos] -> m_asQ6 ()
+ Language.Dockerfile: embed :: forall m_atJU. MonadFree EInstruction m_atJU => [InstructionPos] -> m_atJU ()
- Language.Dockerfile: entrypointArgs :: forall m_asPO. MonadFree EInstruction m_asPO => Arguments -> m_asPO ()
+ Language.Dockerfile: entrypointArgs :: forall m_atJC. MonadFree EInstruction m_atJC => Arguments -> m_atJC ()
- Language.Dockerfile: env :: forall m_asPU. MonadFree EInstruction m_asPU => Pairs -> m_asPU ()
+ Language.Dockerfile: env :: forall m_atJI. MonadFree EInstruction m_atJI => Pairs -> m_atJI ()
- Language.Dockerfile: expose :: forall m_asPI. MonadFree EInstruction m_asPI => Ports -> m_asPI ()
+ Language.Dockerfile: expose :: forall m_atJw. MonadFree EInstruction m_atJw => Ports -> m_atJw ()
- Language.Dockerfile: from :: forall m_asOB. MonadFree EInstruction m_asOB => EBaseImage -> m_asOB ()
+ Language.Dockerfile: from :: forall m_atIp. MonadFree EInstruction m_atIp => EBaseImage -> m_atIp ()
- Language.Dockerfile: label :: forall m_asPp. MonadFree EInstruction m_asPp => Pairs -> m_asPp ()
+ Language.Dockerfile: label :: forall m_atJd. MonadFree EInstruction m_atJd => Pairs -> m_atJd ()
- Language.Dockerfile: maintainer :: forall m_asPR. MonadFree EInstruction m_asPR => String -> m_asPR ()
+ Language.Dockerfile: maintainer :: forall m_atJF. MonadFree EInstruction m_atJF => String -> m_atJF ()
- Language.Dockerfile: onBuildRaw :: forall m_asQ3. MonadFree EInstruction m_asQ3 => Instruction -> m_asQ3 ()
+ Language.Dockerfile: onBuildRaw :: forall m_atJR. MonadFree EInstruction m_atJR => Instruction -> m_atJR ()
- Language.Dockerfile: runArgs :: forall m_asPz. MonadFree EInstruction m_asPz => Arguments -> m_asPz ()
+ Language.Dockerfile: runArgs :: forall m_atJn. MonadFree EInstruction m_atJn => Arguments -> m_atJn ()
- Language.Dockerfile: stopSignal :: forall m_asPs. MonadFree EInstruction m_asPs => String -> m_asPs ()
+ Language.Dockerfile: stopSignal :: forall m_atJg. MonadFree EInstruction m_atJg => String -> m_atJg ()
- Language.Dockerfile: user :: forall m_asPm. MonadFree EInstruction m_asPm => String -> m_asPm ()
+ Language.Dockerfile: user :: forall m_atJa. MonadFree EInstruction m_atJa => String -> m_atJa ()
- Language.Dockerfile: volume :: forall m_asPL. MonadFree EInstruction m_asPL => String -> m_asPL ()
+ Language.Dockerfile: volume :: forall m_atJz. MonadFree EInstruction m_atJz => String -> m_atJz ()
- Language.Dockerfile: workdir :: forall m_asPF. MonadFree EInstruction m_asPF => Directory -> m_asPF ()
+ Language.Dockerfile: workdir :: forall m_atJt. MonadFree EInstruction m_atJt => Directory -> m_atJt ()
- Language.Dockerfile.EDSL: add :: forall m_asPi. MonadFree EInstruction m_asPi => Source -> Destination -> m_asPi ()
+ Language.Dockerfile.EDSL: add :: forall m_atJ6. MonadFree EInstruction m_atJ6 => Source -> Destination -> m_atJ6 ()
- Language.Dockerfile.EDSL: arg :: forall m_asPX. MonadFree EInstruction m_asPX => String -> m_asPX ()
+ Language.Dockerfile.EDSL: arg :: forall m_atJL. MonadFree EInstruction m_atJL => String -> m_atJL ()
- Language.Dockerfile.EDSL: cmdArgs :: forall m_asPC. MonadFree EInstruction m_asPC => Arguments -> m_asPC ()
+ Language.Dockerfile.EDSL: cmdArgs :: forall m_atJq. MonadFree EInstruction m_atJq => Arguments -> m_atJq ()
- Language.Dockerfile.EDSL: comment :: forall m_asQ0. MonadFree EInstruction m_asQ0 => String -> m_asQ0 ()
+ Language.Dockerfile.EDSL: comment :: forall m_atJO. MonadFree EInstruction m_atJO => String -> m_atJO ()
- Language.Dockerfile.EDSL: copy :: forall m_asPv. MonadFree EInstruction m_asPv => Source -> Destination -> m_asPv ()
+ Language.Dockerfile.EDSL: copy :: forall m_atJj. MonadFree EInstruction m_atJj => Source -> Destination -> m_atJj ()
- Language.Dockerfile.EDSL: embed :: forall m_asQ6. MonadFree EInstruction m_asQ6 => [InstructionPos] -> m_asQ6 ()
+ Language.Dockerfile.EDSL: embed :: forall m_atJU. MonadFree EInstruction m_atJU => [InstructionPos] -> m_atJU ()
- Language.Dockerfile.EDSL: entrypointArgs :: forall m_asPO. MonadFree EInstruction m_asPO => Arguments -> m_asPO ()
+ Language.Dockerfile.EDSL: entrypointArgs :: forall m_atJC. MonadFree EInstruction m_atJC => Arguments -> m_atJC ()
- Language.Dockerfile.EDSL: env :: forall m_asPU. MonadFree EInstruction m_asPU => Pairs -> m_asPU ()
+ Language.Dockerfile.EDSL: env :: forall m_atJI. MonadFree EInstruction m_atJI => Pairs -> m_atJI ()
- Language.Dockerfile.EDSL: expose :: forall m_asPI. MonadFree EInstruction m_asPI => Ports -> m_asPI ()
+ Language.Dockerfile.EDSL: expose :: forall m_atJw. MonadFree EInstruction m_atJw => Ports -> m_atJw ()
- Language.Dockerfile.EDSL: from :: forall m_asOB. MonadFree EInstruction m_asOB => EBaseImage -> m_asOB ()
+ Language.Dockerfile.EDSL: from :: forall m_atIp. MonadFree EInstruction m_atIp => EBaseImage -> m_atIp ()
- Language.Dockerfile.EDSL: label :: forall m_asPp. MonadFree EInstruction m_asPp => Pairs -> m_asPp ()
+ Language.Dockerfile.EDSL: label :: forall m_atJd. MonadFree EInstruction m_atJd => Pairs -> m_atJd ()
- Language.Dockerfile.EDSL: maintainer :: forall m_asPR. MonadFree EInstruction m_asPR => String -> m_asPR ()
+ Language.Dockerfile.EDSL: maintainer :: forall m_atJF. MonadFree EInstruction m_atJF => String -> m_atJF ()
- Language.Dockerfile.EDSL: onBuildRaw :: forall m_asQ3. MonadFree EInstruction m_asQ3 => Instruction -> m_asQ3 ()
+ Language.Dockerfile.EDSL: onBuildRaw :: forall m_atJR. MonadFree EInstruction m_atJR => Instruction -> m_atJR ()
- Language.Dockerfile.EDSL: runArgs :: forall m_asPz. MonadFree EInstruction m_asPz => Arguments -> m_asPz ()
+ Language.Dockerfile.EDSL: runArgs :: forall m_atJn. MonadFree EInstruction m_atJn => Arguments -> m_atJn ()
- Language.Dockerfile.EDSL: stopSignal :: forall m_asPs. MonadFree EInstruction m_asPs => String -> m_asPs ()
+ Language.Dockerfile.EDSL: stopSignal :: forall m_atJg. MonadFree EInstruction m_atJg => String -> m_atJg ()
- Language.Dockerfile.EDSL: user :: forall m_asPm. MonadFree EInstruction m_asPm => String -> m_asPm ()
+ Language.Dockerfile.EDSL: user :: forall m_atJa. MonadFree EInstruction m_atJa => String -> m_atJa ()
- Language.Dockerfile.EDSL: volume :: forall m_asPL. MonadFree EInstruction m_asPL => String -> m_asPL ()
+ Language.Dockerfile.EDSL: volume :: forall m_atJz. MonadFree EInstruction m_atJz => String -> m_atJz ()
- Language.Dockerfile.EDSL: workdir :: forall m_asPF. MonadFree EInstruction m_asPF => Directory -> m_asPF ()
+ Language.Dockerfile.EDSL: workdir :: forall m_atJt. MonadFree EInstruction m_atJt => Directory -> m_atJt ()
Files
- language-dockerfile.cabal +40/−3
- src/Language/Dockerfile/Lexer.hs +18/−6
- src/Language/Dockerfile/Predef.hs +115/−0
- test/Language/Dockerfile/ParserSpec.hs +11/−5
language-dockerfile.cabal view
@@ -1,9 +1,9 @@--- This file has been generated from package.yaml by hpack version 0.14.0.+-- This file has been generated from package.yaml by hpack version 0.17.0. -- -- see: https://github.com/sol/hpack name: language-dockerfile-version: 0.3.5.0+version: 0.3.6.0 synopsis: Dockerfile linter, parser, pretty-printer and embedded DSL description: Forked from @hadolint@. .@@ -61,9 +61,17 @@ , template-haskell , th-lift , th-lift-instances+ , text+ , yaml+ , aeson+ , Glob+ , unordered-containers+ , directory+ , filepath exposed-modules: Language.Dockerfile Language.Dockerfile.Parser+ Language.Dockerfile.Predef Language.Dockerfile.PrettyPrint Language.Dockerfile.Normalize Language.Dockerfile.Rules@@ -97,6 +105,13 @@ , template-haskell , th-lift , th-lift-instances+ , text+ , yaml+ , aeson+ , Glob+ , unordered-containers+ , directory+ , filepath , language-dockerfile buildable: False if flag(dockerfmt)@@ -122,6 +137,13 @@ , template-haskell , th-lift , th-lift-instances+ , text+ , yaml+ , aeson+ , Glob+ , unordered-containers+ , directory+ , filepath , language-dockerfile buildable: False if flag(hadolint)@@ -135,7 +157,7 @@ main-is: Test.hs hs-source-dirs: src- , test+ test build-depends: ShellCheck , base >=4.8 && <5@@ -149,6 +171,13 @@ , template-haskell , th-lift , th-lift-instances+ , text+ , yaml+ , aeson+ , Glob+ , unordered-containers+ , directory+ , filepath , HUnit >=1.2 , test-framework , test-framework-hunit@@ -163,6 +192,7 @@ Language.Dockerfile.Lexer Language.Dockerfile.Normalize Language.Dockerfile.Parser+ Language.Dockerfile.Predef Language.Dockerfile.PrettyPrint Language.Dockerfile.Rules Language.Dockerfile.Syntax@@ -194,6 +224,13 @@ , template-haskell , th-lift , th-lift-instances+ , text+ , yaml+ , aeson+ , Glob+ , unordered-containers+ , directory+ , filepath , hspec , QuickCheck , language-dockerfile
src/Language/Dockerfile/Lexer.hs view
@@ -7,12 +7,24 @@ lexer :: Token.TokenParser () lexer = Token.makeTokenParser style -- style where- names = ["FROM","ADD","RUN","WORKDIR","EXPOSE","VOLUME","ENTRYPOINT","MAINTAINER","ENV","LABEL","USER","STOPSIGNAL","CMD", "ONBUILD", "ARG"]- style = emptyDef {- -- Token.commentLine = "#",- -- ,- Token.reservedNames = names- }+ names =+ [ "FROM"+ , "ADD"+ , "RUN"+ , "WORKDIR"+ , "EXPOSE"+ , "VOLUME"+ , "ENTRYPOINT"+ , "MAINTAINER"+ , "ENV"+ , "LABEL"+ , "USER"+ , "STOPSIGNAL"+ , "CMD"+ , "ONBUILD"+ , "ARG"+ ]+ style = emptyDef {Token.caseSensitive = False, Token.reservedNames = names} reserved :: String -> Parser () reserved = Token.reserved lexer
+ src/Language/Dockerfile/Predef.hs view
@@ -0,0 +1,115 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+module Language.Dockerfile.Predef+ where++import Control.Monad+import Control.Monad.Free.Class+import Control.Monad.IO.Class+import Data.Aeson (Value (..))+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Monoid+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Text.IO as Text+import qualified Data.Yaml as Yaml+import System.Directory+import System.FilePath+import qualified System.FilePath.Glob as Glob++import Language.Dockerfile+import Language.Dockerfile.EDSL.Types++appendLnIfMissing :: FilePath -> Text -> IO ()+appendLnIfMissing fp cts = do+ e <- doesFileExist fp+ unless e (Text.writeFile fp "")+ txt <- Text.lines <$> Text.readFile fp+ unless (cts `elem` txt) $+ Text.writeFile fp (Text.unlines (txt <> [cts]))++dockerIgnore :: Text -> IO ()+dockerIgnore = appendLnIfMissing ".dockerignore"++addGlob+ :: (MonadIO m, MonadFree EInstruction m) =>+ String -> Destination -> m ()+addGlob pattern dest = do+ fs <- liftIO $ do+ fs <- Glob.glob pattern+ cwd <- getCurrentDirectory+ let fs' = map (makeRelative cwd . normalise) fs+ forM fs' $ \f -> do+ isdir <- doesDirectoryExist f+ return $ if isdir+ then (f <> "/", dest <> takeBaseName f)+ else (f, dest <> takeBaseName f)+ forM_ fs (uncurry add)++copyGlob+ :: (MonadIO m, MonadFree EInstruction m) =>+ String -> Destination -> m ()+copyGlob = addGlob++stackBuild+ :: (Monad m, MonadIO m,+ MonadFree EInstruction m) =>+ m ()+stackBuild = do+ sts <- liftIO getStackYamlResolver+ stackBuild' sts (return ())+ where+ getStackYamlResolver = do+ mhm <- Yaml.decodeFile "./stack.yaml" :: IO (Maybe Value)+ return $ fromMaybe "latest" $ do+ hm <- mhm+ o <- case hm of+ Object o -> return o+ _ -> Nothing+ rs <- HashMap.lookup "resolver" o+ toString rs+ where+ toString (String m) = Just (Text.unpack m)+ toString _ = Nothing++stackBuild'+ :: (Monad m, MonadIO m,+ MonadFree EInstruction m) =>+ String -> m () -> m ()+stackBuild' tag extra = do+ liftIO $ dockerIgnore ".stack-work"+ liftIO $ dockerIgnore ".cabal-sandbox"++ from ("fpco" `tagged` tag)+ extra+ add "./package.yaml" "/app/package.yaml"+ addGlob "./*.cabal" "/app/"+ add "./stack.yaml" "/app/stack.yaml"+ workdir "/app/"+ run "stack build --only-dependencies"+ add "." "/app/stack.yaml"+ run "stack build"++nodejs+ :: (Monad m, MonadIO m,+ MonadFree EInstruction m) =>+ m ()+nodejs = nodejs' "6" (return ())++nodejs'+ :: (Monad m, MonadIO m,+ MonadFree EInstruction m) =>+ String -> m () -> m ()+nodejs' tag extra = do+ liftIO $ dockerIgnore "node_modules"+ liftIO $ dockerIgnore "bower_components"++ from ("node" `tagged` tag)+ extra+ add "./package.json" "/app/package.json"+ workdir "/app/"+ run "npm install"+ add "." "/app/"+ cmd "npm start"
test/Language/Dockerfile/ParserSpec.hs view
@@ -7,8 +7,14 @@ import Text.Parsec spec :: Spec-spec =- describe "expose" $ do- it "should handle number ports" $ do- let content = "EXPOSE 8080"- parse expose "" content `shouldBe` Right (Expose (Ports [8080]))+spec = do+ describe "expose" $ do+ it "should handle number ports" $ do+ let content = "EXPOSE 8080"+ parse expose "" content `shouldBe` Right (Expose (Ports [8080]))+ describe "syntax" $ do+ it+ "should handle lowercase instructions (#7 - https://github.com/beijaflor-io/haskell-language-dockerfile/issues/7)" $ do+ let content = "from ubuntu"+ parse dockerfile "" content `shouldBe`+ Right [InstructionPos (From (UntaggedImage "ubuntu")) "" 1]