from BuildDemos import demos
import argparse, requests, json, subprocess, re, pickle
parser = argparse.ArgumentParser()
parser.add_argument("version", type=str, help="Vaadin version that was just built")
parser.add_argument("teamcityUser", type=str, help="Teamcity username to use")
parser.add_argument("teamcityPassword", type=str, help="Password for given teamcity username")
parser.add_argument("teamcityUrl", type=str, help="Address to the teamcity server")
parser.add_argument("buildTypeId", type=str, help="The ID of this build step")
parser.add_argument("buildId", type=str, help="ID of the build to generate this report for")
parser.add_argument("stagingRepoUrl", type=str, help="URL to the staging repository")
args = parser.parse_args()
buildResultUrl = "http://{}/viewLog.html?buildId={}&tab=buildResultsDiv&buildTypeId={}".format(args.teamcityUrl, args.buildId, args.buildTypeId)
def createTableRow(*columns):
html = "
"
for column in columns:
html += "
" + column + "
"
return html + "
"
def getHtmlList(array):
html = "
"
for item in array:
html += "
" + item + "
"
return html + "
"
def getBuildStatusHtml():
build_steps_request_string = "http://{}/app/rest/problemOccurrences?locator=build:{}".format(args.teamcityUrl, args.buildId)
build_steps_request = requests.get(build_steps_request_string, auth=(args.teamcityUser, args.teamcityPassword), headers={'Accept':'application/json'})
if build_steps_request.status_code != 200:
return createTableRow(traffic_light.format(color="black"), "Build status: unable to retrieve status of build")
else:
build_steps_json = build_steps_request.json()
if build_steps_json["count"] == 0:
return createTableRow(traffic_light.format(color="green"), "Build status: all build steps successful")
else:
return createTableRow(traffic_light.format(color="red"), "Build status: there are failing build steps, check the build report".format(buildResultUrl))
def getTestStatusHtml():
test_failures_request_string = "http://{}/app/rest/testOccurrences?locator=build:{},status:FAILURE".format(args.teamcityUrl, args.buildId)
test_failures_request = requests.get(test_failures_request_string, auth=(args.teamcityUser, args.teamcityPassword), headers={'Accept':'application/json'})
if test_failures_request.status_code != 200:
return createTableRow(traffic_light.format(color="black"), "Test status: unable to retrieve status of tests")
else:
test_failures_json = test_failures_request.json()
# nowadays the responds doesn't contain count keyword when the build is successful
# while count word can be found when build fails
if "count" not in test_failures_json:
return createTableRow(traffic_light.format(color="green"), "Test status: all tests passing")
else:
return createTableRow(traffic_light.format(color="red"), "Test status: there are " + str(test_failures_json["count"]) + " failing tests, check the build report".format(buildResultUrl))
def getApiDiffHtml():
apidiff_html = "Check API diff"
modules = [
"client", "client-compiler",
"compatibility-client",
"compatibility-server",
"compatibility-server-gae",
"compatibility-shared",
"liferay-integration",
"osgi-integration",
"server", "shared"
]
link_list = list(map(lambda module: "{}".format(args.teamcityUrl, args.buildTypeId, args.buildId, module, module), modules))
return apidiff_html + getHtmlList(link_list)
def getDirs(url):
page = requests.get(url)
files = re.findall('(.*)', page.text)
dirs = filter(lambda x: x.endswith('/'), files)
return list(map(lambda x: x.replace('/', ''), dirs))
def dirTree(url):
dirs = getDirs(url)
result = []
for d in dirs:
result.append(d)
subDirs = list(map(lambda x: d + '/' + x, dirTree(url + '/' + d)))
result.extend(subDirs)
return result
def getAllowedArtifactPaths(allowedArtifacts):
result = []
for artifact in allowedArtifacts:
parts = artifact.split('/', 1)
result.append(parts[0])
if len(parts) > 1:
subart = getAllowedArtifactPaths([ parts[1] ])
subArtifacts = list(map(lambda x: parts[0] + '/' + x, subart))
result.extend(subArtifacts)
return result
def checkStagingContents(url, allowedArtifacts):
dirs = dirTree(url)
allowedDirs = getAllowedArtifactPaths(allowedArtifacts)
return set(dirs) == set(allowedDirs)
def getStagingContentsHtml(repoUrl, allowedArtifacts):
if checkStagingContents(repoUrl, allowedArtifacts):
return createTableRow(traffic_light.format(color="green"), "Expected artifacts found in the staging repository. Link to the repository.".format(repoUrl))
else:
return createTableRow(traffic_light.format(color="red"), "Extraneous or missing artifacts in the staging repository. Link to the repository.".format(repoUrl))
def completeArtifactName(artifactId, version):
return 'com/vaadin/' + artifactId + '/' + version
def completeArtifactNames(artifactIds, version):
return list(map(lambda x: completeArtifactName(x, version), artifactIds))
allowedArtifacts = completeArtifactNames([ 'vaadin-maven-plugin', 'vaadin-archetypes', 'vaadin-archetype-application', 'vaadin-archetype-application-multimodule', 'vaadin-archetype-application-example', 'vaadin-archetype-widget', 'vaadin-archetype-liferay-portlet', 'vaadin-root', 'vaadin-shared', 'vaadin-server', 'vaadin-client', 'vaadin-client-compiler', 'vaadin-client-compiled', 'vaadin-push', 'vaadin-themes', 'vaadin-compatibility-shared', 'vaadin-compatibility-server', "vaadin-compatibility-server-gae", 'vaadin-compatibility-client', 'vaadin-compatibility-client-compiled', 'vaadin-compatibility-themes', 'vaadin-liferay-integration', "vaadin-osgi-integration", 'vaadin-testbench-api', 'vaadin-bom' ], args.version)
content = "
" % (missing))
except subprocess.CalledProcessError as e:
if e.returncode == 1:
content += createTableRow(traffic_light.format(color="green"), "No empty @since")
else:
raise e
# check staging repositories don't contain extra artifacts
content += getStagingContentsHtml(args.stagingRepoUrl, allowedArtifacts)
content += createTableRow("", "
Manual checks before publishing
")
content += createTableRow("", "If changing between branches or phases (stable, maintenance, alpha, beta, rc), check the phase change checklist")
# link to release notes
content += createTableRow("", "Check release notes".format(args.teamcityUrl, args.buildTypeId, args.buildId))
# link to api diff
content += createTableRow("", getApiDiffHtml())
# check that GitHub issues are in the correct status
content += createTableRow("", "Check that closed GitHub issues have correct milestone")
content += createTableRow("", "Check demos from docker image: