251 lines
7.5 KiB
Python
251 lines
7.5 KiB
Python
"""
|
|
Manage jenkins jobs
|
|
|
|
Prerequisites:
|
|
The jenkinsapi module is required https://pypi.python.org/pypi/jenkinsapi
|
|
To install the module using pip:
|
|
sudo pip install jenkinsapi
|
|
|
|
The plugin polls the jenkins server at 'jenkins_url' every 'poll_interval' seconds.
|
|
New failures are reported in the console, and a desktop notification is sent.
|
|
|
|
The following commands are available:
|
|
|
|
/jenkins jobs - list all jobs
|
|
/jenkins show [job] - show details of a specific job
|
|
/jenkins build [job] - trigger a build for the job
|
|
/jenkins open [job] - open the job in the systems default browser
|
|
|
|
"""
|
|
|
|
import prof
|
|
import os
|
|
import webbrowser
|
|
import jenkinsapi
|
|
from jenkinsapi.jenkins import Jenkins
|
|
|
|
win_tag = "Jenkins"
|
|
poll_interval = 10
|
|
remind_interval = 20
|
|
jenkins_url = "http://localhost:8080"
|
|
username = None
|
|
password = None
|
|
|
|
failing = []
|
|
passing = []
|
|
|
|
def _show_help():
|
|
global win_tag
|
|
|
|
prof.win_show(win_tag, "Commands:")
|
|
prof.win_show(win_tag, " /jenkins help - Show this help")
|
|
prof.win_show(win_tag, " /jenkins list - List all jobs")
|
|
prof.win_show(win_tag, " /jenkins show [job] - Details of specific job")
|
|
prof.win_show(win_tag, " /jenkins build [job] - Trigger build for job")
|
|
prof.win_show(win_tag, " /jenkins open [job] - Open job in browser")
|
|
prof.win_show(win_tag, "")
|
|
|
|
def _open_job_url(url):
|
|
savout = os.dup(1)
|
|
saverr = os.dup(2)
|
|
os.close(1)
|
|
os.close(2)
|
|
os.open(os.devnull, os.O_RDWR)
|
|
try:
|
|
webbrowser.open(url, new=2)
|
|
finally:
|
|
os.dup2(savout, 1)
|
|
os.dup2(saverr, 2)
|
|
|
|
def _list_jobs(j):
|
|
global win_tag
|
|
|
|
if len(j.keys()) == 0:
|
|
prof.win_show(win_tag, "No jobs available")
|
|
prof.win_show(win_tag, "")
|
|
else:
|
|
prof.win_show(win_tag, "Jobs:")
|
|
for name, job in j.get_jobs():
|
|
if job.is_queued():
|
|
prof.win_show(win_tag, " " + name + ", QUEUED")
|
|
elif job.is_running():
|
|
prof.win_show(win_tag, " " + name + ", RUNNING")
|
|
else:
|
|
build = job.get_last_build_or_none()
|
|
if build:
|
|
prof.win_show(win_tag, " " + name + " #" + str(build.get_number()) + ", " + build.get_status())
|
|
else:
|
|
prof.win_show(win_tag, " " + name + ", no builds")
|
|
prof.win_show(win_tag, "")
|
|
|
|
def _show_job(j, jobname=None):
|
|
global win_tag
|
|
|
|
if not jobname:
|
|
prof.win_show(win_tag, "Usage: show [job]")
|
|
prof.win_show(win_tag, "")
|
|
else:
|
|
if j.has_job(jobname):
|
|
job = j.get_job(jobname)
|
|
prof.win_show(win_tag, jobname + " details:");
|
|
|
|
desc = job.get_description()
|
|
if desc:
|
|
prof.win_show (win_tag, " Description : " + desc)
|
|
|
|
if job.is_queued():
|
|
prof.win_show (win_tag, " Status : Queued")
|
|
elif job.is_running():
|
|
prof.win_show (win_tag, " Status : Running")
|
|
else:
|
|
build = job.get_last_build_or_none()
|
|
if build:
|
|
prof.win_show (win_tag, " Last build : #" + str(build.get_number()))
|
|
prof.win_show (win_tag, " Status : " + build.get_status())
|
|
else:
|
|
prof.win_show (win_tag, " Last build : No builds")
|
|
|
|
prof.win_show (win_tag, " Trigger : " + job.get_build_triggerurl())
|
|
prof.win_show(win_tag, "")
|
|
else:
|
|
prof.win_show(win_tag, "No such job " + jobname)
|
|
prof.win_show(win_tag, "")
|
|
|
|
def _build_job(j, jobname):
|
|
global win_tag
|
|
|
|
if not jobname:
|
|
prof.win_show(win_tag, "Usage: build [job]")
|
|
prof.win_show(win_tag, "")
|
|
else:
|
|
if j.has_job(jobname):
|
|
job = j.get_job(jobname)
|
|
try:
|
|
job.invoke(invoke_pre_check_delay=1)
|
|
except Exception, e:
|
|
prof.win_show(win_tag, "Failed to trigger build: " + str(e))
|
|
prof.win_show(win_tag, "")
|
|
else:
|
|
prof.win_show(win_tag, "No such job " + jobname)
|
|
prof.win_show(win_tag, "")
|
|
|
|
def _open_job(j, jobname):
|
|
global win_tag
|
|
|
|
if not jobname:
|
|
prof.win_show(win_tag, "Usage: open [job]")
|
|
prof.win_show(win_tag, "")
|
|
else:
|
|
if j.has_job(jobname):
|
|
_open_job_url(jenkins_url + "/job/" + jobname)
|
|
else:
|
|
prof.win_show(win_tag, "No such job " + jobname)
|
|
prof.win_show(win_tag, "")
|
|
|
|
def _process_job(name, job):
|
|
global failing
|
|
global passing
|
|
global win_tag
|
|
|
|
if not job.is_queued_or_running():
|
|
build = job.get_last_build_or_none()
|
|
if build:
|
|
if build.get_status() == "FAILURE":
|
|
if not name in failing:
|
|
prof.win_show(win_tag, name + " #" + str(build.get_number()) + " BROKEN")
|
|
prof.win_show(win_tag, "")
|
|
prof.notify(name + " BROKEN", 5000, "Jenkins")
|
|
failing.append(name)
|
|
if name in passing:
|
|
passing.remove(name)
|
|
else:
|
|
if name in failing:
|
|
prof.win_show(win_tag, name + " #" + str(build.get_number()) + " FIXED")
|
|
prof.win_show(win_tag, "")
|
|
prof.notify(name + " FIXED", 5000, "Jenkins")
|
|
failing.remove(name)
|
|
if not name in passing:
|
|
passing.append(name)
|
|
|
|
def _remind():
|
|
global failing
|
|
|
|
if len(failing) == 1:
|
|
prof.notify("1 broken build", 5000, "Jenkins")
|
|
if len(failing) > 1:
|
|
prof.notify(str(len(failing)) + " broken builds", 5000, "Jenkins")
|
|
|
|
def _poll_jobs():
|
|
global jenkins_url
|
|
global username
|
|
global password
|
|
global win_tag
|
|
|
|
try:
|
|
j = Jenkins(jenkins_url, username, password)
|
|
except Exception:
|
|
prof.win_show(win_tag, "Jenkins down")
|
|
prof.win_show(win_tag, "")
|
|
else:
|
|
for name, job in j.get_jobs():
|
|
_process_job(name, job)
|
|
|
|
def _cmd_jenkins(cmd=None, jobname=None):
|
|
global jenkins_url
|
|
global username
|
|
global password
|
|
global win_tag
|
|
|
|
if not prof.win_exists(win_tag):
|
|
prof.win_create(win_tag, _handle_input)
|
|
|
|
prof.win_focus(win_tag)
|
|
|
|
if not cmd:
|
|
_show_help()
|
|
else:
|
|
try:
|
|
j = Jenkins(jenkins_url, username, password)
|
|
except Exception:
|
|
prof.win_show(win_tag, "Jenkins down")
|
|
prof.win_show(win_tag, "")
|
|
else:
|
|
if cmd == "help":
|
|
_show_help()
|
|
elif cmd == "list":
|
|
_list_jobs(j)
|
|
elif cmd == "show":
|
|
_show_job(j, jobname)
|
|
elif cmd == "build":
|
|
_build_job(j, jobname)
|
|
elif cmd == "open":
|
|
_open_job(j, jobname)
|
|
else:
|
|
prof.win_show(win_tag, "Usage: list|show|build|open [job].")
|
|
prof.win_show(win_tag, "")
|
|
|
|
def prof_init(version, status):
|
|
global poll_interval
|
|
global win_tag
|
|
|
|
prof.register_timed(_poll_jobs, poll_interval)
|
|
prof.register_timed(_remind, remind_interval)
|
|
prof.register_command("/jenkins", 0, 2, "/jenkins list|show|build|open [job]", "Do jenkins stuff.", "Do jenkins stuff.",
|
|
_cmd_jenkins)
|
|
|
|
def _handle_input(win, line):
|
|
_show_help()
|
|
|
|
def prof_on_start():
|
|
global win_tag
|
|
|
|
prof.win_create(win_tag, _handle_input)
|
|
_show_help()
|
|
|
|
try:
|
|
j = Jenkins(jenkins_url, username, password)
|
|
except Exception:
|
|
prof.win_show(win_tag, "Jenkins down")
|
|
else:
|
|
_list_jobs(j)
|