blob: 15701898aa9f9ad7b04bf25f079f6dfa1eaae5d5 [file] [log] [blame]
#!/usr/bin/python
# 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.
import json
import subprocess
import os
import shutil
from tempfile import mkdtemp
ALL_BUILD_OPTIONS_JOB = "all-build-options-ub1604"
JENKINS_IMPALA_IO = "jenkins.impala.io"
M2_ARCHIVE_NAME = "m2_archive.tar.gz"
class JenkinsBuild(object):
"""
Basic information about a Jenkins build (number, url) to allow retrieving
more detailed information.
"""
def __init__(self, number, url):
self.number = number
self.url = url
class JenkinsBuildDetails(object):
"""
Detailed information about the parameters and artifacts for a particular
Jenkins build.
"""
def __init__(self, parameter_dict, artifact_dict):
self.parameter_dict = parameter_dict
self.artifact_dict = artifact_dict
def get_build_list(jenkins_server, job):
"""
Get the list of recent builds for the specified job on the jenkins server.
This returns a list of JenkinsBuild objects containing the build numbers
and corresponding urls.
"""
# Make a temporary directory
tmpdir = mkdtemp()
json_dict = {}
try:
# This uses Jenkin's JSON API to get the list of build numbers for this job
# along with the URL to each build. This downloads the JSON to a temporary file
# and reads it back. This uses wget to avoid any python dependencies.
json_url_tmpl = "https://{0}/job/{1}/api/json?tree=builds[number,url]&pretty=true"
json_url = json_url_tmpl.format(jenkins_server, job)
json_filename = os.path.join(tmpdir, "job_{0}_build_list.json".format(job))
subprocess.check_call(["wget", "-q", json_url, "-O", json_filename])
# Open the JSON file
with open(json_filename) as f:
json_dict = json.load(f)
finally:
# Cleanup temporary directory
shutil.rmtree(tmpdir)
# Convert the JSON dictionaries to JenkinsBuild objects
builds = []
for build_info in json_dict["builds"]:
builds.append(JenkinsBuild(build_info["number"], build_info["url"]))
return builds
def get_build_details(build):
"""
Download detailed build information for the build number at the provided URL using
the Jenkins JSON API. This returns a JenkinsBuildDetails, which includes information
about the parameters of the Jenkins job and the artifacts produced by the Jenkins job.
"""
tmpdir = mkdtemp()
json_dict = {}
try:
# This downloads a json job to the temporary directory
json_url = "{0}/api/json?&pretty=true".format(build.url)
json_filename = os.path.join(tmpdir, "build_details_{0}.json".format(build.number))
subprocess.check_call(["wget", "-q", json_url, "-O", json_filename])
# Parse the JSON file
json_dict = {}
with open(json_filename) as f:
json_dict = json.load(f)
finally:
shutil.rmtree(tmpdir)
# Convert the JSON dictionaries to a JenkinsBuildDetail object
parameter_dict = {}
parameter_section = None
for section in json_dict["actions"]:
if "parameters" in section:
parameter_section = section["parameters"]
break
for parameter in parameter_section:
parameter_dict[parameter["name"]] = parameter["value"]
artifact_dict = {}
for artifact in json_dict["artifacts"]:
artifact_url = "{0}/artifact/{1}".format(build.url, artifact["relativePath"])
artifact_dict[artifact["fileName"]] = artifact_url
return JenkinsBuildDetails(parameter_dict, artifact_dict)
def get_m2_archive_url(jenkins_server, jenkins_job):
# Get the JSON list of builds for the all-build-options-ub1604 job. This code
# is specific to how the Jenkins job is structured (i.e. parameters, archives),
# so this is not generic.
build_list = get_build_list(jenkins_server, jenkins_job)
for build in build_list:
# Go get more detailed information about the job
build_details = get_build_details(build)
# There are two criteria for a valid m2 archive:
# 1. The build is based on the master branch
# 2. The build has the appropriate m2 archive artifact
is_master_build = "IMPALA_REPO_BRANCH" in build_details.parameter_dict and \
build_details.parameter_dict["IMPALA_REPO_BRANCH"] == "master"
has_m2_archive = M2_ARCHIVE_NAME in build_details.artifact_dict
if is_master_build and has_m2_archive:
return build_details.artifact_dict[M2_ARCHIVE_NAME]
return None
def download_and_unpack_m2_archive(url, directory):
print("Downloading m2 archive from {0} to {1}".format(url, directory))
tarball_name = os.path.basename(url)
tmp_tarball_location = os.path.join(directory, tarball_name)
subprocess.check_call(["wget", "-q", url, "-O", tmp_tarball_location])
m2_directory = os.path.expanduser("~/.m2")
if not os.path.exists(m2_directory):
print("{0} does not exist, creating...".format(m2_directory))
os.makedirs(m2_directory)
print("Unpacking {0} to {1}".format(tarball_name, m2_directory))
tar_command = ["tar", "-zxf", tmp_tarball_location]
# Unpack into m2 directory, but don't overwrite any files
tar_command.extend(["-C", m2_directory, "--skip-old-files"])
subprocess.check_call(tar_command)
def main():
m2_archive_url = get_m2_archive_url(JENKINS_IMPALA_IO, ALL_BUILD_OPTIONS_JOB)
if not m2_archive_url:
print("Could not find any m2 archive for {0} {1}".format(JENKINS_IMPALA_IO,
ALL_BUILD_OPTIONS_JOB))
tmpdir = mkdtemp()
try:
download_and_unpack_m2_archive(m2_archive_url, tmpdir)
finally:
shutil.rmtree(tmpdir)
if __name__ == "__main__":
main()