packages feed

hadolint 1.8.0 → 1.9.0

raw patch · 5 files changed

+119/−12 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Hadolint.Formatter.Codeclimate: instance Data.Aeson.Types.Class.ToJSON Hadolint.Formatter.Codeclimate.Issue
- Hadolint.Formatter.Codeclimate: instance Data.Aeson.Types.Class.ToJSON Hadolint.Formatter.Codeclimate.Location
- Hadolint.Formatter.Codeclimate: instance Data.Aeson.Types.Class.ToJSON Hadolint.Formatter.Codeclimate.Pos
- Hadolint.Formatter.Format: instance Data.Semigroup.Semigroup (Hadolint.Formatter.Format.Result t e)
- Hadolint.Formatter.Json: instance (Text.Megaparsec.Error.ShowToken t, GHC.Classes.Ord t, Text.Megaparsec.Error.ShowErrorComponent e) => Data.Aeson.Types.Class.ToJSON (Hadolint.Formatter.Json.JsonFormat t e)
+ Hadolint.Bash: extractTokensWith :: (Token -> Maybe Token) -> ParsedBash -> [Token]
+ Hadolint.Bash: findPipes :: ParsedBash -> [Token]
+ Hadolint.Bash: hasPipes :: ParsedBash -> Bool
+ Hadolint.Formatter.Codeclimate: instance Data.Aeson.Types.ToJSON.ToJSON Hadolint.Formatter.Codeclimate.Issue
+ Hadolint.Formatter.Codeclimate: instance Data.Aeson.Types.ToJSON.ToJSON Hadolint.Formatter.Codeclimate.Location
+ Hadolint.Formatter.Codeclimate: instance Data.Aeson.Types.ToJSON.ToJSON Hadolint.Formatter.Codeclimate.Pos
+ Hadolint.Formatter.Format: instance GHC.Base.Semigroup (Hadolint.Formatter.Format.Result t e)
+ Hadolint.Formatter.Json: instance (Text.Megaparsec.Error.ShowToken t, GHC.Classes.Ord t, Text.Megaparsec.Error.ShowErrorComponent e) => Data.Aeson.Types.ToJSON.ToJSON (Hadolint.Formatter.Json.JsonFormat t e)
+ Hadolint.Rules: usePipefail :: Rule

Files

README.md view
@@ -153,12 +153,13 @@ | [DL3022](https://github.com/hadolint/hadolint/wiki/DL3022)   | `COPY --from` should reference a previously defined `FROM` alias                                                                                    | | [DL3023](https://github.com/hadolint/hadolint/wiki/DL3023)   | `COPY --from` cannot reference its own `FROM` alias                                                                                                 | | [DL3024](https://github.com/hadolint/hadolint/wiki/DL3024)   | `FROM` aliases (stage names) must be unique                                                                                                         |-| [DL3025](https://github.com/hadolint/hadolint/wiki/DL3025)   | Use argumens JSON notation for CMD and ENTRYPOINT arguments                                                                                         |+| [DL3025](https://github.com/hadolint/hadolint/wiki/DL3025)   | Use arguments JSON notation for CMD and ENTRYPOINT arguments                                                                                        | | [DL4000](https://github.com/hadolint/hadolint/wiki/DL4000)   | MAINTAINER is deprecated.                                                                                                                           | | [DL4001](https://github.com/hadolint/hadolint/wiki/DL4001)   | Either use Wget or Curl but not both.                                                                                                               | | [DL4003](https://github.com/hadolint/hadolint/wiki/DL4003)   | Multiple `CMD` instructions found.                                                                                                                  | | [DL4004](https://github.com/hadolint/hadolint/wiki/DL4004)   | Multiple `ENTRYPOINT` instructions found.                                                                                                           | | [DL4005](https://github.com/hadolint/hadolint/wiki/DL4005)   | Use `SHELL` to change the default shell.                                                                                                            |+| [DL4006](https://github.com/hadolint/hadolint/wiki/DL4006)   | Set the `SHELL` option -o pipefail before `RUN` with a pipe in it                                                                                   | | [SC1000](https://github.com/koalaman/shellcheck/wiki/SC1000) | `$` is not used specially and should therefore be escaped.                                                                                          | | [SC1001](https://github.com/koalaman/shellcheck/wiki/SC1001) | This `\c` will be a regular `'c'`  in this context.                                                                                                 | | [SC1007](https://github.com/koalaman/shellcheck/wiki/SC1007) | Remove space after `=` if trying to assign a value (or for empty string, use `var='' ...`).                                                         |
hadolint.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: ed40f7e723efb830715c051c8b06bf4693ace2a9f94c7a53e035fd1fc237febb+-- hash: 0723e0fb6351589066a83e427a444fd8297f43911d23ac2c3a053888a957f94b  name:           hadolint-version:        1.8.0+version:        1.9.0 synopsis:       Dockerfile Linter JavaScript API description:    A smarter Dockerfile linter that helps you build best practice Docker images. category:       Development
src/Hadolint/Bash.hs view
@@ -43,17 +43,31 @@               }     } -findCommands :: ParsedBash -> [Token]-findCommands (ParsedBash _ ast) =+extractTokensWith :: (Token -> Maybe Token) -> ParsedBash -> [Token]+extractTokensWith extractor (ParsedBash _ ast) =     case prRoot ast of         Nothing -> []         Just script -> nub . execWriter $ ShellCheck.AST.doAnalysis extract script   where     extract :: Token -> Writer [Token] ()-    extract t =-        case ShellCheck.ASTLib.getCommand t of-            Nothing -> return ()-            Just cmd -> tell [cmd]+    extract token =+      case extractor token of+        Nothing -> return ()+        Just t -> tell [t]++findPipes :: ParsedBash -> [Token]+findPipes = extractTokensWith pipesExtractor+  where+    pipesExtractor pipe@T_Pipe{} = Just pipe+    pipesExtractor _ = Nothing++hasPipes :: ParsedBash -> Bool+hasPipes = not . null . findPipes++findCommands :: ParsedBash -> [Token]+findCommands = extractTokensWith commandsExtractor+  where+    commandsExtractor = ShellCheck.ASTLib.getCommand  allCommands :: (Token -> Bool) -> ParsedBash -> Bool allCommands check script = all check (findCommands script)
src/Hadolint/Rules.hs view
@@ -175,6 +175,7 @@     , multipleEntrypoints     , useShell     , useJsonArgs+    , usePipefail     ]  commentMetadata :: ShellCheck.Interface.Comment -> Metadata@@ -709,7 +710,30 @@   where     code = "DL3025"     severity = WarningC-    message = "Use argumens JSON notation for CMD and ENTRYPOINT arguments"-    check (Cmd (ArgumentsText _ )) = False-    check (Entrypoint (ArgumentsText _ )) = False+    message = "Use arguments JSON notation for CMD and ENTRYPOINT arguments"+    check (Cmd (ArgumentsText _)) = False+    check (Entrypoint (ArgumentsText _)) = False     check _ = True++usePipefail :: Rule+usePipefail = instructionRuleState code severity message check False+  where+    code = "DL4006"+    severity = WarningC+    message = "Set the SHELL option -o pipefail before RUN with a pipe in it"+    check _ _ From {} = (False, True) -- Reset the state each time we find a new FROM+    check _ _ (Shell args) = (argumentsRule hasPipefailOption args, True)+    check False _ (Run args) = (False, argumentsRule notHasPipes args)+    check st _ _ = (st, True)+    notHasPipes script = not (Bash.hasPipes script)+    hasPipefailOption script =+        not $+        null+            [ True+            | cmd <- Bash.findCommands script+            , validShell <- ["/bin/bash", "/bin/zsh", "/bin/ash", "bash", "zsh", "ash"]+            , Bash.getCommandName cmd == Just validShell+            , Bash.hasFlag "o" cmd+            , arg <- Bash.getAllArgs cmd+            , arg == "pipefail"+            ]
test/Spec.hs view
@@ -757,6 +757,74 @@                         ]                 in ruleCatchesNot useJsonArgs $ Text.unlines dockerFile +        --+        describe "Detects missing pipefail option" $ do+            it "warn on missing pipefail" $+                let dockerFile =+                        [ "FROM scratch"+                        , "RUN wget -O - https://some.site | wc -l > /number"+                        ]+                in ruleCatches usePipefail $ Text.unlines dockerFile+            it "don't warn on commands with no pipes" $+                let dockerFile =+                        [ "FROM scratch as build"+                        , "RUN wget -O - https://some.site && wc -l file > /number"+                        ]+                in ruleCatchesNot usePipefail $ Text.unlines dockerFile+            it "don't warn on commands with pipes and the pipefail option" $+                let dockerFile =+                        [ "FROM scratch as build"+                        , "SHELL [\"/bin/bash\", \"-eo\", \"pipefail\", \"-c\"]"+                        , "RUN wget -O - https://some.site | wc -l file > /number"+                        ]+                in ruleCatchesNot usePipefail $ Text.unlines dockerFile+            it "don't warn on commands with pipes and the pipefail option 2" $+                let dockerFile =+                        [ "FROM scratch as build"+                        , "SHELL [\"/bin/bash\", \"-e\", \"-o\", \"pipefail\", \"-c\"]"+                        , "RUN wget -O - https://some.site | wc -l file > /number"+                        ]+                in ruleCatchesNot usePipefail $ Text.unlines dockerFile+            it "don't warn on commands with pipes and the pipefail option 3" $+                let dockerFile =+                        [ "FROM scratch as build"+                        , "SHELL [\"/bin/bash\", \"-o\", \"errexit\", \"-o\", \"pipefail\", \"-c\"]"+                        , "RUN wget -O - https://some.site | wc -l file > /number"+                        ]+                in ruleCatchesNot usePipefail $ Text.unlines dockerFile+            it "don't warn on commands with pipes and the pipefail zsh" $+                let dockerFile =+                        [ "FROM scratch as build"+                        , "SHELL [\"/bin/zsh\", \"-o\", \"pipefail\", \"-c\"]"+                        , "RUN wget -O - https://some.site | wc -l file > /number"+                        ]+                in ruleCatchesNot usePipefail $ Text.unlines dockerFile+            it "warns when using plain sh" $+                let dockerFile =+                        [ "FROM scratch as build"+                        , "SHELL [\"/bin/sh\", \"-o\", \"pipefail\", \"-c\"]"+                        , "RUN wget -O - https://some.site | wc -l file > /number"+                        ]+                in ruleCatches usePipefail $ Text.unlines dockerFile+            it "warn on missing pipefail in the next image" $+                let dockerFile =+                        [ "FROM scratch as build"+                        , "SHELL [\"/bin/bash\", \"-o\", \"pipefail\", \"-c\"]"+                        , "RUN wget -O - https://some.site | wc -l file > /number"+                        , "FROM scratch as build2"+                        , "RUN wget -O - https://some.site | wc -l file > /number"+                        ]+                in ruleCatches usePipefail $ Text.unlines dockerFile+            it "warn on missing pipefail if next SHELL is not using it" $+                let dockerFile =+                        [ "FROM scratch as build"+                        , "SHELL [\"/bin/bash\", \"-o\", \"pipefail\", \"-c\"]"+                        , "RUN wget -O - https://some.site | wc -l file > /number"+                        , "SHELL [\"/bin/sh\", \"-c\"]"+                        , "RUN wget -O - https://some.site | wc -l file > /number"+                        ]+                in ruleCatches usePipefail $ Text.unlines dockerFile+ assertChecks :: HasCallStack => Rule -> Text.Text -> ([RuleCheck] -> IO a) -> IO a assertChecks rule s makeAssertions =     case parseText (s <> "\n") of