Update Jenkins script to use python-jenkins

This commit is contained in:
Raoul Snyman 2017-10-26 13:33:22 -07:00
parent d34918a5e2
commit 93e0a35489
1 changed files with 62 additions and 56 deletions

View File

@ -31,25 +31,16 @@ You probably want to create an alias. Add this to your ~/.bashrc file and then l
You can look up the token in the Branch-01-Pull job configuration or ask in IRC. You can look up the token in the Branch-01-Pull job configuration or ask in IRC.
""" """
import os
import re import re
import sys
import time import time
from optparse import OptionParser from argparse import ArgumentParser
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
import warnings
from requests.exceptions import HTTPError
from jenkins import Jenkins from jenkins import Jenkins
JENKINS_URL = 'https://ci.openlp.io/' JENKINS_URL = 'https://ci.openlp.io/'
REPO_REGEX = r'(.*/+)(~.*)' REPO_REGEX = r'(.*/+)(~.*)'
# Allows us to black list token. So when we change the token, we can display a proper message to the user.
OLD_TOKENS = []
# Disable the InsecureRequestWarning we get from urllib3, because we're not verifying our own self-signed certificate
warnings.simplefilter('ignore')
class OpenLPJobs(object): class OpenLPJobs(object):
@ -85,13 +76,22 @@ class JenkinsTrigger(object):
:param token: The token we need to trigger the build. If you do not have this token, ask in IRC. :param token: The token we need to trigger the build. If you do not have this token, ask in IRC.
""" """
def __init__(self, token): def __init__(self, username, password, can_use_colour):
""" """
Create the JenkinsTrigger instance. Create the JenkinsTrigger instance.
""" """
self.token = token self.build_numbers = {}
self.can_use_colour = can_use_colour and not os.name.startswith('nt')
self.repo_name = get_repo_name() self.repo_name = get_repo_name()
self.jenkins_instance = Jenkins(JENKINS_URL) self.server = Jenkins(JENKINS_URL, username=username, password=password)
def fetch_build_numbers(self):
"""
Get the next build number from all the jobs
"""
for job_name in OpenLPJobs.Jobs:
job_info = self.server.get_job_info(job_name)
self.build_number[job_name] = job_info['nextBuildNumber']
def trigger_build(self): def trigger_build(self):
""" """
@ -102,8 +102,7 @@ class JenkinsTrigger(object):
# We just want the name (not the email). # We just want the name (not the email).
name = ' '.join(raw_output.decode().split()[:-1]) name = ' '.join(raw_output.decode().split()[:-1])
cause = 'Build triggered by %s (%s)' % (name, self.repo_name) cause = 'Build triggered by %s (%s)' % (name, self.repo_name)
self.jenkins_instance.job(OpenLPJobs.Branch_Pull).build({'BRANCH_NAME': self.repo_name, 'cause': cause}, self.server.build_job(OpenLPJobs.Branch_Pull, {'BRANCH_NAME': self.repo_name, 'cause': cause})
token=self.token)
def print_output(self): def print_output(self):
""" """
@ -129,6 +128,20 @@ class JenkinsTrigger(object):
# Open the url # Open the url
Popen(('xdg-open', url), stderr=PIPE) Popen(('xdg-open', url), stderr=PIPE)
def _get_build_info(self, job_name, build_number):
"""
Get the build info from the server. This method will check the queue and wait for the build.
"""
queue_info = self.server.get_queue_info()
tries = 0
while queue_info and tries < 50:
tries += 1
time.sleep(0.5)
queue_info = self.server.get_queue_info()
if tries >= 50:
raise Exception('Build has not started yet, it may be stuck in the queue.')
return self.server.get_build_info(job_name, build_number)
def __print_build_info(self, job_name): def __print_build_info(self, job_name):
""" """
This helper method prints the job information of the given ``job_name`` This helper method prints the job information of the given ``job_name``
@ -136,21 +149,21 @@ class JenkinsTrigger(object):
:param job_name: The name of the job we want the information from. For example *Branch-01-Pull*. Use the class :param job_name: The name of the job we want the information from. For example *Branch-01-Pull*. Use the class
variables from the :class:`OpenLPJobs` class. variables from the :class:`OpenLPJobs` class.
""" """
build_info = self._get_build_info(job_name, self.build_number[job_name])
print('{} ... '.format(build_info['url']), end='', flush=True)
is_success = False is_success = False
job = self.jenkins_instance.job(job_name) while build_info['building'] is True:
while job.info['inQueue']: time.sleep(0.5)
time.sleep(1) build_info = self.server.get_build_info(job_name, self.build_number[job_name])
build = job.last_build result_string = build_info['result']
build.wait() if self.can_use_colour and result_string == 'SUCCESS':
if build.info['result'] == 'SUCCESS':
# Make 'SUCCESS' green. # Make 'SUCCESS' green.
result_string = '%s%s%s' % (Colour.GREEN_START, build.info['result'], Colour.GREEN_END) result_string = '%s%s%s' % (Colour.GREEN_START, result_string, Colour.GREEN_END)
is_success = True is_success = True
else: elif self.can_use_colour:
# Make 'FAILURE' red. # Make 'FAILURE' red.
result_string = '%s%s%s' % (Colour.RED_START, build.info['result'], Colour.RED_END) result_string = '%s%s%s' % (Colour.RED_START, result_string, Colour.RED_END)
url = build.info['url'] print('[{}]'.format(result_string))
print('[%s] %s' % (result_string, url))
return is_success return is_success
@ -186,36 +199,29 @@ def get_repo_name():
def main(): def main():
usage = 'Usage: python %prog TOKEN [options]' """
Run the script
"""
parser = ArgumentParser()
parser.add_argument('-d', '--disable-output', action='store_false', default=True, help='Disable output')
parser.add_argument('-b', '--open-browser', action='store_true', default=False,
help='Opens the jenkins page in your browser')
parser.add_argument('-c', '--enable-colour', action='store_false', default=True,
help='Enable coloured output. Disabled on Windows')
parser.add_argument('-u', '--username', required=True, help='Your Jenkins username')
parser.add_argument('-p', '--password', required=True, help='Your Jenkins password or personal token')
args = parser.parse_args()
parser = OptionParser(usage=usage)
parser.add_option('-d', '--disable-output', dest='enable_output', action='store_false', default=True,
help='Disable output.')
parser.add_option('-b', '--open-browser', dest='open_browser', action='store_true', default=False,
help='Opens the jenkins page in your browser.')
options, args = parser.parse_args(sys.argv)
if len(args) == 2:
if not get_repo_name(): if not get_repo_name():
print('Not a branch. Have you pushed it to launchpad? Did you cd to the branch?') print('Not a branch. Have you pushed it to launchpad? Did you cd to the branch?')
return return
token = args[-1] jenkins_trigger = JenkinsTrigger(username=args.username, password=args.password)
if token in OLD_TOKENS:
print('Your token is not valid anymore. Get the most recent one.')
return
jenkins_trigger = JenkinsTrigger(token)
try:
jenkins_trigger.trigger_build() jenkins_trigger.trigger_build()
except HTTPError:
print('Wrong token.')
return
# Open the browser before printing the output. # Open the browser before printing the output.
if options.open_browser: if args.open_browser:
jenkins_trigger.open_browser() jenkins_trigger.open_browser()
if options.enable_output: if not args.disable_output:
jenkins_trigger.print_output() jenkins_trigger.print_output()
else:
parser.print_help()
if __name__ == '__main__': if __name__ == '__main__':