596 lines
22 KiB
Python
596 lines
22 KiB
Python
# 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.
|
|
|
|
|
|
"""
|
|
Publishers define actions that the Jenkins job should perform after
|
|
the build is complete.
|
|
|
|
**Component**: publishers
|
|
:Macro: publisher
|
|
:Entry Point: jenkins_jobs.publishers
|
|
|
|
Example::
|
|
|
|
job:
|
|
name: test_job
|
|
|
|
publishers:
|
|
- scp:
|
|
site: 'example.com'
|
|
source: 'doc/build/html/**/*'
|
|
target_path: 'project'
|
|
"""
|
|
|
|
|
|
import xml.etree.ElementTree as XML
|
|
import jenkins_jobs.modules.base
|
|
import logging
|
|
|
|
|
|
def archive(parser, xml_parent, data):
|
|
"""yaml: archive
|
|
Archive build artifacts
|
|
|
|
:arg str artifacts: path specifier for artifacts to archive
|
|
:arg str excludes: path specifier for artifacts to exclude
|
|
:arg bool latest_only: only keep the artifacts from the latest
|
|
successful build
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- archive:
|
|
artifacts: *.tar.gz
|
|
"""
|
|
archiver = XML.SubElement(xml_parent, 'hudson.tasks.ArtifactArchiver')
|
|
artifacts = XML.SubElement(archiver, 'artifacts')
|
|
artifacts.text = data['artifacts']
|
|
if 'excludes' in data:
|
|
excludes = XML.SubElement(archiver, 'excludes')
|
|
excludes.text = data['excludes']
|
|
latest = XML.SubElement(archiver, 'latestOnly')
|
|
latest_only = data.get('latest_only', False)
|
|
if latest_only:
|
|
latest.text = 'true'
|
|
else:
|
|
latest.text = 'false'
|
|
|
|
|
|
def trigger_parameterized_builds(parser, xml_parent, data):
|
|
"""yaml: trigger-parameterized-builds
|
|
Trigger parameterized builds of other jobs.
|
|
Requires the Jenkins `Parameterized Trigger Plugin.
|
|
<https://wiki.jenkins-ci.org/display/JENKINS/
|
|
Parameterized+Trigger+Plugin>`_
|
|
|
|
:arg str project: name of the job to trigger
|
|
:arg str predefined-parameters: parameters to pass to the other
|
|
job (optional)
|
|
:arg str condition: when to trigger the other job (default 'ALWAYS')
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- trigger-parameterized-builds:
|
|
project: other_job
|
|
"""
|
|
tbuilder = XML.SubElement(xml_parent,
|
|
'hudson.plugins.parameterizedtrigger.BuildTrigger')
|
|
configs = XML.SubElement(tbuilder, 'configs')
|
|
for project_def in data:
|
|
tconfig = XML.SubElement(configs,
|
|
'hudson.plugins.parameterizedtrigger.BuildTriggerConfig')
|
|
tconfigs = XML.SubElement(tconfig, 'configs')
|
|
if 'predefined-parameters' in project_def:
|
|
params = XML.SubElement(tconfigs,
|
|
'hudson.plugins.parameterizedtrigger.PredefinedBuildParameters')
|
|
properties = XML.SubElement(params, 'properties')
|
|
properties.text = project_def['predefined-parameters']
|
|
else:
|
|
tconfigs.set('class', 'java.util.Collections$EmptyList')
|
|
projects = XML.SubElement(tconfig, 'projects')
|
|
projects.text = project_def['project']
|
|
condition = XML.SubElement(tconfig, 'condition')
|
|
condition.text = project_def.get('condition', 'ALWAYS')
|
|
trigger_with_no_params = XML.SubElement(tconfig,
|
|
'triggerWithNoParameters')
|
|
trigger_with_no_params.text = 'false'
|
|
|
|
|
|
def coverage(parser, xml_parent, data):
|
|
"""yaml: coverage
|
|
Generate a cobertura coverage report.
|
|
Requires the Jenkins `Cobertura Coverage Plugin.
|
|
<https://wiki.jenkins-ci.org/display/JENKINS/Cobertura+Plugin>`_
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- coverage
|
|
"""
|
|
cobertura = XML.SubElement(xml_parent,
|
|
'hudson.plugins.cobertura.CoberturaPublisher')
|
|
XML.SubElement(cobertura, 'coberturaReportFile').text = '**/coverage.xml'
|
|
XML.SubElement(cobertura, 'onlyStable').text = 'false'
|
|
healthy = XML.SubElement(cobertura, 'healthyTarget')
|
|
targets = XML.SubElement(healthy, 'targets', {
|
|
'class': 'enum-map',
|
|
'enum-type': 'hudson.plugins.cobertura.targets.CoverageMetric'})
|
|
entry = XML.SubElement(targets, 'entry')
|
|
XML.SubElement(entry, 'hudson.plugins.cobertura.targets.CoverageMetric'
|
|
).text = 'CONDITIONAL'
|
|
XML.SubElement(entry, 'int').text = '70'
|
|
entry = XML.SubElement(targets, 'entry')
|
|
XML.SubElement(entry, 'hudson.plugins.cobertura.targets.CoverageMetric'
|
|
).text = 'LINE'
|
|
XML.SubElement(entry, 'int').text = '80'
|
|
entry = XML.SubElement(targets, 'entry')
|
|
XML.SubElement(entry, 'hudson.plugins.cobertura.targets.CoverageMetric'
|
|
).text = 'METHOD'
|
|
XML.SubElement(entry, 'int').text = '80'
|
|
unhealthy = XML.SubElement(cobertura, 'unhealthyTarget')
|
|
targets = XML.SubElement(unhealthy, 'targets', {
|
|
'class': 'enum-map',
|
|
'enum-type': 'hudson.plugins.cobertura.targets.CoverageMetric'})
|
|
entry = XML.SubElement(targets, 'entry')
|
|
XML.SubElement(entry, 'hudson.plugins.cobertura.targets.CoverageMetric'
|
|
).text = 'CONDITIONAL'
|
|
XML.SubElement(entry, 'int').text = '0'
|
|
entry = XML.SubElement(targets, 'entry')
|
|
XML.SubElement(entry, 'hudson.plugins.cobertura.targets.CoverageMetric'
|
|
).text = 'LINE'
|
|
XML.SubElement(entry, 'int').text = '0'
|
|
entry = XML.SubElement(targets, 'entry')
|
|
XML.SubElement(entry, 'hudson.plugins.cobertura.targets.CoverageMetric'
|
|
).text = 'METHOD'
|
|
XML.SubElement(entry, 'int').text = '0'
|
|
failing = XML.SubElement(cobertura, 'failingTarget')
|
|
targets = XML.SubElement(failing, 'targets', {
|
|
'class': 'enum-map',
|
|
'enum-type': 'hudson.plugins.cobertura.targets.CoverageMetric'})
|
|
entry = XML.SubElement(targets, 'entry')
|
|
XML.SubElement(entry, 'hudson.plugins.cobertura.targets.CoverageMetric'
|
|
).text = 'CONDITIONAL'
|
|
XML.SubElement(entry, 'int').text = '0'
|
|
entry = XML.SubElement(targets, 'entry')
|
|
XML.SubElement(entry, 'hudson.plugins.cobertura.targets.CoverageMetric'
|
|
).text = 'LINE'
|
|
XML.SubElement(entry, 'int').text = '0'
|
|
entry = XML.SubElement(targets, 'entry')
|
|
XML.SubElement(entry, 'hudson.plugins.cobertura.targets.CoverageMetric'
|
|
).text = 'METHOD'
|
|
XML.SubElement(entry, 'int').text = '0'
|
|
XML.SubElement(cobertura, 'sourceEncoding').text = 'ASCII'
|
|
|
|
|
|
def ftp(parser, xml_parent, data):
|
|
"""yaml: ftp
|
|
Upload files via FTP.
|
|
Requires the Jenkins `Publish over FTP Plugin.
|
|
<https://wiki.jenkins-ci.org/display/JENKINS/Publish+Over+FTP+Plugin>`_
|
|
|
|
:arg str site: name of the ftp site
|
|
:arg str target: destination directory
|
|
:arg str source: source path specifier
|
|
:arg str excludes: excluded file pattern (optional)
|
|
:arg str remove-prefix: prefix to remove from uploaded file paths
|
|
(optional)
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- ftp:
|
|
site: 'ftp.example.com'
|
|
target: 'dest/dir'
|
|
source: 'base/source/dir/**'
|
|
remove-prefix: 'base/source/dir'
|
|
excludes: '**/*.excludedfiletype'
|
|
"""
|
|
outer_ftp = XML.SubElement(xml_parent,
|
|
'jenkins.plugins.publish__over__ftp.BapFtpPublisherPlugin')
|
|
XML.SubElement(outer_ftp, 'consolePrefix').text = 'FTP: '
|
|
delegate = XML.SubElement(outer_ftp, 'delegate')
|
|
publishers = XML.SubElement(delegate, 'publishers')
|
|
ftp = XML.SubElement(publishers,
|
|
'jenkins.plugins.publish__over__ftp.BapFtpPublisher')
|
|
XML.SubElement(ftp, 'configName').text = data['site']
|
|
XML.SubElement(ftp, 'verbose').text = 'true'
|
|
|
|
transfers = XML.SubElement(ftp, 'transfers')
|
|
ftp_transfers = XML.SubElement(transfers,
|
|
'jenkins.plugins.publish__over__ftp.BapFtpTransfer')
|
|
XML.SubElement(ftp_transfers, 'remoteDirectory').text = data['target']
|
|
XML.SubElement(ftp_transfers, 'sourceFiles').text = data['source']
|
|
XML.SubElement(ftp_transfers, 'excludes').text = data['excludes']
|
|
XML.SubElement(ftp_transfers, 'removePrefix').text = data['remove-prefix']
|
|
XML.SubElement(ftp_transfers, 'remoteDirectorySDF').text = 'false'
|
|
XML.SubElement(ftp_transfers, 'flatten').text = 'false'
|
|
XML.SubElement(ftp_transfers, 'cleanRemote').text = 'false'
|
|
XML.SubElement(ftp_transfers, 'asciiMode').text = 'false'
|
|
|
|
XML.SubElement(ftp, 'useWorkspaceInPromotion').text = 'false'
|
|
XML.SubElement(ftp, 'usePromotionTimestamp').text = 'false'
|
|
XML.SubElement(delegate, 'continueOnError').text = 'false'
|
|
XML.SubElement(delegate, 'failOnError').text = 'false'
|
|
XML.SubElement(delegate, 'alwaysPublishFromMaster').text = 'false'
|
|
XML.SubElement(delegate, 'hostConfigurationAccess',
|
|
{'class': 'jenkins.plugins.publish_over_ftp.BapFtpPublisherPlugin',
|
|
'reference': '../..'})
|
|
|
|
|
|
def junit(parser, xml_parent, data):
|
|
"""yaml: junit
|
|
Publish JUnit test results.
|
|
|
|
:arg str results: results filename
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- junit:
|
|
results: nosetests.xml
|
|
"""
|
|
junitresult = XML.SubElement(xml_parent,
|
|
'hudson.tasks.junit.JUnitResultArchiver')
|
|
XML.SubElement(junitresult, 'testResults').text = data['results']
|
|
XML.SubElement(junitresult, 'keepLongStdio').text = "true"
|
|
XML.SubElement(junitresult, 'testDataPublishers')
|
|
|
|
|
|
def xunit(parser, xml_parent, data):
|
|
"""yaml: xunit
|
|
Publish tests results. Requires the Jenkins `xUnit Plugin.
|
|
<https://wiki.jenkins-ci.org/display/JENKINS/xUnit+Plugin>`_
|
|
|
|
:arg str thresholdmode: whether thresholds represents an absolute \
|
|
number of tests or a percentage. Either 'number' or 'percent', will \
|
|
default to 'number' if ommitted.
|
|
|
|
:arg dict thresholds: list containing the thresholds for both \
|
|
'failed' and 'skipped' tests. Each entry should in turn have a \
|
|
list of "threshold name: values". The threshold names are \
|
|
'unstable', 'unstablenew', 'failure', 'failurenew'. Omitting a \
|
|
value will resort on xUnit default value (should be 0).
|
|
|
|
:arg dict types: per framework configuration. The key should be \
|
|
one of the internal types we support:\
|
|
'aunit', 'boosttest', 'checktype', 'cpptest', 'cppunit', 'fpcunit', \
|
|
'junit', 'mstest', 'nunit', 'phpunit', 'tusar', 'unittest', 'valgrind'. \
|
|
The 'custom' type is not supported.
|
|
|
|
Each framework type can be configured using the following parameters:
|
|
|
|
:arg str pattern: An Ant pattern to look for Junit result files, \
|
|
relative to the workspace root.
|
|
|
|
:arg bool requireupdate: fail the build whenever fresh tests \
|
|
results have not been found (default: true).
|
|
|
|
:arg bool deleteoutput: delete temporary JUnit files (default: true)
|
|
|
|
:arg bool stoponerror: Fail the build whenever an error occur during \
|
|
a result file processing (default: true).
|
|
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- xunit:
|
|
thresholdmode: 'percent'
|
|
thresholds:
|
|
- failed:
|
|
unstable: 0
|
|
unstablenew: 0
|
|
failure: 0
|
|
failurenew: 0
|
|
- skipped:
|
|
unstable: 0
|
|
unstablenew: 0
|
|
failure: 0
|
|
failurenew: 0
|
|
types:
|
|
- phpunit:
|
|
pattern: junit.log
|
|
- cppUnit:
|
|
pattern: cppunit.log
|
|
|
|
"""
|
|
logger = logging.getLogger(__name__)
|
|
xunit = XML.SubElement(xml_parent, 'xunit')
|
|
|
|
# Map our internal types to the XML element names used by Jenkins plugin
|
|
types_to_plugin_types = {
|
|
'aunit': 'AUnitJunitHudsonTestType',
|
|
'boosttest': 'AUnitJunitHudsonTestType',
|
|
'checktype': 'CheckType',
|
|
'cpptest': 'CppTestJunitHudsonTestType',
|
|
'cppunit': 'CppUnitJunitHudsonTestType',
|
|
'fpcunit': 'FPCUnitJunitHudsonTestType',
|
|
'junit': 'JUnitType',
|
|
'mstest': 'MSTestJunitHudsonTestType',
|
|
'nunit': 'NUnitJunitHudsonTestType',
|
|
'phpunit': 'PHPUnitJunitHudsonTestType',
|
|
'tusar': 'TUSARJunitHudsonTestType',
|
|
'unittest': 'UnitTestJunitHudsonTestType',
|
|
'valgrind': 'ValgrindJunitHudsonTestType',
|
|
# FIXME should implement the 'custom' type
|
|
}
|
|
implemented_types = types_to_plugin_types.keys() # shortcut
|
|
|
|
# Unit framework we are going to generate xml for
|
|
supported_types = []
|
|
|
|
for configured_type in data['types']:
|
|
type_name = configured_type.keys()[0]
|
|
if type_name not in implemented_types:
|
|
logger.warn("Requested xUnit type '%s' is not yet supported" %
|
|
type_name)
|
|
else:
|
|
# Append for generation
|
|
supported_types.append(configured_type)
|
|
|
|
# Generate XML for each of the supported framework types
|
|
for supported_type in supported_types:
|
|
framework_name = supported_type.keys()[0]
|
|
xmltypes = XML.SubElement(xunit, 'types')
|
|
xmlframework = XML.SubElement(xmltypes,
|
|
types_to_plugin_types[framework_name])
|
|
|
|
XML.SubElement(xmlframework, 'pattern').text = \
|
|
supported_type[framework_name].get('pattern', '')
|
|
XML.SubElement(xmlframework, 'failedIfNotNew').text = \
|
|
str(supported_type[framework_name].get(
|
|
'requireupdate', 'true')).lower()
|
|
XML.SubElement(xmlframework, 'deleteOutputFiles').text = \
|
|
str(supported_type[framework_name].get(
|
|
'deleteoutput', 'true')).lower()
|
|
XML.SubElement(xmlframework, 'stopProcessingIfError').text = \
|
|
str(supported_type[framework_name].get(
|
|
'stoponerror', 'true')).lower()
|
|
|
|
xmlthresholds = XML.SubElement(xunit, 'thresholds')
|
|
if 'thresholds' in data:
|
|
for t in data['thresholds']:
|
|
if not ('failed' in t or 'skipped' in t):
|
|
logger.warn(
|
|
"Unrecognized threshold, should be 'failed' or 'skipped'")
|
|
continue
|
|
elname = "org.jenkinsci.plugins.xunit.threshold.%sThreshold" \
|
|
% t.keys()[0].title()
|
|
el = XML.SubElement(xmlthresholds, elname)
|
|
for threshold_name, threshold_value in t.values()[0].items():
|
|
# Normalize and craft the element name for this threshold
|
|
elname = "%sThreshold" % threshold_name.lower().replace(
|
|
'new', 'New')
|
|
XML.SubElement(el, elname).text = threshold_value
|
|
|
|
# Whether to use percent of exact number of tests.
|
|
# Thresholdmode is either:
|
|
# - 1 : absolute (number of tests), default.
|
|
# - 2 : relative (percentage of tests)
|
|
thresholdmode = '1'
|
|
if 'percent' == data.get('thresholdmode', 'number'):
|
|
thresholdmode = '2'
|
|
XML.SubElement(xunit, 'thresholdMode').text = \
|
|
thresholdmode
|
|
|
|
|
|
def _violations_add_entry(xml_parent, name, data):
|
|
vmin = data.get('min', 10)
|
|
vmax = data.get('max', 999)
|
|
vunstable = data.get('unstable', 999)
|
|
pattern = data.get('pattern', None)
|
|
|
|
entry = XML.SubElement(xml_parent, 'entry')
|
|
XML.SubElement(entry, 'string').text = name
|
|
tconfig = XML.SubElement(entry, 'hudson.plugins.violations.TypeConfig')
|
|
XML.SubElement(tconfig, 'type').text = name
|
|
XML.SubElement(tconfig, 'min').text = str(vmin)
|
|
XML.SubElement(tconfig, 'max').text = str(vmax)
|
|
XML.SubElement(tconfig, 'unstable').text = str(vunstable)
|
|
XML.SubElement(tconfig, 'usePattern').text = 'false'
|
|
if pattern:
|
|
XML.SubElement(tconfig, 'pattern').text = pattern
|
|
else:
|
|
XML.SubElement(tconfig, 'pattern')
|
|
|
|
|
|
def violations(parser, xml_parent, data):
|
|
"""yaml: violations
|
|
Publish code style violations.
|
|
Requires the Jenkins `Violations Plugin.
|
|
<https://wiki.jenkins-ci.org/display/JENKINS/Violations>`_
|
|
|
|
The violations component accepts any number of dictionaries keyed
|
|
by the name of the violations system. The dictionary has the
|
|
following values:
|
|
|
|
:arg int min: sunny threshold
|
|
:arg int max: stormy threshold
|
|
:arg int unstable: unstable threshold
|
|
:arg str pattern: report filename pattern
|
|
|
|
Any system without a dictionary provided will use default values.
|
|
|
|
Valid systems are:
|
|
|
|
checkstyle, codenarc, cpd, cpplint, csslint, findbugs, fxcop,
|
|
gendarme, jcreport, jslint, pep8, pmd, pylint, simian, stylecop
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- violations:
|
|
pep8:
|
|
min: 0
|
|
max: 1
|
|
unstable: 1
|
|
pattern: '**/pep8.txt'
|
|
"""
|
|
violations = XML.SubElement(xml_parent,
|
|
'hudson.plugins.violations.ViolationsPublisher')
|
|
config = XML.SubElement(violations, 'config')
|
|
suppressions = XML.SubElement(config, 'suppressions',
|
|
{'class': 'tree-set'})
|
|
XML.SubElement(suppressions, 'no-comparator')
|
|
configs = XML.SubElement(config, 'typeConfigs')
|
|
XML.SubElement(configs, 'no-comparator')
|
|
|
|
for name in [
|
|
'checkstyle',
|
|
'codenarc',
|
|
'cpd',
|
|
'cpplint',
|
|
'csslint',
|
|
'findbugs',
|
|
'fxcop',
|
|
'gendarme',
|
|
'jcreport',
|
|
'jslint',
|
|
'pep8',
|
|
'pmd',
|
|
'pylint',
|
|
'simian',
|
|
'stylecop']:
|
|
_violations_add_entry(configs, name, data.get(name, {}))
|
|
|
|
XML.SubElement(config, 'limit').text = '100'
|
|
XML.SubElement(config, 'sourcePathPattern')
|
|
XML.SubElement(config, 'fauxProjectPath')
|
|
XML.SubElement(config, 'encoding').text = 'default'
|
|
|
|
|
|
def scp(parser, xml_parent, data):
|
|
"""yaml: scp
|
|
Upload files via SCP
|
|
Requires the Jenkins `SCP Plugin.
|
|
<https://wiki.jenkins-ci.org/display/JENKINS/SCP+plugin>`_
|
|
|
|
:arg str site: name of the scp site
|
|
:arg str target: destination directory
|
|
:arg str source: source path specifier
|
|
:arg bool keep-hierarchy: keep the file hierarchy when uploading
|
|
(default false)
|
|
:arg bool copy-after-failure: copy files even if the job fails
|
|
(default false)
|
|
:arg bool copy-console: copy the console log (default false); if
|
|
specified, omit 'target'
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- scp:
|
|
site: 'example.com'
|
|
target: 'dest/dir'
|
|
source: 'base/source/dir/**'
|
|
"""
|
|
site = data['site']
|
|
scp = XML.SubElement(xml_parent,
|
|
'be.certipost.hudson.plugin.SCPRepositoryPublisher')
|
|
XML.SubElement(scp, 'siteName').text = site
|
|
entries = XML.SubElement(scp, 'entries')
|
|
for entry in data['files']:
|
|
entry_e = XML.SubElement(entries, 'be.certipost.hudson.plugin.Entry')
|
|
XML.SubElement(entry_e, 'filePath').text = entry['target']
|
|
XML.SubElement(entry_e, 'sourceFile').text = entry.get('source', '')
|
|
if entry.get('keep-hierarchy', False):
|
|
XML.SubElement(entry_e, 'keepHierarchy').text = 'true'
|
|
else:
|
|
XML.SubElement(entry_e, 'keepHierarchy').text = 'false'
|
|
if entry.get('copy-console', False):
|
|
XML.SubElement(entry_e, 'copyConsoleLog').text = 'true'
|
|
else:
|
|
XML.SubElement(entry_e, 'copyConsoleLog').text = 'false'
|
|
if entry.get('copy-after-failure', False):
|
|
XML.SubElement(entry_e, 'copyAfterFailure').text = 'true'
|
|
else:
|
|
XML.SubElement(entry_e, 'copyAfterFailure').text = 'false'
|
|
|
|
|
|
def pipeline(parser, xml_parent, data):
|
|
"""yaml: pipeline
|
|
Specify a downstream project in a pipeline.
|
|
Requires the Jenkins `Build Pipeline Plugin.
|
|
<https://wiki.jenkins-ci.org/display/JENKINS/Build+Pipeline+Plugin>`_
|
|
|
|
:Parameter: the name of the downstream project
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- pipleline: deploy
|
|
"""
|
|
pippub = XML.SubElement(xml_parent,
|
|
'au.com.centrumsystems.hudson.plugin.'
|
|
'buildpipeline.trigger.BuildPipelineTrigger')
|
|
XML.SubElement(pippub, 'downstreamProjectNames').text = data
|
|
|
|
|
|
def email(parser, xml_parent, data):
|
|
"""yaml: email
|
|
Email notifications on build failure.
|
|
|
|
:arg str recipients: Recipient email addresses
|
|
:arg bool notify-every-unstable-build: Send an email for every
|
|
unstable build (default true)
|
|
:arg bool send-to-individuals: Send an email to the individual
|
|
who broke the build (default false)
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- email:
|
|
recipients: breakage@example.com
|
|
"""
|
|
|
|
# TODO: raise exception if this is applied to a maven job
|
|
mailer = XML.SubElement(xml_parent,
|
|
'hudson.tasks.Mailer')
|
|
XML.SubElement(mailer, 'recipients').text = data['recipients']
|
|
|
|
# Note the logic reversal (included here to match the GUI
|
|
if data.get('notify-every-unstable-build', True):
|
|
XML.SubElement(mailer, 'dontNotifyEveryUnstableBuild').text = 'false'
|
|
else:
|
|
XML.SubElement(mailer, 'dontNotifyEveryUnstableBuild').text = 'true'
|
|
XML.SubElement(mailer, 'sendToIndividuals').text = str(
|
|
data.get('send-to-individuals', False)).lower()
|
|
|
|
|
|
def claimbuild(parser, xml_parent, data):
|
|
"""yaml: claim-build
|
|
Claim build failures
|
|
Requires the Jenkins `Claim Plugin.
|
|
<https://wiki.jenkins-ci.org/display/JENKINS/Claim+plugin>`_
|
|
|
|
Example::
|
|
|
|
publishers:
|
|
- claim-build
|
|
"""
|
|
|
|
XML.SubElement(xml_parent, 'hudson.plugins.claim.ClaimPublisher')
|
|
|
|
|
|
class Publishers(jenkins_jobs.modules.base.Base):
|
|
sequence = 70
|
|
|
|
def gen_xml(self, parser, xml_parent, data):
|
|
publishers = XML.SubElement(xml_parent, 'publishers')
|
|
|
|
for action in data.get('publishers', []):
|
|
self._dispatch('publisher', 'publishers',
|
|
parser, publishers, action)
|