blob: 009ba9a564e64b30560b7ed3d42b46c6ed9d8271 [file] [log] [blame]
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This script checks build status of given pullrequest identified by author and commit hash.
#
# usage)
# python travis_check.py [author] [commit hash] [check interval (optional)]
#
# example)
# # full hash
# python travis_check.py Leemoonsoo 1f2549a38f440ebfbfe2d32a041684e3e39b496c
#
# # with short hash
# python travis_check.py Leemoonsoo 1f2549a
#
# # with custom check interval
# python travis_check.py Leemoonsoo 1f2549a 5,60,60
import os, sys, getopt, traceback, json, requests, time, urllib3, re
# disable SNIMissingWarning. see https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
urllib3.disable_warnings()
author = sys.argv[1]
commit = sys.argv[2]
# check interval in sec
check = [5, 60, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 600, 600, 600, 600, 600, 600]
if len(sys.argv) > 3:
check = map(lambda x: int(x), sys.argv[3].split(","))
def info(msg):
print("[" + time.strftime("%Y-%m-%d %H:%M:%S") + "] " + msg)
sys.stdout.flush()
info("Author: " + author + ", commit: " + commit)
def getBuildStatus(author, commit):
travisApi = "https://api.travis-ci.org/"
# get latest 25 builds
resp = requests.get(url=travisApi + "/repos/" + author + "/zeppelin/builds")
data = json.loads(resp.text)
build = None
if len(data) == 0:
return build
for b in data:
if b["commit"][:len(commit)] == commit:
resp = requests.get(url=travisApi + "/repos/" + author + "/zeppelin/builds/" + str(b["id"]))
build = json.loads(resp.text)
break
return build
def status(index, msg, jobId):
return '{:20}'.format("[" + str(index+1) + "] " + msg) + "https://travis-ci.org/" + author + "/zeppelin/jobs/" + str(jobId)
# load full build log and summarize
def logSummary(url):
# test start pattern "Running org.apache.zeppelin.scheduler.ParallelSchedulerTest"
testStartPattern = re.compile("^Running[ ](.*)")
# test end pattern "Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.554 sec - in org.apache.zeppelin.scheduler.JobTest"
testEndPattern = re.compile("^Tests [^0-9]*([0-9]+)[^0-9]*([0-9]+)[^0-9]*([0-9]+)[^0-9]*([0-9]+)[^-]*[-][ ]in[ ](.*)")
tests = {}
resp = requests.get(url=url)
lines = resp.text.splitlines()
lastNonEmptyLine = ""
indent = '{:10}'.format("")
for line in lines:
if not len(line.strip()) == 0:
lastNonEmptyLine = line
mStart = testStartPattern.match(line)
if mStart:
testName = mStart.group(1)
tests[testName] = {
"start": mStart
}
continue
mEnd = testEndPattern.match(line)
if mEnd:
testName = mEnd.group(5)
tests[testName]["end"] = mEnd
continue
for testName, test in tests.items():
if not "end" in test:
print(indent + "Test " + testName + " never finished")
else:
failures = int(test["end"].group(2))
errors = int(test["end"].group(3))
if failures > 0 or errors > 0:
print(indent + test["end"].group(0))
if not lastNonEmptyLine.startswith("Done"):
print(indent + lastNonEmptyLine)
print(indent + "Please check full log at " + url)
def printBuildStatus(build):
failure = 0
running = 0
for index, job in enumerate(build["matrix"]):
result = job["result"]
jobId = job["id"]
if job["started_at"] == None and result == None:
print(status(index, "Not started", jobId))
running = running + 1
elif job["started_at"] != None and job["finished_at"] == None:
print(status(index, "Running ...", jobId))
running = running + 1
elif job["started_at"] != None and job["finished_at"] != None:
if result == None:
print(status(index, "Not completed", jobId))
failure = failure + 1
logSummary("https://api.travis-ci.org/v3/job/" + str(jobId) + "/log.txt")
elif result == 0:
print(status(index, "OK", jobId))
else:
print(status(index, "Error " + str(result), jobId))
failure = failure + 1
logSummary("https://api.travis-ci.org/v3/job/" + str(jobId) + "/log.txt")
else:
print(status(index, "Unknown state", jobId))
failure = failure + 1
return failure, running
for sleep in check:
info("--------------------------------")
time.sleep(sleep)
info("Get build status ...")
build = getBuildStatus(author, commit)
if build == None:
info("Can't find build for commit " + commit + " from " + author)
sys.exit(2)
print("Build https://travis-ci.org/" + author + "/zeppelin/builds/" + str(build["id"]))
failure, running = printBuildStatus(build)
print(str(failure) + " job(s) failed, " + str(running) + " job(s) running/pending")
if failure != 0:
sys.exit(1)
if failure == 0 and running == 0:
info("CI Green!")
sys.exit(0)
info("Timeout")
sys.exit(1)