packages feed

stack-hpc-coveralls-0.0.0.1: src/SHC/Api.hs

{-# LANGUAGE OverloadedStrings #-}
module SHC.Api (sendData, readCoverageResult)
    where

import Safe (atMay, headMay)
import Data.Aeson (Value, encode)
import Data.Aeson.Lens (key, _String)
import qualified Data.Text as T
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import Codec.Binary.UTF8.String (decode)
import Control.Lens
import Network.Wreq
import Network.HTTP.Client (RequestBody(RequestBodyLBS))
import Network.HTTP.Client.MultipartFormData (partFileRequestBody)

import SHC.Types


sendData :: Config -> String -> Value -> IO PostResult
sendData conf url json = do
    r <- post url [partFileRequestBody "json_file" fileName requestBody]
    if r ^. responseStatus . statusCode == 200
       then return $ readResponse r
       else return . PostFailure $
           "Error: " ++ decode (BS.unpack $ r ^. responseStatus . statusMessage)
    where fileName    = serviceName conf ++ "-" ++ jobId conf ++ ".json"
          requestBody = RequestBodyLBS $ encode json

readResponse :: Response LBS.ByteString -> PostResult
readResponse r =
    case r ^? responseBody . key "error" . _String of
      Just err -> PostFailure $ T.unpack err
      Nothing  -> case r ^? responseBody . key "url" . _String of
                    Just url -> PostSuccess $ T.unpack url
                    Nothing  -> PostFailure "Error: malformed response body"

-- | Extract the total coverage percentage value from coveralls coverage result
--   page content.  The current implementation is kept as low level as possible
--   in order not to increase the library build time, by not relying on
--   additional packages.
extractCoverage :: T.Text -> Maybe T.Text
extractCoverage body = T.splitOn "<"
                    <$> T.splitOn prefix body `atMay` 1 >>= headMay
    where prefix = "div class='run-statistics'>\n<strong>"

-- | Read the coveraege result page from coveralls.io
readCoverageResult :: String -> IO (Maybe String)
readCoverageResult url = do
    r <- get url
    return . fmap T.unpack . extractCoverage $
        r ^. responseBody . _String