Adding hipchat notification capability.
Tweaks the Builder and YamlParser classes to accept a config object which is passed to the parser's ModuleRegistry object. This makes it available to the HipChat object. Change-Id: I3017658336b949c0fda7c82945e7014dbcf6e152 Reviewed-on: https://review.openstack.org/12794 Reviewed-by: James E. Blair <corvus@inaugust.com> Reviewed-by: Clark Boylan <clark.boylan@gmail.com> Approved: James E. Blair <corvus@inaugust.com> Tested-by: Jenkins
This commit is contained in:
parent
b6af0f0060
commit
5465ab6d4f
|
@ -184,6 +184,7 @@ The bulk of the job definitions come from the following modules.
|
||||||
project_maven
|
project_maven
|
||||||
general
|
general
|
||||||
builders
|
builders
|
||||||
|
hipchat
|
||||||
notifications
|
notifications
|
||||||
parameters
|
parameters
|
||||||
properties
|
properties
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
.. _hipchat:
|
||||||
|
|
||||||
|
Hipchat
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. automodule:: hipchat_notif
|
||||||
|
:members:
|
|
@ -45,7 +45,8 @@ def main():
|
||||||
logger.debug("Config: {0}".format(config))
|
logger.debug("Config: {0}".format(config))
|
||||||
builder = jenkins_jobs.builder.Builder(config.get('jenkins', 'url'),
|
builder = jenkins_jobs.builder.Builder(config.get('jenkins', 'url'),
|
||||||
config.get('jenkins', 'user'),
|
config.get('jenkins', 'user'),
|
||||||
config.get('jenkins', 'password'))
|
config.get('jenkins', 'password'),
|
||||||
|
config)
|
||||||
|
|
||||||
if options.command == 'delete':
|
if options.command == 'delete':
|
||||||
for job in options.name:
|
for job in options.name:
|
||||||
|
|
|
@ -29,8 +29,8 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class YamlParser(object):
|
class YamlParser(object):
|
||||||
def __init__(self):
|
def __init__(self, config=None):
|
||||||
self.registry = ModuleRegistry()
|
self.registry = ModuleRegistry(config)
|
||||||
self.data = {}
|
self.data = {}
|
||||||
self.jobs = []
|
self.jobs = []
|
||||||
|
|
||||||
|
@ -150,9 +150,10 @@ class YamlParser(object):
|
||||||
|
|
||||||
|
|
||||||
class ModuleRegistry(object):
|
class ModuleRegistry(object):
|
||||||
def __init__(self):
|
def __init__(self, config):
|
||||||
self.modules = []
|
self.modules = []
|
||||||
self.handlers = {}
|
self.handlers = {}
|
||||||
|
self.global_config = config
|
||||||
|
|
||||||
for entrypoint in pkg_resources.iter_entry_points(
|
for entrypoint in pkg_resources.iter_entry_points(
|
||||||
group='jenkins_jobs.modules'):
|
group='jenkins_jobs.modules'):
|
||||||
|
@ -242,9 +243,11 @@ class Jenkins(object):
|
||||||
|
|
||||||
|
|
||||||
class Builder(object):
|
class Builder(object):
|
||||||
def __init__(self, jenkins_url, jenkins_user, jenkins_password):
|
def __init__(self, jenkins_url, jenkins_user, jenkins_password,
|
||||||
|
config=None):
|
||||||
self.jenkins = Jenkins(jenkins_url, jenkins_user, jenkins_password)
|
self.jenkins = Jenkins(jenkins_url, jenkins_user, jenkins_password)
|
||||||
self.cache = CacheStorage()
|
self.cache = CacheStorage()
|
||||||
|
self.global_config = config
|
||||||
|
|
||||||
def delete_job(self, name):
|
def delete_job(self, name):
|
||||||
self.jenkins.delete_job(name)
|
self.jenkins.delete_job(name)
|
||||||
|
@ -258,7 +261,7 @@ class Builder(object):
|
||||||
if (f.endswith('.yml') or f.endswith('.yaml'))]
|
if (f.endswith('.yml') or f.endswith('.yaml'))]
|
||||||
else:
|
else:
|
||||||
files_to_process = [fn]
|
files_to_process = [fn]
|
||||||
parser = YamlParser()
|
parser = YamlParser(self.global_config)
|
||||||
for in_file in files_to_process:
|
for in_file in files_to_process:
|
||||||
logger.debug("Parsing YAML file {0}".format(in_file))
|
logger.debug("Parsing YAML file {0}".format(in_file))
|
||||||
parser.parse(in_file)
|
parser.parse(in_file)
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
# Copyright 2012 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Licensed 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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Enable hipchat notification of build execution.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
- job:
|
||||||
|
name: test_job
|
||||||
|
hipchat:
|
||||||
|
enabled: true
|
||||||
|
room: Testjob Build Notifications
|
||||||
|
start-notify: true
|
||||||
|
|
||||||
|
In the jenkins UI specification, the hipchat plugin must be explicitly
|
||||||
|
selected as a publisher. This is not required (or supported) here - use the
|
||||||
|
``enabled`` parameter to enable/disable the publisher action.
|
||||||
|
If you set ``enabled: false``, no hipchat parameters are written to XML.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Enabling hipchat notifications on a job requires specifying the hipchat
|
||||||
|
# config in job properties, and adding the hipchat notifier to the job's
|
||||||
|
# publishers list.
|
||||||
|
# The publisher configuration contains extra details not specified per job:
|
||||||
|
# - the hipchat authorisation token.
|
||||||
|
# - the jenkins server url.
|
||||||
|
# - a default room name/id.
|
||||||
|
# This complicates matters somewhat since the sensible place to store these
|
||||||
|
# details is in the global config file.
|
||||||
|
# The global config object is therefore passed down to the registry object,
|
||||||
|
# and this object is passed to the HipChat() class initialiser.
|
||||||
|
|
||||||
|
import xml.etree.ElementTree as XML
|
||||||
|
import jenkins_jobs.modules.base
|
||||||
|
import jenkins_jobs.errors
|
||||||
|
import logging
|
||||||
|
import ConfigParser
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class HipChat(jenkins_jobs.modules.base.Base):
|
||||||
|
sequence = 80
|
||||||
|
|
||||||
|
def __init__(self, registry):
|
||||||
|
self.authToken = None
|
||||||
|
self.jenkinsUrl = None
|
||||||
|
self.registry = registry
|
||||||
|
|
||||||
|
def _load_global_data(self):
|
||||||
|
"""Load data from the global config object.
|
||||||
|
This is done lazily to avoid looking up the '[hipchat]' section
|
||||||
|
unless actually required.
|
||||||
|
"""
|
||||||
|
if(not self.authToken):
|
||||||
|
# Verify that the config object in the registry is of type
|
||||||
|
# ConfigParser (it could possibly be a regular 'dict' object which
|
||||||
|
# doesn't have the right get() method).
|
||||||
|
if(not isinstance(self.registry.global_config,
|
||||||
|
ConfigParser.ConfigParser)):
|
||||||
|
raise jenkins_jobs.errors.JenkinsJobsException(
|
||||||
|
'HipChat requires a config object in the registry.')
|
||||||
|
self.authToken = self.registry.global_config.get(
|
||||||
|
'hipchat', 'authtoken')
|
||||||
|
self.jenkinsUrl = self.registry.global_config.get('jenkins', 'url')
|
||||||
|
|
||||||
|
def gen_xml(self, parser, xml_parent, data):
|
||||||
|
hipchat = data.get('hipchat')
|
||||||
|
if not hipchat or not hipchat.get('enabled', True):
|
||||||
|
return
|
||||||
|
if('room' not in hipchat):
|
||||||
|
raise jenkins_jobs.errors.YAMLFormatError(
|
||||||
|
"Missing hipchat 'room' specifier")
|
||||||
|
self._load_global_data()
|
||||||
|
|
||||||
|
properties = xml_parent.find('properties')
|
||||||
|
if properties is None:
|
||||||
|
properties = XML.SubElement(xml_parent, 'properties')
|
||||||
|
pdefhip = XML.SubElement(properties,
|
||||||
|
'jenkins.plugins.hipchat.HipChatNotifier_-HipChatJobProperty')
|
||||||
|
XML.SubElement(pdefhip, 'room').text = hipchat['room']
|
||||||
|
XML.SubElement(pdefhip, 'startNotification').text = str(
|
||||||
|
hipchat.get('start-notify', 'false')).lower()
|
||||||
|
|
||||||
|
publishers = xml_parent.find('publishers')
|
||||||
|
if publishers is None:
|
||||||
|
publishers = XML.SubElement(xml_parent, 'publishers')
|
||||||
|
hippub = XML.SubElement(publishers,
|
||||||
|
'jenkins.plugins.hipchat.HipChatNotifier')
|
||||||
|
XML.SubElement(hippub, 'jenkinsUrl').text = self.jenkinsUrl
|
||||||
|
XML.SubElement(hippub, 'authToken').text = self.authToken
|
||||||
|
# The room specified here is the default room. The default is
|
||||||
|
# redundant in this case since a room must be specified. Leave empty.
|
||||||
|
XML.SubElement(hippub, 'room').text = ''
|
1
setup.py
1
setup.py
|
@ -95,6 +95,7 @@ setup(name='jenkins_job_builder',
|
||||||
'triggers=jenkins_jobs.modules.triggers:Triggers',
|
'triggers=jenkins_jobs.modules.triggers:Triggers',
|
||||||
'wrappers=jenkins_jobs.modules.wrappers:Wrappers',
|
'wrappers=jenkins_jobs.modules.wrappers:Wrappers',
|
||||||
'zuul=jenkins_jobs.modules.zuul:Zuul',
|
'zuul=jenkins_jobs.modules.zuul:Zuul',
|
||||||
|
'hipchat=jenkins_jobs.modules.hipchat_notif:HipChat',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue