{-# LANGUAGE CPP #-} {-# LANGUAGE QuasiQuotes #-} module Main where import Control.Monad (unless, when) import Data.Aeson (encode) import qualified Data.ByteString.Lazy as BSL import Data.List (find) import Data.Maybe (isJust) #if __GLASGOW_HASKELL__ < 710 import Control.Applicative (pure, (<$>), (<*>)) #endif import Control.Concurrent (threadDelay) import System.Console.Docopt import System.Environment (getArgs, getEnv, getEnvironment) import System.Exit (exitFailure) import SHC.Api import SHC.Coverage import SHC.Stack import SHC.Types import SHC.Utils 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 pn <- args `getArgOrExit` argument "package-name" let suites = args `getAllArgs` argument "suite-name" unless (not $ null suites) $ putStrLn "Error: provide at least one test-suite name" >> exitFailure (sn, jId) <- getServiceAndJobId Config <$> pure pn <*> pure suites <*> pure sn <*> pure jId <*> pure (args `getArg` longOption "repo-token") <*> getGitInfo <*> defaultOr args (longOption "hpc-dir") (getHpcDir pn) <*> pure (args `getArg` longOption "mix-dir") <*> pure (if args `isPresent` longOption "partial-coverage" then PartialLines else FullLines) <*> getStackProjects <*> pure (args `isPresent` longOption "fetch-coverage") main :: IO () main = do args <- parseArgsOrExit patterns =<< getArgs stackGood <- checkStackVersion unless stackGood $ do putStrLn "Error: at least Stack 0.1.7 is required" exitFailure 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 u -> do let apiUrl = u ++ ".json" putStrLn $ "Job URL: " ++ apiUrl when (fetchCoverage conf) $ do -- wait 5 seconds until the page is available threadDelay $ 5 * 1000 * 1000 coverageResult <- readCoverageResult apiUrl case coverageResult of Just totalCov -> putStrLn $ "Coverage: " ++ show totalCov Nothing -> putStrLn "Failed to read total coverage" PostFailure msg -> do putStrLn $ "Error: " ++ msg exitFailure