neil-0.0: src/Travis.hs
{-# LANGUAGE RecordWildCards, PatternGuards #-}
module Travis(run) where
import Control.Monad
import Data.Char
import Data.List.Extra hiding (list)
import System.Directory
import System.IO.Extra
import System.FilePath
import System.Time.Extra
import Text.JSON
import Arguments
import Util
run :: Arguments -> Maybe (IO ())
run Travis{..} = Just $ do
dir <- getCurrentDirectory
let name = takeFileName dir
createDirectoryIfMissing True "dist"
appendFile "dist/travis" ""
rel <- findRelevant
found <- findEntries
let more [] = more . list =<< wgetJSON wait ("https://api.travis-ci.org/repos/ndmitchell/" ++ name ++ "/builds")
more xs = let i = read (last xs ! "number") in if i == 1 then return xs else do
new <- wgetJSON wait $ "https://api.travis-ci.org/repos/ndmitchell/" ++ name ++ "/builds?after_number=" ++ show i
more $ xs ++ list new
builds <- more []
forM_ (reverse builds) $ \x -> do
let num = x ! "number"
let id = show (x ! "id" :: Int)
let time = x ! "started_at"
when (num `notElem` found && x ! "result" /= JSNull) $ do
build <- wgetJSON wait $ "https://api.travis-ci.org/builds/" ++ id
sleep 2
let jobs = map (\x -> show (x ! "id" :: Int)) $ build ! "matrix"
forM_ jobs $ \i -> do
putChar '.'
src <- wget wait $ "https://s3.amazonaws.com/archive.travis-ci.org/jobs/" ++ i ++ "/log.txt"
let want = [x | x <- lines $ reps '\r' '\n' src, any (`isPrefixOf` x) rel]
addEntry num time want
when (null jobs) $ addEntry num time []
putStrLn "\nDone!"
run _ = Nothing
findRelevant :: IO [String]
findRelevant = do
src <- fmap lines $ readFile ".travis.yml"
src <- return $ takeWhile (isPrefixOf " ") $ drop 1 $ dropWhile (not . isPrefixOf "relevant") src
when (null src) $ error "No relevant lines in the travis file"
return $ map (dropWhile isSpace) src
findEntries :: IO [String]
findEntries = do
x <- readFile "dist/travis"
return [takeWhile isDigit x | x <- lines x, Just x <- ["BUILD " `stripPrefix` x]]
addEntry :: String -> String -> [String] -> IO ()
addEntry num time xs = appendFile "dist/travis" $ unlines $ ("BUILD " ++ num ++ " " ++ time) : xs
wget :: Double -> String -> IO String
wget wait x = withTempFile $ \t -> do
putStr $ "wget " ++ x ++ " ... "
cmd $ "wget " ++ x ++ " -O" ++ t ++ " --no-check-certificate --quiet"
res <- readFile' t
putStrLn "done"
sleep wait
return res
wgetJSON :: Double -> String -> IO JSValue
wgetJSON wait x = fmap (ok . decode) $ wget wait x
ok (Ok x) = x
ok (Error x) = error x
(!) :: JSON a => JSValue -> String -> a
(!) (JSObject mp) k = ok $ valFromObj k mp
list :: JSValue -> [JSValue]
list (JSArray x) = x