{-# LANGUAGE QuasiQuotes #-} module Main where import Data.List (find) import Data.Maybe (isJust) import Data.Aeson (encode) import qualified Data.ByteString.Lazy as BSL import Control.Applicative (pure, (<$>), (<*>)) import Control.Concurrent (threadDelay) import System.Console.Docopt import System.Environment (getArgs, getEnv, getEnvironment) import System.Exit (exitFailure) import SHC urlApiV1 :: String urlApiV1 = "https://coveralls.io/api/v1/jobs" getServiceAndJobId :: IO (String, String) getServiceAndJobId = do env <- getEnvironment case snd <$> find (isJust . flip lookup env . fst) ciEnvVars of Just (ciName, jobIdVarName) -> do jId <- getEnv jobIdVarName return (ciName, jId) _ -> error "Unsupported CI service." where ciEnvVars = [ ("TRAVIS", ("travis-ci", "TRAVIS_JOB_ID")), ("CIRCLECI", ("circleci", "CIRCLE_BUILD_NUM")), ("SEMAPHORE", ("semaphore", "REVISION")), ("JENKINS_URL", ("jenkins", "BUILD_ID")), ("CI_NAME", ("codeship", "CI_BUILD_NUMBER"))] patterns :: Docopt patterns = [docoptFile|USAGE.txt|] getArgOrExit :: Arguments -> Option -> IO String getArgOrExit = getArgOrExitWith patterns defaultOr :: Arguments -> Option -> IO String -> IO String defaultOr args opt action = maybe action return $ args `getArg` opt getConfig :: Arguments -> IO Config getConfig args = do -- TODO: Read from Cabal? pn <- args `getArgOrExit` argument "package-name" (sn, jId) <- getServiceAndJobId Config <$> args `getArgOrExit` argument "suite-name" <*> pure sn <*> pure jId <*> pure (args `getArg` longOption "repo-token") <*> getGitInfo <*> defaultOr args (longOption "hpc-dir") (getHpcDir pn) <*> defaultOr args (longOption "hpc-dir") getMixDir <*> pure (if args `isPresent` longOption "partial-coverage" then PartialLines else FullLines) main :: IO () main = do args <- parseArgsOrExit patterns =<< getArgs conf <- getConfig args coverallsJson <- generateCoverallsFromTix conf if args `isPresent` longOption "dont-send" then BSL.putStr $ encode coverallsJson else do response <- sendData conf urlApiV1 coverallsJson case response of PostSuccess url -> do putStrLn $ "URL: " ++ url -- wait 5 seconds until the page is available threadDelay $ 5 * 1000 * 1000 coverageResult <- readCoverageResult url case coverageResult of Just totalCov -> putStrLn $ "Coverage: " ++ totalCov Nothing -> putStrLn "Failed to read total coverage" PostFailure msg -> do putStrLn $ "Error: " ++ msg exitFailure