hadolint 1.6.0 → 1.6.1
raw patch · 3 files changed
+94/−13 lines, 3 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Hadolint.Rules: allFromImages :: Dockerfile -> [(Linenumber, BaseImage)]
+ Hadolint.Rules: allImageNames :: Dockerfile -> [(Linenumber, String)]
+ Hadolint.Rules: fromAlias :: BaseImage -> Maybe ImageAlias
+ Hadolint.Rules: fromName :: BaseImage -> String
- Hadolint.Rules: aptGetCleanup :: Rule
+ Hadolint.Rules: aptGetCleanup :: Dockerfile -> [RuleCheck]
Files
- hadolint.cabal +2/−2
- src/Hadolint/Rules.hs +41/−7
- test/Spec.hs +51/−4
hadolint.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 8953f4990fda4e78c53418a6f7426bc5f60f367bf771ed9e7bf015eac0868247+-- hash: dad086f0af35e0c451cefe4a1513876be3f752b5251b47db3267dc37fc59edd6 name: hadolint-version: 1.6.0+version: 1.6.1 synopsis: Dockerfile Linter JavaScript API description: A smarter Dockerfile linter that helps you build best practice Docker images. category: Development
src/Hadolint/Rules.hs view
@@ -169,14 +169,20 @@ bashCommands :: [String] -> [[String]] bashCommands = splitOneOf [";", "|", "&&"] +allFromImages :: Dockerfile -> [(Linenumber, BaseImage)]+allFromImages dockerfile = [(l, f) | (l, From f) <- instr]+ where+ instr = fmap (lineNumber &&& instruction) dockerfile+ allAliasedImages :: Dockerfile -> [(Linenumber, ImageAlias)] allAliasedImages dockerfile =- [(l, a) | (l, From (UntaggedImage _ (Just a))) <- instr] ++- [(l, a) | (l, From (TaggedImage _ _ (Just a))) <- instr] ++- [(l, a) | (l, From (DigestedImage _ _ (Just a))) <- instr]+ [(l, alias) | (l, Just alias) <- map extractAlias (allFromImages dockerfile)] where- instr = fmap (lineNumber &&& instruction) dockerfile+ extractAlias (l, f) = (l, fromAlias f) +allImageNames :: Dockerfile -> [(Linenumber, String)]+allImageNames dockerfile = [(l, fromName baseImage) | (l, baseImage) <- allFromImages dockerfile]+ -- | Returns a list of all image aliases in FROM instructions that -- are defined before the given line number. previouslyDefinedAliases :: Linenumber -> Dockerfile -> [String]@@ -194,6 +200,16 @@ From (DigestedImage _ _ (Just (ImageAlias alias))) -> predicate alias _ -> True +fromName :: BaseImage -> String+fromName (UntaggedImage Image {imageName} _) = imageName+fromName (TaggedImage Image {imageName} _ _) = imageName+fromName (DigestedImage Image {imageName} _ _) = imageName++fromAlias :: BaseImage -> Maybe ImageAlias+fromAlias (UntaggedImage _ alias) = alias+fromAlias (TaggedImage _ _ alias) = alias+fromAlias (DigestedImage _ _ alias) = alias+ absoluteWorkdir = instructionRule code severity message check where code = "DL3000"@@ -335,15 +351,33 @@ noOption arg = arg `notElem` options && not ("--" `isPrefixOf` arg) options = ["apt-get", "install", "-d", "-f", "-m", "-q", "-y", "-qq"] -aptGetCleanup = instructionRule code severity message check+aptGetCleanup dockerfile = instructionRuleState code severity message check Nothing dockerfile where code = "DL3009" severity = InfoC message = "Delete the apt-get lists after installing something"- check (Run (Arguments args)) = not (hasUpdate args) || hasCleanup args- check _ = True+ 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.+ -- We only care for users to delete the lists folder if the FROM clase we're is is the last one+ -- or if it is used as the base image for another FROM clause.+ check _ line f@(From _) = withState (Just (line, f)) True -- Remember the last FROM instruction found+ check st@(Just (line, From baseimage)) _ (Run (Arguments args))+ | not (hasUpdate args) || not (imageIsUsed line baseimage) = withState st True+ | otherwise = withState st (hasCleanup args)+ check st _ _ = withState st True hasCleanup cmd = ["rm", "-rf", "/var/lib/apt/lists/*"] `isInfixOf` cmd hasUpdate cmd = ["apt-get", "update"] `isInfixOf` cmd+ imageIsUsed line baseimage = isLastImage line baseimage || imageIsUsedLater line baseimage+ isLastImage line baseimage =+ case reverse (allFromImages dockerfile) of+ lst:_ -> (line, baseimage) == lst+ _ -> True+ imageIsUsedLater line baseimage =+ case fromAlias baseimage of+ Nothing -> True+ Just (ImageAlias alias) -> alias `elem` [i | (l, i) <- allImageNames dockerfile, l > line] dropOptionsWithArg :: [String] -> [String] -> [String] dropOptionsWithArg os [] = []
test/Spec.hs view
@@ -65,11 +65,58 @@ it "apt-get version pinning" $ ruleCatches aptGetVersionPinned "RUN apt-get update && apt-get install python" it "apt-get no cleanup" $- ruleCatches aptGetCleanup "RUN apt-get update && apt-get install python"+ let dockerfile =+ [ "FROM scratch"+ , "RUN apt-get update && apt-get install python"+ ]+ in ruleCatches aptGetCleanup $ unlines dockerfile+ it "apt-get cleanup in stage image" $+ let dockerfile =+ [ "FROM ubuntu as foo"+ , "RUN apt-get update && apt-get install python"+ , "FROM scratch"+ , "RUN echo hey!"+ ]+ in ruleCatchesNot aptGetCleanup $ unlines dockerfile+ it "apt-get no cleanup in last stage" $+ let dockerfile =+ [ "FROM ubuntu as foo"+ , "RUN hey!"+ , "FROM scratch"+ , "RUN apt-get update && apt-get install python"+ ]+ in ruleCatches aptGetCleanup $ unlines dockerfile+ it "apt-get no cleanup in intermediate stage" $+ let dockerfile =+ [ "FROM ubuntu as foo"+ , "RUN apt-get update && apt-get install python"+ , "FROM foo"+ , "RUN hey!"+ ]+ in ruleCatches aptGetCleanup $ unlines dockerfile+ it "now warn apt-get cleanup in intermediate stage that cleans lists" $+ let dockerfile =+ [ "FROM ubuntu as foo"+ , "RUN apt-get update && apt-get install python && rm -rf /var/lib/apt/lists/*"+ , "FROM foo"+ , "RUN hey!"+ ]+ in ruleCatchesNot aptGetCleanup $ unlines dockerfile+ it "no warn apt-get cleanup in intermediate stage when stage not used later" $+ let dockerfile =+ [ "FROM ubuntu as foo"+ , "RUN apt-get update && apt-get install python"+ , "FROM scratch"+ , "RUN hey!"+ ]+ in ruleCatchesNot aptGetCleanup $ unlines dockerfile it "apt-get cleanup" $- ruleCatchesNot- aptGetCleanup- "RUN apt-get update && apt-get install python && rm -rf /var/lib/apt/lists/*"+ let dockerfile =+ [ "FROM scratch"+ , "RUN apt-get update && apt-get install python && rm -rf /var/lib/apt/lists/*"+ ]+ in ruleCatchesNot aptGetCleanup $ unlines dockerfile+ it "apt-get pinned chained" $ let dockerfile = [ "RUN apt-get update \\"