packages feed

hadolint 1.6.5 → 1.6.6

raw patch · 7 files changed

+45/−58 lines, 7 filesdep +containersdep −dlist

Dependencies added: containers

Dependencies removed: dlist

Files

hadolint.cabal view
@@ -1,11 +1,11 @@--- This file has been generated from package.yaml by hpack version 0.21.2.+-- This file has been generated from package.yaml by hpack version 0.28.2. -- -- see: https://github.com/sol/hpack ----- hash: b523045510203dbac76d6488afec9838250f551597ef35d8b888adcbdc39e619+-- hash: 913a53c45d2193a9fb13a8dfb47bf647d985298fc2522ce1e369ab2ed1d1a311  name:           hadolint-version:        1.6.5+version:        1.6.6 synopsis:       Dockerfile Linter JavaScript API description:    A smarter Dockerfile linter that helps you build best practice Docker images. category:       Development@@ -17,7 +17,6 @@ license-file:   LICENSE build-type:     Simple cabal-version:  >= 1.10- extra-source-files:     README.md @@ -34,7 +33,7 @@     , aeson     , base >=4.8 && <5     , bytestring-    , dlist+    , containers     , language-docker >=5.0.0 && <6     , parsec >=3.1     , split >=0.2
src/Hadolint/Formatter/Checkstyle.hs view
@@ -9,7 +9,7 @@ import qualified Data.ByteString.Builder as Builder import qualified Data.ByteString.Lazy.Char8 as B import Data.Char-import Data.DList (toList)+import Data.Foldable (toList) import Data.List (groupBy) import Data.Monoid ((<>), mconcat) import Hadolint.Formatter.Format@@ -79,7 +79,7 @@         if isOk c             then [c]             else "&#" ++ show (ord c) ++ ";"-    isOk x = any ($x) [isAsciiUpper, isAsciiLower, isDigit, (`elem` [' ', '.', '/'])]+    isOk x = any (\check -> check x) [isAsciiUpper, isAsciiLower, isDigit, (`elem` [' ', '.', '/'])]  formatResult :: Result -> Builder.Builder formatResult (Result errors checks) =
src/Hadolint/Formatter/Codeclimate.hs view
@@ -9,8 +9,8 @@  import Data.Aeson hiding (Result) import qualified Data.ByteString.Lazy as B-import Data.DList (DList) import Data.Monoid ((<>))+import Data.Sequence (Seq) import GHC.Generics import Hadolint.Formatter.Format (Result(..), formatErrorReason) import Hadolint.Rules (Metadata(..), RuleCheck(..))@@ -59,7 +59,7 @@     Issue     { checkName = "DL1000"     , description = formatErrorReason err-    , location = LocPos (sourceName pos) Pos{..}+    , location = LocPos (sourceName pos) Pos {..}     , impact = severityText ErrorC     }   where@@ -67,7 +67,6 @@     line = sourceLine pos     column = sourceColumn pos - checkToIssue :: RuleCheck -> Issue checkToIssue RuleCheck {..} =     Issue@@ -85,7 +84,7 @@         InfoC -> "info"         StyleC -> "minor" -formatResult :: Result -> DList Issue+formatResult :: Result -> Seq Issue formatResult (Result errors checks) = allIssues   where     allIssues = errorMessages <> checkMessages
src/Hadolint/Formatter/Format.hs view
@@ -6,18 +6,18 @@     , toResult     ) where -import Data.DList (DList, fromList, singleton) import Data.List (sort) import Data.Monoid (Monoid) import Data.Semigroup+import Data.Sequence (Seq, fromList, singleton) import Hadolint.Rules import ShellCheck.Interface import Text.Parsec.Error        (ParseError, errorMessages, showErrorMessages)  data Result = Result-    { errors :: DList ParseError-    , checks :: DList RuleCheck+    { errors :: Seq ParseError+    , checks :: Seq RuleCheck     } deriving (Eq)  instance Semigroup Result where
src/Hadolint/Formatter/TTY.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE NamedFieldPuns #-}+ module Hadolint.Formatter.TTY     ( printResult     , formatError@@ -26,13 +27,10 @@         formatPos source line ++ code meta ++ " " ++ message meta  formatPos :: Filename -> Linenumber -> String-formatPos source line =-    if line >= 0-        then source ++ ":" ++ show line ++ " "-        else source ++ " "+formatPos source line = source ++ ":" ++ show line ++ " "  printResult :: Result -> IO ()-printResult Result{errors, checks} = printErrors >> printChecks+printResult Result {errors, checks} = printErrors >> printChecks   where     printErrors = mapM_ putStrLn (formatErrors errors)     printChecks = mapM_ putStrLn (formatChecks checks)
src/Hadolint/Rules.hs view
@@ -10,6 +10,7 @@ import Hadolint.Bash import Language.Docker.Syntax +import qualified Data.Set as Set import qualified ShellCheck.Interface import ShellCheck.Interface (Severity(..)) import qualified Text.Parsec as Parsec@@ -76,19 +77,8 @@     -> Rule instructionRuleState code severity message = mapInstructions (Metadata code severity message) -dockerfileRule ::-       String -- ^ The rule code name-    -> ShellCheck.Interface.Severity -- ^ The rule severity-    -> String -- ^ The error message associated with the rule-    -> ([Instruction] -> Bool) -- ^ The function that will check the rule-    -> Rule-dockerfileRule code severity message f = rule-  where-    rule dockerfile =-        [RuleCheck metadata (filename dockerfile) (-1) (f (map instruction dockerfile))]-    metadata = Metadata code severity message-    filename (inst:_) = sourcename inst-    filename [] = ""+withState :: a -> b -> (a, b)+withState st res = (st, res)  -- Enforce rules on a dockerfile and return failed checks analyze :: [Rule] -> Dockerfile -> [RuleCheck]@@ -225,54 +215,55 @@     check _ = True  hasNoMaintainer :: Rule-hasNoMaintainer = dockerfileRule code severity message check+hasNoMaintainer = instructionRule code severity message check   where     code = "DL4000"     severity = ErrorC     message = "MAINTAINER is deprecated"-    check dockerfile = not $ any isMaintainer dockerfile-    isMaintainer (Maintainer _) = True-    isMaintainer _ = False+    check (Maintainer _) = False+    check _ = True  -- Check if a command contains a program call in the Run instruction usingProgram :: String -> [String] -> Bool usingProgram prog args = or [True | cmd:_ <- bashCommands args, cmd == prog]  multipleCmds :: Rule-multipleCmds = dockerfileRule code severity message check+multipleCmds = instructionRuleState code severity message check Nothing   where     code = "DL4003"     severity = WarningC     message =         "Multiple `CMD` instructions found. If you list more than one `CMD` then only the last \         \`CMD` will take effect"-    check dockerfile = 1 >= length (filter (True ==) $ map isCmd dockerfile)-    isCmd (Cmd _) = True-    isCmd _ = False+    check Nothing line (Cmd _) = withState (Just line) True -- Remember the first CMD found+    check (Just l) _ (Cmd _) = withState (Just l) False -- Fail the rule, CMD is duplicated+    check st _ _ = withState st True  multipleEntrypoints :: Rule-multipleEntrypoints = dockerfileRule code severity message check+multipleEntrypoints = instructionRuleState code severity message check Nothing   where     code = "DL4004"     severity = ErrorC     message =         "Multiple `ENTRYPOINT` instructions found. If you list more than one `ENTRYPOINT` then \         \only the last `ENTRYPOINT` will take effect"-    check dockerfile = 1 >= length (filter (True ==) $ map isEntrypoint dockerfile)-    isEntrypoint (Entrypoint _) = True-    isEntrypoint _ = False+    check Nothing line (Entrypoint _) = withState (Just line) True -- Remember the first ENTRYPOINT found+    check (Just l) _ (Entrypoint _) = withState (Just l) False -- Fail the rule, ENTRYPOINT is duplicated+    check st _ _ = withState st True  wgetOrCurl :: Rule-wgetOrCurl = dockerfileRule code severity message check+wgetOrCurl = instructionRuleState code severity message check Set.empty   where     code = "DL4001"     severity = WarningC     message = "Either use Wget or Curl but not both"-    check dockerfile = not $ anyCurl dockerfile && anyWget dockerfile-    anyCurl = any $ usingCmd "curl"-    anyWget = any $ usingCmd "wget"-    usingCmd cmd (Run (Arguments args)) = cmd `elem` args-    usingCmd _ _ = False+    check state _ (Run (Arguments args)) = detectDoubleUsage state args+    check state _ _ = withState state True+    detectDoubleUsage state args =+        let newArgs = extractCommands args+            newState = Set.union state newArgs+        in withState newState (Set.size newState < 2)+    extractCommands args = Set.fromList [w | w <- args, w == "curl" || w == "wget"]  invalidCmd :: Rule invalidCmd = instructionRule code severity message check@@ -375,7 +366,6 @@     code = "DL3009"     severity = InfoC     message = "Delete the apt-get lists after installing something"-    withState st res = (st, res)     -- | 'check' returns a tuple (state, check_result)     --   The state in this case is the FROM instruction where the current instruction we are     --   inspecting is nested in.@@ -653,7 +643,6 @@     code = "DL3023"     severity = ErrorC     message = "COPY --from should reference a previously defined FROM alias"-    withState st res = (st, res)     -- | 'check' returns a tuple (state, check_result)     --   The state in this case is the FROM instruction where the current instruction we are     --   inspecting is nested in.
test/Spec.hs view
@@ -453,19 +453,21 @@                   ruleCatchesNot copyFromAnother $ unlines dockerFile                   ruleCatchesNot copyEndingSlash $ unlines dockerFile -assertChecks :: Rule -> String -> ([RuleCheck] -> IO a) -> IO a-assertChecks rule s f =+assertChecks :: HasCallStack => Rule -> String -> ([RuleCheck] -> IO a) -> IO a+assertChecks rule s makeAssertions =     case parseString (s ++ "\n") of         Left err -> assertFailure $ show err-        Right dockerFile -> f $ analyze [rule] dockerFile+        Right dockerFile -> makeAssertions $ analyze [rule] dockerFile  -- Assert a failed check exists for rule-ruleCatches :: Rule -> String -> Assertion+ruleCatches :: HasCallStack => Rule -> String -> Assertion ruleCatches rule s = assertChecks rule s f   where-    f checks = assertEqual "No check for rule found" 1 $ length checks+    f checks = do+      assertEqual "No check for rule found" 1 $ length checks+      assertBool "Incorrect line number for result" $ null [c | c <- checks, linenumber c <= 0] -ruleCatchesNot :: Rule -> String -> Assertion+ruleCatchesNot :: HasCallStack => Rule -> String -> Assertion ruleCatchesNot rule s = assertChecks rule s f   where     f checks = assertEqual "Found check of rule" 0 $ length checks