hadolint-2.8.0: src/Hadolint/Rule/DL3059.hs
module Hadolint.Rule.DL3059 (rule) where
import Hadolint.Rule
import qualified Hadolint.Shell as Shell
import Language.Docker.Syntax
data Acc
= Acc { flags :: RunFlags, count :: Int }
| Empty
deriving (Eq)
-- | This Rule catches multiple consecutive `RUN` instructions.
-- It ignores the case where multiple commands are chained together (e.g. with
-- `&&`) because in that case the programmer most likely has deliberately
-- chosen to use multiuple `RUN` instructions. Cases where --mount=xxx flags
-- differ are excluded as well.
rule :: Rule Shell.ParsedShell
rule = customRule check (emptyState Empty)
where
code = "DL3059"
severity = DLInfoC
message = "Multiple consecutive `RUN` instructions. Consider consolidation."
check line st (Run (RunArgs ar fl))
| state st == Empty =
st |> modify (remember fl (foldArguments countCommands ar))
| flags (state st) /= fl =
st |> modify (remember fl (foldArguments countCommands ar))
| foldArguments countCommands ar > 2 || count (state st) > 2 =
st |> modify (remember fl (foldArguments countCommands ar))
| otherwise = st |> addFail CheckFailure {..}
check _ st (Comment _) = st
check _ st _ = st |> modify reset
{-# INLINEABLE rule #-}
remember :: RunFlags -> Int -> Acc -> Acc
remember fl cn _ = Acc { flags = fl, count = cn }
reset :: Acc -> Acc
reset _ = Empty
countCommands :: Shell.ParsedShell -> Int
countCommands script = length $ Shell.presentCommands script