on master help sign in
Slightly better output signalling (#58)
44a3c27iko
src/OpenAPI/Checker/Options.hs+42−38
@@ -1,8 +1,9 @@
1module OpenAPI.Checker.Options
1module OpenAPI.Checker.Options
2− ( Options (..),
2+ ( Options (..)
3− Mode (..),
3+ , Mode (..)
4+ , OutputMode (..)
4− optionsParserInfo,
5+ , optionsParserInfo
5− execParser,
6+ , execParser
6 )
7 )
7where
8where
8
9
@@ -10,52 +11,55 @@ import GHC.Generics (Generic)
10import Options.Applicative
11import Options.Applicative
11
12
12data Options = Options
13data Options = Options
13− { clientFile :: FilePath,
14+ { clientFile :: FilePath
14− serverFile :: FilePath,
15+ , serverFile :: FilePath
15− mode :: Mode
16+ , mode :: Mode
17+ , outputMode :: OutputMode
16 }
18 }
17 deriving stock (Generic)
19 deriving stock (Generic)
18
20
19data Mode = Silent | OnlyErrors | All
21data Mode = Silent | OnlyErrors | All
20
22
23+data OutputMode = StdoutMode | FileMode FilePath
24+
21optionsParserInfo :: ParserInfo Options
25optionsParserInfo :: ParserInfo Options
22optionsParserInfo =
26optionsParserInfo =
23 info
27 info
24 (helper <*> optionsParser)
28 (helper <*> optionsParser)
25− ( fullDesc
29+ (fullDesc
26− <> header "openapi-diff"
30+ <> header "openapi-diff"
27− <> progDesc "A tool to check compatibility between two OpenApi specifications."
31+ <> progDesc "A tool to check compatibility between two OpenApi specifications.")
28− )
29
32
30optionsParser :: Parser Options
33optionsParser :: Parser Options
31optionsParser =
34optionsParser =
32 Options
35 Options
33 <$> strOption
36 <$> strOption
34− ( short 'c'
37+ (short 'c'
35− <> long "client"
38+ <> long "client"
36− <> help "The specification that will be used for the client of the API."
39+ <> help "The specification that will be used for the client of the API.")
37− )
38 <*> strOption
40 <*> strOption
39− ( short 's'
41+ (short 's'
40− <> long "server"
42+ <> long "server"
41− <> help "The specification that will be used for the server of the API."
43+ <> help "The specification that will be used for the server of the API.")
42− )
43− <*> ( flag'
44+ <*> (flag'
44− Silent
45+ Silent
45− ( long "silent"
46+ (long "silent"
46− <> help "Silence all output."
47+ <> help "Silence all output.")
47− )
48− <|> flag'
48+ <|> flag'
49− OnlyErrors
49+ OnlyErrors
50− ( long "only-errors"
50+ (long "only-errors"
51− <> help "Only report incompatibility errors in the output."
51+ <> help "Only report incompatibility errors in the output.")
52− )
53− <|> flag'
52+ <|> flag'
54− All
53+ All
55− ( long "all"
54+ (long "all"
56− <> help
55+ <> help
57− "Report both incompatible and compatible changes. \
56+ "Report both incompatible and compatible changes. \
58− \Compatible changes will not trigger a failure exit code."
57+ \Compatible changes will not trigger a failure exit code.")
59− )
60− <|> pure All
58+ <|> pure All)
61− )
59+ <*> (pure StdoutMode
60+ <|> (FileMode
61+ <$> strOption
62+ (short 'o' <> long "output"
63+ <> help
64+ "The file path where the output should be writtrn. \
65+ \Leave blank to output result to stdout.")))
src/OpenAPI/Checker/Run.hs+14−4
@@ -5,9 +5,10 @@ import qualified Data.ByteString.Char8 as BSC
5import Data.HList
5import Data.HList
6import qualified Data.Yaml as Yaml
6import qualified Data.Yaml as Yaml
7import OpenAPI.Checker.Options
7import OpenAPI.Checker.Options
8−import OpenAPI.Checker.Subtree
9import OpenAPI.Checker.Paths
8import OpenAPI.Checker.Paths
9+import OpenAPI.Checker.Subtree
10import OpenAPI.Checker.Validate.OpenApi ()
10import OpenAPI.Checker.Validate.OpenApi ()
11+import System.Exit
11import Prelude hiding (id, (.))
12import Prelude hiding (id, (.))
12
13
13runChecker :: IO ()
14runChecker :: IO ()
@@ -19,12 +20,21 @@ runChecker = do
19 Yaml.decodeFileEither path >>= \case
20 Yaml.decodeFileEither path >>= \case
20 Left yamlErr -> do
21 Left yamlErr -> do
21 putStrLn "Could not parse as json or yaml"
22 putStrLn "Could not parse as json or yaml"
22− putStrLn $ show jsonErr
23+ print jsonErr
23− putStrLn $ show yamlErr
24+ print yamlErr
24 fail "Exiting"
25 fail "Exiting"
25 Right s -> pure s
26 Right s -> pure s
26 Right s -> pure s
27 Right s -> pure s
27 a <- traced Root <$> parseSchema (clientFile opts)
28 a <- traced Root <$> parseSchema (clientFile opts)
28 b <- traced Root <$> parseSchema (serverFile opts)
29 b <- traced Root <$> parseSchema (serverFile opts)
29 let report = runCompatFormula $ checkCompatibility HNil Root (ProdCons a b)
30 let report = runCompatFormula $ checkCompatibility HNil Root (ProdCons a b)
31+ output = case outputMode opts of
32+ StdoutMode -> BSC.putStrLn
33+ FileMode f -> BSC.writeFile f
34+ case report of
35+ Right () -> do
36+ output "No breaking changes found ✨"
37+ exitSuccess
38+ Left e -> do
30− BSC.putStrLn $ Yaml.encode report
39+ output $ Yaml.encode e
40+ exitFailure