module Hadolint.Rule.DL3006 (rule) where

import qualified Data.Set as Set
import Data.Text (Text)
import Hadolint.Rule
import Language.Docker.Syntax

rule :: Rule args
rule :: Rule args
rule = (Linenumber
 -> State (Set Text) -> Instruction args -> State (Set Text))
-> State (Set Text) -> Rule args
forall a args.
(Linenumber -> State a -> Instruction args -> State a)
-> State a -> Rule args
customRule Linenumber
-> State (Set Text) -> Instruction args -> State (Set Text)
forall args.
Linenumber
-> State (Set Text) -> Instruction args -> State (Set Text)
check (Set Text -> State (Set Text)
forall a. a -> State a
emptyState Set Text
forall a. Set a
Set.empty)
  where
    code :: RuleCode
code = RuleCode
"DL3006"
    severity :: DLSeverity
severity = DLSeverity
DLWarningC
    message :: Text
message = Text
"Always tag the version of an image explicitly"

    check :: Linenumber
-> State (Set Text) -> Instruction args -> State (Set Text)
check Linenumber
line State (Set Text)
st (From BaseImage
from) =
      let newState :: State (Set Text)
newState = State (Set Text)
st State (Set Text)
-> (State (Set Text) -> State (Set Text)) -> State (Set Text)
forall a b. a -> (a -> b) -> b
|> (Set Text -> Set Text) -> State (Set Text) -> State (Set Text)
forall a. (a -> a) -> State a -> State a
modify (BaseImage -> Set Text -> Set Text
insertFromAlias BaseImage
from)
       in case BaseImage
from of
            BaseImage {$sel:image:BaseImage :: BaseImage -> Image
image = (Image Maybe Registry
_ Text
"scratch")} -> State (Set Text)
newState
            BaseImage {$sel:digest:BaseImage :: BaseImage -> Maybe Digest
digest = Just Digest
_} -> State (Set Text)
newState
            BaseImage {$sel:image:BaseImage :: BaseImage -> Image
image = (Image Maybe Registry
_ Text
i), $sel:tag:BaseImage :: BaseImage -> Maybe Tag
tag = Maybe Tag
Nothing} ->
              -- When the image being used is a previously defined FROM alias,
              -- then we can safely ignore that the image is not tagged. Otherwise
              -- we marked it as a failure
              if Text -> Set Text -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member Text
i (State (Set Text) -> Set Text
forall a. State a -> a
state State (Set Text)
st)
                then State (Set Text)
newState
                else State (Set Text)
newState State (Set Text)
-> (State (Set Text) -> State (Set Text)) -> State (Set Text)
forall a b. a -> (a -> b) -> b
|> CheckFailure -> State (Set Text) -> State (Set Text)
forall a. CheckFailure -> State a -> State a
addFail (CheckFailure :: RuleCode -> DLSeverity -> Text -> Linenumber -> CheckFailure
CheckFailure {Linenumber
Text
RuleCode
DLSeverity
line :: Linenumber
message :: Text
severity :: DLSeverity
code :: RuleCode
line :: Linenumber
message :: Text
severity :: DLSeverity
code :: RuleCode
..})
            BaseImage
_ -> State (Set Text)
newState
    check Linenumber
_ State (Set Text)
st Instruction args
_ = State (Set Text)
st
{-# INLINEABLE rule #-}

insertFromAlias :: BaseImage -> Set.Set Text -> Set.Set Text
insertFromAlias :: BaseImage -> Set Text -> Set Text
insertFromAlias BaseImage {$sel:alias:BaseImage :: BaseImage -> Maybe ImageAlias
alias = Just ImageAlias
a} Set Text
st = Set Text
st Set Text -> (Set Text -> Set Text) -> Set Text
forall a b. a -> (a -> b) -> b
|> Text -> Set Text -> Set Text
forall a. Ord a => a -> Set a -> Set a
Set.insert (ImageAlias -> Text
unImageAlias ImageAlias
a)
insertFromAlias BaseImage
_ Set Text
st = Set Text
st