haskell-ci-0.14: src/HaskellCI/GitHub/Yaml.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StrictData #-}
module HaskellCI.GitHub.Yaml where
import HaskellCI.Prelude
import qualified Data.Map.Strict as M
import HaskellCI.Compiler
import HaskellCI.List
import HaskellCI.Sh
import HaskellCI.YamlSyntax
-------------------------------------------------------------------------------
-- Data
-------------------------------------------------------------------------------
data GitHub = GitHub
{ ghName :: String
, ghOn :: GitHubOn
, ghJobs :: M.Map String GitHubJob
}
deriving (Show)
newtype GitHubOn = GitHubOn
{ ghBranches :: [String]
}
deriving (Show)
data GitHubJob = GitHubJob
{ ghjName :: String
, ghjRunsOn :: String
, ghjNeeds :: [String]
, ghjIf :: Maybe String
, ghjContainer :: Maybe String
, ghjServices :: M.Map String GitHubService
, ghjContinueOnError :: Maybe String
, ghjMatrix :: [GitHubMatrixEntry]
, ghjSteps :: [GitHubStep]
, ghjTimeout :: Natural
}
deriving (Show)
data SetupMethod = HVRPPA | GHCUP
deriving Show
data GitHubMatrixEntry = GitHubMatrixEntry
{ ghmeCompiler :: CompilerVersion
, ghmeAllowFailure :: Bool
, ghmeSetupMethod :: SetupMethod
}
deriving (Show)
data GitHubStep = GitHubStep
{ ghsName :: String
, ghsStep :: Either GitHubRun GitHubUses
}
deriving (Show)
-- | Steps with @run@
data GitHubRun = GitHubRun
{ ghsRun :: [Sh]
, ghsEnv :: M.Map String String
}
deriving (Show)
-- | Steps with @uses@
data GitHubUses = GitHubUses
{ ghsAction :: String
, ghsIf :: Maybe String
, ghsWith :: M.Map String String
}
deriving (Show)
data GitHubService = GitHubService
{ ghServImage :: String
, ghServEnv :: M.Map String String
, ghServOptions :: Maybe String
}
deriving (Show)
-------------------------------------------------------------------------------
-- ToYaml
-------------------------------------------------------------------------------
instance ToYaml GitHub where
toYaml GitHub {..} = ykeyValuesFilt []
[ "name" ~> fromString ghName
, "on" ~> toYaml ghOn
, "jobs" ~> ykeyValuesFilt []
[ ([], j, toYaml job)
| (j, job) <- M.toList ghJobs
]
]
instance ToYaml GitHubOn where
toYaml GitHubOn {..}
| null ghBranches
= ylistFilt [] ["push", "pull_request"]
| otherwise
= ykeyValuesFilt []
[ "push" ~> branches
, "pull_request" ~> branches
]
where
branches = ykeyValuesFilt []
[ "branches" ~> ylistFilt [] (map fromString ghBranches)
]
instance ToYaml GitHubJob where
toYaml GitHubJob {..} = ykeyValuesFilt [] $ buildList $ do
item $ "name" ~> fromString ghjName
item $ "runs-on" ~> fromString ghjRunsOn
item $ "needs" ~> ylistFilt [] (map fromString ghjNeeds)
for_ ghjIf $ \if_ ->
item $ "if" ~> fromString if_
item $ "timeout-minutes" ~> YNumber [] (toInteger ghjTimeout)
item $ "container" ~> ykeyValuesFilt [] (buildList $
for_ ghjContainer $ \image -> item $ "image" ~> fromString image)
item $ "services" ~> toYaml ghjServices
for_ ghjContinueOnError $ \continueOnError ->
item $ "continue-on-error" ~> fromString continueOnError
item $ "strategy" ~> ykeyValuesFilt []
[ "matrix" ~> ykeyValuesFilt []
[ "include" ~> ylistFilt [] (map toYaml ghjMatrix)
]
, "fail-fast" ~> YBool [] False
]
item $ "steps" ~> ylistFilt [] (map toYaml $ filter notEmptyStep ghjSteps)
instance ToYaml SetupMethod where
toYaml HVRPPA = "hvr-ppa"
toYaml GHCUP = "ghcup"
instance ToYaml GitHubMatrixEntry where
toYaml GitHubMatrixEntry {..} = ykeyValuesFilt []
[ "compiler" ~> fromString (dispGhcVersion ghmeCompiler)
, "compilerKind" ~> fromString (compilerKind ghmeCompiler)
, "compilerVersion" ~> fromString (compilerVersion ghmeCompiler)
, "setup-method" ~> toYaml ghmeSetupMethod
, "allow-failure" ~> toYaml ghmeAllowFailure
]
instance ToYaml GitHubStep where
toYaml GitHubStep {..} = ykeyValuesFilt [] $
[ "name" ~> fromString ghsName
] ++ case ghsStep of
Left GitHubRun {..} ->
[ "run" ~> fromString (shlistToString ghsRun)
, "env" ~> mapToYaml ghsEnv
]
Right GitHubUses {..} -> buildList $ do
item $ "uses" ~> fromString ghsAction
for_ ghsIf $ \if_ -> item $ "if" ~> fromString if_
item $ "with" ~> mapToYaml ghsWith
notEmptyStep :: GitHubStep -> Bool
notEmptyStep (GitHubStep _ (Left (GitHubRun [] _))) = False
notEmptyStep _ = True
instance ToYaml GitHubService where
toYaml GitHubService {..} = ykeyValuesFilt [] $ buildList $ do
item $ "image" ~> fromString ghServImage
item $ "env" ~> toYaml (YString [] <$> ghServEnv)
for_ ghServOptions $ \opt -> item $ "options" ~> fromString opt
-------------------------------------------------------------------------------
-- Helpers
-------------------------------------------------------------------------------
mapToYaml :: M.Map String String -> Yaml [String]
mapToYaml m = ykeyValuesFilt []
[ k ~> fromString v
| (k, v) <- M.toList m
]