diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -36,6 +36,10 @@
 $ docker run --rm -i ghcr.io/hadolint/hadolint < Dockerfile
 ```
 
+or if you are using Windows PowerShell:
+```powershell
+> cat .\Dockerfile | docker run --rm -i hadolint/hadolint
+```
 ## Install
 
 You can download prebuilt binaries for OSX, Windows and Linux from the latest
@@ -107,6 +111,21 @@
   - my-company.com:5000
 ```
 
+If you want to override the severity of specific rules, you can do that too:
+```yaml
+override:
+  error:
+    - DL3001
+    - DL3002
+  warning:
+    - DL3042
+    - DL3033
+  info:
+    - DL3032
+  style:
+    - DL3015
+```
+
 Configuration files can be used globally or per project. By default, `hadolint` will look for
 a configuration file in the current directory with the name `.hadolint.yaml`
 
@@ -165,6 +184,7 @@
 ```yaml
 label-schema:
   author: text
+  contact: email
   created: rfc3339
   version: semver
   documentation: url
@@ -181,6 +201,7 @@
 | url     | A URI as described in [RFC 3986][rfc3986]          |
 | hash    | Either a short or a long [Git hash][githash]       |
 | spdx    | An [SPDX license identifier][spdxid]               |
+| email   | An email address conforming to [RFC 5322][rfc5322] |
 
 By default, Hadolint ignores any label not specified in the label schema. To
 warn on such additional labels, turn on strict labels:
@@ -239,7 +260,7 @@
 | [DL3002](https://github.com/hadolint/hadolint/wiki/DL3002)   | Last user should not be root.                                                                                                                       |
 | [DL3003](https://github.com/hadolint/hadolint/wiki/DL3003)   | Use WORKDIR to switch to a directory.                                                                                                               |
 | [DL3004](https://github.com/hadolint/hadolint/wiki/DL3004)   | Do not use sudo as it leads to unpredictable behavior. Use a tool like gosu to enforce root.                                                        |
-| [DL3005](https://github.com/hadolint/hadolint/wiki/DL3005)   | Do not use apt-get upgrade or dist-upgrade.                                                                                                         |
+| [DL3005](https://github.com/hadolint/hadolint/wiki/DL3005)   | Do not use apt-get dist-upgrade.                                                                                                                    |
 | [DL3006](https://github.com/hadolint/hadolint/wiki/DL3006)   | Always tag the version of an image explicitly.                                                                                                      |
 | [DL3007](https://github.com/hadolint/hadolint/wiki/DL3007)   | Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag.                                         |
 | [DL3008](https://github.com/hadolint/hadolint/wiki/DL3008)   | Pin versions in apt-get install.                                                                                                                    |
@@ -293,6 +314,8 @@
 | [DL3056](https://github.com/hadolint/hadolint/wiki/DL3056)   | Label `<label>` does not conform to semantic versioning.                                                                                            |
 | [DL3057](https://github.com/hadolint/hadolint/wiki/DL3057)   | `HEALTHCHECK` instruction missing.                                                                                                                  |
 | [DL3058](https://github.com/hadolint/hadolint/wiki/DL3058)   | Label `<label>` is not a valid email format - must be conform to RFC5322.                                                                           |
+| [DL3059](https://github.com/hadolint/hadolint/wiki/DL3059)   | Multiple consecutive `RUN` instructions. Consider consolidation.                                                                                    |
+| [DL3060](https://github.com/hadolint/hadolint/wiki/DL3060)   | `yarn cache clean` missing after `yarn install` was run.                                                                                            |
 | [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.                                                                                                                  |
@@ -417,3 +440,4 @@
 [rfc3986]: https://www.ietf.org/rfc/rfc3986.txt
 [githash]: https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection
 [spdxid]: https://spdx.org/licenses/
+[rfc5322]: https://www.ietf.org/rfc/rfc5322.txt
diff --git a/hadolint.cabal b/hadolint.cabal
--- a/hadolint.cabal
+++ b/hadolint.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 3a6af1aecfc32d960fd1df8de865bb60b8682f8877a9b3bb848a3f59c50c063d
+-- hash: 391fff086908037463e385c3450cb46068242dcf3932fbfbb995f2bf9ee6a98c
 
 name:           hadolint
-version:        2.1.0
+version:        2.2.0
 synopsis:       Dockerfile Linter JavaScript API
 description:    A smarter Dockerfile linter that helps you build best practice Docker images.
 category:       Development
@@ -103,6 +103,8 @@
       Hadolint.Rule.DL3056
       Hadolint.Rule.DL3057
       Hadolint.Rule.DL3058
+      Hadolint.Rule.DL3059
+      Hadolint.Rule.DL3060
       Hadolint.Rule.DL4000
       Hadolint.Rule.DL4001
       Hadolint.Rule.DL4003
@@ -135,7 +137,7 @@
     , filepath
     , foldl
     , ilist
-    , language-docker >=9.1.3 && <10
+    , language-docker >=9.2.0 && <10
     , megaparsec >=9.0.0
     , mtl
     , network-uri
@@ -163,7 +165,7 @@
     , containers
     , gitrev >=1.3.1
     , hadolint
-    , language-docker >=9.1.3 && <10
+    , language-docker >=9.2.0 && <10
     , megaparsec >=9.0.0
     , optparse-applicative >=0.14.0
     , text
@@ -235,6 +237,8 @@
       DL3056
       DL3057
       DL3058
+      DL3059
+      DL3060
       DL4000
       DL4001
       DL4003
@@ -260,7 +264,7 @@
     , foldl
     , hadolint
     , hspec
-    , language-docker >=9.1.3 && <10
+    , language-docker >=9.2.0 && <10
     , megaparsec >=9.0.0
     , split >=0.2
     , text
diff --git a/src/Hadolint/Config.hs b/src/Hadolint/Config.hs
--- a/src/Hadolint/Config.hs
+++ b/src/Hadolint/Config.hs
@@ -145,7 +145,7 @@
           "\terror:",
           "\t\t- DL3008\n\n",
           "The key 'trustedRegistries' should contain the names of the allowed docker registries:\n",
-          "allowedRegistries:",
+          "trustedRegistries:",
           "\t- docker.io",
           "\t- my-company.com",
           "",
diff --git a/src/Hadolint/Formatter/Format.hs b/src/Hadolint/Formatter/Format.hs
--- a/src/Hadolint/Formatter/Format.hs
+++ b/src/Hadolint/Formatter/Format.hs
@@ -1,6 +1,7 @@
 module Hadolint.Formatter.Format
   ( severityText,
     stripNewlines,
+    errorMessage,
     errorMessageLine,
     errorPosition,
     errorPositionPretty,
@@ -53,6 +54,10 @@
 errorMessageLine :: (VisualStream s, TraversableStream s, ShowErrorComponent e) => ParseErrorBundle s e -> String
 errorMessageLine err@(ParseErrorBundle e _) =
   errorPositionPretty err ++ " " ++ parseErrorTextPretty (NE.head e)
+
+errorMessage :: (VisualStream s, ShowErrorComponent e) => ParseErrorBundle s e -> String
+errorMessage (ParseErrorBundle e _) =
+  reverse . dropWhile (== '\n') . reverse $ parseErrorTextPretty (NE.head e)
 
 errorPositionPretty :: TraversableStream s => ParseErrorBundle s e -> String
 errorPositionPretty err = sourcePosPretty (errorPosition err)
diff --git a/src/Hadolint/Formatter/Json.hs b/src/Hadolint/Formatter/Json.hs
--- a/src/Hadolint/Formatter/Json.hs
+++ b/src/Hadolint/Formatter/Json.hs
@@ -9,7 +9,12 @@
 import qualified Data.ByteString.Lazy.Char8 as B
 import Data.Sequence (Seq)
 import qualified Data.Text as Text
-import Hadolint.Formatter.Format (Result (..), errorPosition, severityText)
+import Hadolint.Formatter.Format
+  ( Result (..),
+    errorPosition,
+    severityText,
+    errorMessage
+  )
 import Hadolint.Rule (CheckFailure (..), DLSeverity (..), unRuleCode)
 import Text.Megaparsec (TraversableStream)
 import Text.Megaparsec.Error
@@ -37,7 +42,7 @@
         "column" .= unPos (sourceColumn pos),
         "level" .= severityText DLErrorC,
         "code" .= ("DL1000" :: Text.Text),
-        "message" .= errorBundlePretty err
+        "message" .= errorMessage err
       ]
     where
       pos = errorPosition err
diff --git a/src/Hadolint/Process.hs b/src/Hadolint/Process.hs
--- a/src/Hadolint/Process.hs
+++ b/src/Hadolint/Process.hs
@@ -67,6 +67,8 @@
 import qualified Hadolint.Rule.DL3056
 import qualified Hadolint.Rule.DL3057
 import qualified Hadolint.Rule.DL3058
+import qualified Hadolint.Rule.DL3059
+import qualified Hadolint.Rule.DL3060
 import qualified Hadolint.Rule.DL4000
 import qualified Hadolint.Rule.DL4001
 import qualified Hadolint.Rule.DL4003
@@ -194,8 +196,10 @@
     <> Hadolint.Rule.DL3054.rule labelSchema
     <> Hadolint.Rule.DL3055.rule labelSchema
     <> Hadolint.Rule.DL3056.rule labelSchema
-    <> Hadolint.Rule.DL3058.rule labelSchema
     <> Hadolint.Rule.DL3057.rule
+    <> Hadolint.Rule.DL3058.rule labelSchema
+    <> Hadolint.Rule.DL3059.rule
+    <> Hadolint.Rule.DL3060.rule
     <> Hadolint.Rule.DL4000.rule
     <> Hadolint.Rule.DL4001.rule
     <> Hadolint.Rule.DL4003.rule
diff --git a/src/Hadolint/Rule/DL3005.hs b/src/Hadolint/Rule/DL3005.hs
--- a/src/Hadolint/Rule/DL3005.hs
+++ b/src/Hadolint/Rule/DL3005.hs
@@ -10,8 +10,8 @@
   where
     code = "DL3005"
     severity = DLErrorC
-    message = "Do not use apt-get upgrade or dist-upgrade"
+    message = "Do not use apt-get dist-upgrade"
     check (Run (RunArgs args _)) =
-      foldArguments (Shell.noCommands (Shell.cmdHasArgs "apt-get" ["upgrade", "dist-upgrade"])) args
+      foldArguments (Shell.noCommands (Shell.cmdHasArgs "apt-get" ["dist-upgrade"])) args
     check _ = True
 {-# INLINEABLE rule #-}
diff --git a/src/Hadolint/Rule/DL3042.hs b/src/Hadolint/Rule/DL3042.hs
--- a/src/Hadolint/Rule/DL3042.hs
+++ b/src/Hadolint/Rule/DL3042.hs
@@ -1,25 +1,66 @@
 module Hadolint.Rule.DL3042 (rule) where
 
 import Data.List (isInfixOf)
+import Data.Map.Strict (Map)
+import qualified Data.Map.Strict as Map
+import Data.Maybe (fromMaybe, isNothing, isJust, fromJust)
+import Data.Set (Set)
+import qualified Data.Set as Set
+import Data.Text (Text)
 import qualified Data.Text as Text
 import Hadolint.Rule
 import qualified Hadolint.Shell as Shell
 import Language.Docker.Syntax
 
+
+-- This data encapsulates the name of a build stage. It may be None withing an
+-- `ONBUILD` context.
+data Stage
+  = Stage {stage :: Text}
+  | None
+  deriving (Eq, Ord)
+
+data Acc
+  = Acc {current :: Stage, noCacheMap :: Map Stage Bool}
+  | Empty
+
+
 rule :: Rule Shell.ParsedShell
-rule = simpleRule code severity message check
+rule = customRule check (emptyState Empty)
   where
     code = "DL3042"
     severity = DLWarningC
-    message =
-      "Avoid use of cache directory with pip. Use `pip install --no-cache-dir <package>`"
-    check (Run (RunArgs args _)) = foldArguments (Shell.noCommands forgotNoCacheDir) args
-    check _ = True
-    forgotNoCacheDir cmd =
-      Shell.isPipInstall cmd && not (usesNoCacheDir cmd) && not (isPipWrapper cmd)
-    usesNoCacheDir cmd = "--no-cache-dir" `elem` Shell.getArgs cmd
+    message = "Avoid use of cache directory with pip.\
+              \ Use `pip install --no-cache-dir <package>`"
+    check _ st (From from) = st |> modify (rememberStage from)
+    check _ st (Env pairs) = st |> modify (registerEnv pairs)
+    check line st (Run (RunArgs args _))
+      | Acc s ncm <- state st, Just True <- Map.lookup s ncm = st
+      | foldArguments pipNoCacheDirIsSet args = st
+      | foldArguments (Shell.noCommands forgotNoCacheDir) args = st
+      | otherwise = st |> addFail CheckFailure {..}
+    check _ st _ = st
 {-# INLINEABLE rule #-}
 
+forgotNoCacheDir :: Shell.Command -> Bool
+forgotNoCacheDir cmd =  Shell.isPipInstall cmd
+    && not (usesNoCacheDir cmd)
+    && not (isPipWrapper cmd)
+
+usesNoCacheDir :: Shell.Command -> Bool
+usesNoCacheDir cmd = "--no-cache-dir" `elem` Shell.getArgs cmd
+
+pipNoCacheDirIsSet :: Shell.ParsedShell -> Bool
+pipNoCacheDirIsSet shell = any
+  (`Text.isPrefixOf` Text.drop 1
+    (Text.dropWhile (/= '=')
+      (snd
+        (Text.breakOn "PIP_NO_CACHE_DIR=" (Shell.original shell)
+        )
+      )
+    )
+  ) truthy
+
 isPipWrapper :: Shell.Command -> Bool
 isPipWrapper cmd@(Shell.Command name _ _) = isWrapper "pipx" || isWrapper "pipenv"
   where
@@ -27,3 +68,52 @@
     isWrapper w =
       w `Text.isInfixOf` name
         || ("python" `Text.isPrefixOf` name && ["-m", w] `isInfixOf` Shell.getArgs cmd)
+
+rememberStage :: BaseImage -> Acc -> Acc
+rememberStage BaseImage {alias = Just als} Empty =
+  Acc
+    { current = Stage {stage = unImageAlias als},
+      noCacheMap = mempty
+    }
+rememberStage BaseImage {alias = Nothing, image} Empty =
+  Acc
+    { current = Stage {stage = imageName image},
+      noCacheMap = mempty
+    }
+rememberStage BaseImage {alias = Just als, image} Acc {..} =
+  Acc
+    { current = Stage {stage = unImageAlias als},
+      noCacheMap =
+        let parentValue =
+              Map.lookup (Stage {stage = imageName image}) noCacheMap |> fromMaybe False
+         in noCacheMap |> Map.insert (Stage {stage = unImageAlias als}) parentValue
+    }
+rememberStage BaseImage {alias = Nothing, image} Acc {..} =
+  Acc
+    { current = Stage {stage = imageName image},
+      noCacheMap =
+        let parentValue =
+              Map.lookup (Stage {stage = imageName image}) noCacheMap |> fromMaybe False
+         in noCacheMap |> Map.insert (Stage {stage = imageName image}) parentValue
+    }
+
+registerEnv :: Pairs -> Acc -> Acc
+registerEnv pairs Empty
+  | pipNoCacheDirSet pairs =
+    Acc {current = None, noCacheMap = Map.insert None True Map.empty}
+  | otherwise = Empty
+registerEnv pairs Acc {..}
+  | pipNoCacheDirSet pairs =
+    Acc {current, noCacheMap = Map.insert current True noCacheMap}
+  | otherwise = Acc {..}
+
+pipNoCacheDirSet :: Pairs -> Bool
+pipNoCacheDirSet [] = False
+pipNoCacheDirSet pairs
+  | isNothing (lookup "PIP_NO_CACHE_DIR" pairs) = False
+  | val <- lookup "PIP_NO_CACHE_DIR" pairs,
+    isJust val && fromJust val `notElem` truthy = False
+  | otherwise = True
+
+truthy :: Set Text
+truthy = Set.fromList ["1", "true", "True", "TRUE", "on", "On", "ON", "yes", "Yes", "YES"]
diff --git a/src/Hadolint/Rule/DL3059.hs b/src/Hadolint/Rule/DL3059.hs
new file mode 100644
--- /dev/null
+++ b/src/Hadolint/Rule/DL3059.hs
@@ -0,0 +1,29 @@
+module Hadolint.Rule.DL3059 (rule) where
+
+import Hadolint.Rule
+import Language.Docker.Syntax
+
+
+data Acc
+  = Acc RunFlags
+  | Empty
+  deriving (Eq, Show)
+
+rule :: Rule args
+rule = customRule check (emptyState Empty)
+  where
+    code = "DL3059"
+    severity = DLInfoC
+    message = "Multiple consecutive `RUN` instructions. Consider consolidation."
+
+    check line st (Run (RunArgs _ flags))
+      | state st == Acc flags = st |> addFail CheckFailure {..}
+      | otherwise = st |> modify (remember flags)
+    check _ st _ = st |> modify reset
+{-# INLINEABLE rule #-}
+
+remember :: RunFlags -> Acc -> Acc
+remember flags _ = Acc flags
+
+reset :: Acc -> Acc
+reset _ = Empty
diff --git a/src/Hadolint/Rule/DL3060.hs b/src/Hadolint/Rule/DL3060.hs
new file mode 100644
--- /dev/null
+++ b/src/Hadolint/Rule/DL3060.hs
@@ -0,0 +1,27 @@
+module Hadolint.Rule.DL3060 (rule) where
+
+import Hadolint.Rule
+import qualified Hadolint.Shell as Shell
+import Language.Docker.Syntax
+
+
+rule :: Rule Shell.ParsedShell
+rule = simpleRule code severity message check
+  where
+    code = "DL3060"
+    severity = DLInfoC
+    message = "`yarn cache clean` missing after `yarn install` was run."
+
+    check (Run (RunArgs args _)) =
+      foldArguments (Shell.noCommands yarnInstall) args
+        || ( foldArguments (Shell.anyCommands yarnInstall) args
+              && foldArguments (Shell.anyCommands yarnCacheClean) args
+           )
+    check _ = True
+{-# INLINEABLE rule #-}
+
+yarnInstall :: Shell.Command -> Bool
+yarnInstall = Shell.cmdHasArgs "yarn" ["install"]
+
+yarnCacheClean :: Shell.Command -> Bool
+yarnCacheClean = Shell.cmdHasArgs "yarn" ["cache", "clean"]
diff --git a/test/DL3005.hs b/test/DL3005.hs
--- a/test/DL3005.hs
+++ b/test/DL3005.hs
@@ -8,9 +8,6 @@
 tests = do
   let ?rulesConfig = mempty
   describe "DL3005" $ do
-    it "apt-get upgrade" $ do
-      ruleCatches "DL3005" "RUN apt-get update && apt-get upgrade"
-      onBuildRuleCatches "DL3005" "RUN apt-get update && apt-get upgrade"
     it "apt-get dist-upgrade" $ do
       ruleCatches "DL3005" "RUN apt-get update && apt-get dist-upgrade"
       onBuildRuleCatches "DL3005" "RUN apt-get update && apt-get dist-upgrade"
diff --git a/test/DL3042.hs b/test/DL3042.hs
--- a/test/DL3042.hs
+++ b/test/DL3042.hs
@@ -1,5 +1,6 @@
 module DL3042 (tests) where
 
+import Data.Text as Text
 import Helpers
 import Test.Hspec
 
@@ -32,3 +33,54 @@
     it "don't match on pipenv" $ do
       ruleCatchesNot "DL3042" "RUN pipenv install library"
       onBuildRuleCatchesNot "DL3042" "RUN pipenv install library"
+
+    -- ENV won't work with the onBuildRuleCatches[Not] wrapper:
+    it "respect ENV PIP_NO_CACHE_DIR with truthy values" $ do
+      ruleCatchesNot "DL3042" "ENV PIP_NO_CACHE_DIR=1\nRUN pip install MySQL_python"
+      ruleCatchesNot "DL3042" "ENV PIP_NO_CACHE_DIR=on\nRUN pip install MySQL_python"
+      ruleCatchesNot "DL3042" "ENV PIP_NO_CACHE_DIR=yes\nRUN pip install MySQL_python"
+      ruleCatchesNot "DL3042" "ENV PIP_NO_CACHE_DIR=true\nRUN pip install MySQL_python"
+    it "respect RUN PIP_NO_CACHE_DIR=... with truthy values" $ do
+      ruleCatchesNot "DL3042" "RUN PIP_NO_CACHE_DIR=1 pip install MySQL_python"
+      ruleCatchesNot "DL3042" "RUN PIP_NO_CACHE_DIR=on pip install MySQL_python"
+      ruleCatchesNot "DL3042" "RUN PIP_NO_CACHE_DIR=yes pip install MySQL_python"
+      ruleCatchesNot "DL3042" "RUN PIP_NO_CACHE_DIR=true pip install MySQL_python"
+    it "respect RUN export PIP_NO_CACHE_DIR=... with truthy values" $ do
+      ruleCatchesNot "DL3042" "RUN export PIP_NO_CACHE_DIR=1 && pip install MySQL_python"
+      ruleCatchesNot "DL3042" "RUN export PIP_NO_CACHE_DIR=on && pip install MySQL_python"
+      ruleCatchesNot "DL3042" "RUN export PIP_NO_CACHE_DIR=yes && pip install MySQL_python"
+      ruleCatchesNot "DL3042" "RUN export PIP_NO_CACHE_DIR=true && pip install MySQL_python"
+    it "respect ENV PIP_NO_CACHE_DIR with falsy values" $ do
+      ruleCatches "DL3042" "ENV PIP_NO_CACHE_DIR=0\nRUN pip install MySQL_python"
+      ruleCatches "DL3042" "ENV PIP_NO_CACHE_DIR=off\nRUN pip install MySQL_python"
+      ruleCatches "DL3042" "ENV PIP_NO_CACHE_DIR=no\nRUN pip install MySQL_python"
+      ruleCatches "DL3042" "ENV PIP_NO_CACHE_DIR=false\nRUN pip install MySQL_python"
+    it "respect RUN PIP_NO_CACHE_DIR=... with falsy values" $ do
+      ruleCatches "DL3042" "RUN PIP_NO_CACHE_DIR=0 pip install MySQL_python"
+      ruleCatches "DL3042" "RUN PIP_NO_CACHE_DIR=off pip install MySQL_python"
+      ruleCatches "DL3042" "RUN PIP_NO_CACHE_DIR=no pip install MySQL_python"
+      ruleCatches "DL3042" "RUN PIP_NO_CACHE_DIR=false pip install MySQL_python"
+    it "respect RUN export PIP_NO_CACHE_DIR=... with falsy values" $ do
+      ruleCatches "DL3042" "RUN export PIP_NO_CACHE_DIR=0 && pip install MySQL_python"
+      ruleCatches "DL3042" "RUN export PIP_NO_CACHE_DIR=off && pip install MySQL_python"
+      ruleCatches "DL3042" "RUN export PIP_NO_CACHE_DIR=no && pip install MySQL_python"
+      ruleCatches "DL3042" "RUN export PIP_NO_CACHE_DIR=false && pip install MySQL_python"
+
+    it "don't trigger if PIP_NO_CACHE_DIR is inherited" $
+      let dockerFile = Text.unlines
+            [ "FROM debian:buster as base",
+              "ENV PIP_NO_CACHE_DIR=1",
+              "FROM base",
+              "RUN pip install six"
+            ]
+       in do
+        ruleCatchesNot "DL3042" dockerFile
+    it "trigger if PIP_NO_CACHE_DIR is not inherited" $
+      let dockerFile = Text.unlines
+            [ "FROM debian:buster as base",
+              "ENV PIP_NO_CACHE_DIR=1",
+              "FROM debian:buster",
+              "RUN pip install six"
+            ]
+       in do
+        ruleCatches "DL3042" dockerFile
diff --git a/test/DL3059.hs b/test/DL3059.hs
new file mode 100644
--- /dev/null
+++ b/test/DL3059.hs
@@ -0,0 +1,31 @@
+module DL3059 (tests) where
+
+import Data.Text as Text
+import Helpers
+import Test.Hspec
+
+
+tests :: SpecWith ()
+tests = do
+  let ?rulesConfig = mempty
+  describe "DL3059 - Multiple consecutive `RUN` instructions" $ do
+    it "ok with no `RUN` at all" $ do
+      ruleCatchesNot "DL3059" "FROM debian:10"
+    it "ok with one `RUN`" $ do
+      ruleCatchesNot "DL3059" "RUN /foo.sh"
+    it "ok with two not consecutive `RUN`" $ do
+      ruleCatchesNot "DL3059" "RUN /foo.sh\nWORKDIR /\nRUN /bar.sh"
+    it "not ok with two consecutive `RUN`s" $ do
+      ruleCatches "DL3059" "RUN /foo.sh\nRUN /bar.sh"
+    it "ok with two consecutive `RUN`s when flags are different 1" $ do
+      ruleCatchesNot "DL3059" "RUN --mount=type=secret,id=foo /foo.sh\nRUN /bar.sh"
+    it "ok with two consecutive `RUN`s when flags are different 2" $ do
+      let dfile = [ "RUN --mount=type=secret,id=foo /foo.sh",
+                    "RUN --mount=type=secret,id=bar /bar.sh"
+                  ]
+       in ruleCatchesNot "DL3059" $ Text.unlines dfile
+    it "not ok with two consecutive `RUN`s when flags are equal" $ do
+      let dfile = [ "RUN --mount=type=secret,id=foo /foo.sh",
+                    "RUN --mount=type=secret,id=foo /bar.sh"
+                  ]
+       in ruleCatches "DL3059" $ Text.unlines dfile
diff --git a/test/DL3060.hs b/test/DL3060.hs
new file mode 100644
--- /dev/null
+++ b/test/DL3060.hs
@@ -0,0 +1,19 @@
+module DL3060 (tests) where
+
+import Helpers
+import Test.Hspec
+
+
+tests :: SpecWith ()
+tests = do
+  let ?rulesConfig = mempty
+  describe "DL3060 - `yarn cache clean` missing after `yarn install`" $ do
+    it "ok with non-yarn commands" $ do
+      ruleCatchesNot "DL3060" "RUN foo"
+      onBuildRuleCatchesNot "DL3060" "RUN foo"
+    it "not ok with no cache clean" $ do
+      ruleCatches "DL3060" "RUN yarn install foo"
+      onBuildRuleCatches "DL3060" "RUN yarn install foo"
+    it "ok with cache clean" $ do
+      ruleCatchesNot "DL3060" "RUN yarn install bar && yarn cache clean"
+      onBuildRuleCatchesNot "DL3060" "RUN yarn install bar && yarn cache clean"
diff --git a/test/ShellSpec.hs b/test/ShellSpec.hs
--- a/test/ShellSpec.hs
+++ b/test/ShellSpec.hs
@@ -1,6 +1,5 @@
 module ShellSpec where
 
-import Data.Text as Text
 import Hadolint.Shell
 import Test.Hspec
 
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -59,11 +59,13 @@
 import qualified DL3056
 import qualified DL3057
 import qualified DL3058
+import qualified DL3059
 import qualified DL4001
 import qualified DL4003
 import qualified DL4004
 import qualified DL4005
 import qualified DL4006
+import Hadolint.Formatter.Format (errorMessage)
 import Hadolint.Formatter.TTY (formatError)
 import Helpers
 import Language.Docker.Parser
@@ -86,6 +88,13 @@
         case ast of
           Left err -> assertEqual "Unexpected error msg" expectedMsg (formatError err)
           Right _ -> assertFailure "AST should fail parsing"
+    describe "errorMessage" $
+      it "display just the error message" $ do
+        let ast = parseText "RUNNN"
+            expectedMsg = "missing whitespace"
+        case ast of
+          Left err -> assertEqual "Unexpected error msg" expectedMsg (errorMessage err)
+          Right _ -> assertFailure "AST should fail parsing"
     --
     describe "Rules can be ignored with inline comments" $ do
       it "ignores single rule" $
@@ -220,6 +229,7 @@
     DL3056.tests
     DL3057.tests
     DL3058.tests
+    DL3059.tests
     DL4001.tests
     DL4003.tests
     DL4004.tests
