This notebook should be used to update the Jenkins configuration for the Menpo project en-masse. It works by completing three template projects with the state that changes between projects - namely, the name of the project (and hence the github URL) and the Python versions that need to be built.
In [ ]:
# set your jenkins credentials here - and do not commit them!!
USERNAME = 'USER'
PASSWORD = 'PASS'
In [ ]:
from functools import partial
from subprocess import check_output, Popen, PIPE, STDOUT, CalledProcessError
from utils import PROJECTS, download_file
# downlad the CLI file for use
download_file('https://jenkins.menpo.org/jnlpJars/jenkins-cli.jar', 'jenkins-cli.jar')
T_OFF = '<disabled>true</disabled>'
T_ON = '<disabled>false</disabled>'
T_VERSIONS = '<string>@PYTHON_VERSIONS@</string>\n'
T_NAME = '@PROJECT_NAME@'
VERSION_TO_STR = {k: '<string>{}</string>\n '.format(v) for k, v in
{2: '2.7', 34: '3.4', 35: '3.5'}.items()}
JENKINS_CMD = ['java', '-jar', 'jenkins-cli.jar',
'-noKeyAuth', '-noCertificateCheck',
'-s', 'https://jenkins.menpo.org']
AUTH = [
'--username', USERNAME,
'--password', PASSWORD
]
cmd_for_args = lambda args: JENKINS_CMD + list(args) + AUTH
def jcall(*args, **kwargs):
verbose = kwargs.get('verbose', False)
cmd = cmd_for_args(args)
if verbose:
print(' '.join(cmd))
try:
output = check_output(cmd).decode()
return output.split('Skipping HTTPS certificate checks altogether. Note that this is not secure at all.\n')[-1]
except CalledProcessError as e:
print(e.returncode)
print(e.output)
def jinput(stdin, cmd):
p = Popen(cmd_for_args(cmd), stdout=PIPE, stdin=PIPE, stderr=STDOUT)
try:
return p.communicate(input=stdin.encode())[0].decode()
except CalledProcessError as e:
print(e.returncode)
print(e.output)
def fill_template(t, name, versions):
return t.replace(T_NAME, name).replace(T_VERSIONS, versions).replace(T_OFF, T_ON)
get_job = partial(jcall, 'get-job')
create_job = lambda name, job: jinput(job, ['create-job', name])
update_job = lambda name, job: jinput(job, ['update-job', name])
delete_job = lambda name: jcall('delete-job', name)
In [ ]:
# Check we are successfully logged in:
print(jcall('who-am-i'))
In [ ]:
print('loading templates...')
def load_text(name):
with open(name, 'rt') as f:
content = f.read()
return content
T, T_PR = (load_text('./jenkins/templates/TEMPLATE.xml'),
load_text('./jenkins/templates/TEMPLATE-pr.xml'))
SUFFIX_TO_TEMPLATE = { '': T, '-pr': T_PR }
print('done.')
print('acquiring current jobs...')
JOBS = set(x for x in jcall('list-jobs').split('\n') if not x == '')
print('done.')
In [ ]:
non_pr_jobs = {j for j in JOBS if not j.endswith('-pr')}
known_jobs = {p.name for p in PROJECTS}
extra_jobs = non_pr_jobs - known_jobs - { 'TEMPLATE' }
if len(extra_jobs) != 0:
print(extra_jobs)
raise ValueError("Warning - a Jenkins jobs is present that isn't managed")
In [ ]:
for p in PROJECTS:
versions = ' '.join([VERSION_TO_STR[v] for v in p.versions])
for suffix, template in SUFFIX_TO_TEMPLATE.items():
job = fill_template(template, p.name, versions)
job_name = p.name + suffix
if job_name in JOBS:
print('{} already exists, updating.'.format(job_name))
update_job(job_name, job)
else:
print('creating job: {}'.format(job_name))
create_job(job_name, job)