Add tox.ini and pep8, pyflakes cleanup.

Change-Id: I4d6312e92dffd596ae58e55c837e3db3ea7d1c52
Reviewed-on: https://review.openstack.org/11198
Reviewed-by: Monty Taylor <mordred@inaugust.com>
Approved: James E. Blair <corvus@inaugust.com>
Tested-by: Jenkins
This commit is contained in:
James E. Blair 2012-08-10 16:45:00 -07:00 committed by Jenkins
parent ab1ee4c6c8
commit fb0a113eff
13 changed files with 135 additions and 123 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
*.pyc
*.egg-info
config
.tox

View File

@ -21,15 +21,9 @@ import yaml
import xml.etree.ElementTree as XML
from xml.dom import minidom
import jenkins
import ConfigParser
from StringIO import StringIO
import re
import pkgutil
import pkg_resources
import pprint
import sys
class JenkinsJobsException(Exception): pass
class YamlParser(object):
def __init__(self):
@ -115,11 +109,16 @@ class YamlParser(object):
def gen_xml(self, xml, data):
XML.SubElement(xml, 'actions')
description = XML.SubElement(xml, 'description')
description.text = "THIS JOB IS MANAGED BY PUPPET AND WILL BE OVERWRITTEN.\n\n\
DON'T EDIT THIS JOB THROUGH THE WEB\n\n\
If you would like to make changes to this job, please see:\n\n\
https://github.com/openstack/openstack-ci-puppet\n\n\
In modules/jenkins_jobs"
description.text = """THIS JOB IS MANAGED BY PUPPET \
AND WILL BE OVERWRITTEN.
DON'T EDIT THIS JOB THROUGH THE WEB
If you would like to make changes to this job, please see:
https://github.com/openstack/openstack-ci-puppet
In modules/jenkins_jobs"""
XML.SubElement(xml, 'keepDependencies').text = 'false'
if data.get('disabled'):
XML.SubElement(xml, 'disabled').text = 'true'
@ -138,8 +137,6 @@ In modules/jenkins_jobs"
class ModuleRegistry(object):
# TODO: make this extensible
def __init__(self):
self.modules = []
self.handlers = {}
@ -160,6 +157,7 @@ class ModuleRegistry(object):
def getHandler(self, category, name):
return self.handlers[category][name]
class XmlJob(object):
def __init__(self, xml, name):
self.xml = xml
@ -168,61 +166,65 @@ class XmlJob(object):
def md5(self):
return hashlib.md5(self.output()).hexdigest()
# Pretty printing ideas from http://stackoverflow.com/questions/749796/pretty-printing-xml-in-python
# Pretty printing ideas from
# http://stackoverflow.com/questions/749796/pretty-printing-xml-in-python
pretty_text_re = re.compile('>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL)
def output(self):
out = minidom.parseString(XML.tostring(self.xml)).toprettyxml(indent=' ')
out = minidom.parseString(XML.tostring(self.xml))
out = out.toprettyxml(indent=' ')
return self.pretty_text_re.sub('>\g<1></', out)
class CacheStorage(object):
def __init__(self):
self.cachefilename = os.path.expanduser('~/.jenkins_jobs_cache.yml')
try:
yfile = file(self.cachefilename, 'r')
except IOError:
self.data = {}
return
self.data = yaml.load(yfile)
yfile.close()
def __init__(self):
self.cachefilename = os.path.expanduser('~/.jenkins_jobs_cache.yml')
try:
yfile = file(self.cachefilename, 'r')
except IOError:
self.data = {}
return
self.data = yaml.load(yfile)
yfile.close()
def set(self, job, md5):
self.data[job] = md5
yfile = file(self.cachefilename, 'w')
yaml.dump(self.data, yfile)
yfile.close()
def set(self, job, md5):
self.data[job] = md5
yfile = file(self.cachefilename, 'w')
yaml.dump(self.data, yfile)
yfile.close()
def is_cached(self, job):
if self.data.has_key(job):
def is_cached(self, job):
if job in self.data:
return True
return False
return False
def has_changed(self, job, md5):
if self.data.has_key(job) and self.data[job] == md5:
def has_changed(self, job, md5):
if job in self.data and self.data[job] == md5:
return False
return True
return True
class Jenkins(object):
def __init__(self, url, user, password):
self.jenkins = jenkins.Jenkins(url, user, password)
def __init__(self, url, user, password):
self.jenkins = jenkins.Jenkins(url, user, password)
def update_job(self, job_name, xml):
if self.is_job(job_name):
self.jenkins.reconfig_job(job_name, xml)
else:
self.jenkins.create_job(job_name, xml)
def update_job(self, job_name, xml):
if self.is_job(job_name):
self.jenkins.reconfig_job(job_name, xml)
else:
self.jenkins.create_job(job_name, xml)
def is_job(self, job_name):
return self.jenkins.job_exists(job_name)
def is_job(self, job_name):
return self.jenkins.job_exists(job_name)
def get_job_md5(self, job_name):
xml = self.jenkins.get_job_config(job_name)
return hashlib.md5(xml).hexdigest()
def get_job_md5(self, job_name):
xml = self.jenkins.get_job_config(job_name)
return hashlib.md5(xml).hexdigest()
def delete_job(self, job_name):
if self.is_job(job_name):
self.jenkins.delete_job(job_name)
def delete_job(self, job_name):
if self.is_job(job_name):
self.jenkins.delete_job(job_name)
class Builder(object):
def __init__(self, jenkins_url, jenkins_user, jenkins_password):
@ -244,7 +246,7 @@ class Builder(object):
parser.parse(in_file)
parser.generateXML()
parser.jobs.sort(lambda a,b: cmp(a.name, b.name))
parser.jobs.sort(lambda a, b: cmp(a.name, b.name))
for job in parser.jobs:
if name and job.name != name:
continue
@ -266,6 +268,3 @@ class Builder(object):
if self.cache.has_changed(job.name, md5):
self.jenkins.update_job(job.name, job.output())
self.cache.set(job.name, md5)

View File

@ -20,24 +20,24 @@
import xml.etree.ElementTree as XML
import jenkins_jobs.modules.base
import pkg_resources
import yaml
def shell(parser, xml_parent, data):
shell = XML.SubElement(xml_parent, 'hudson.tasks.Shell')
XML.SubElement(shell, 'command').text = data
def trigger_builds(parser, xml_parent, data):
tbuilder = XML.SubElement(xml_parent,
'hudson.plugins.parameterizedtrigger.TriggerBuilder')
'hudson.plugins.parameterizedtrigger.TriggerBuilder')
configs = XML.SubElement(tbuilder, 'configs')
for project_def in data:
tconfig = XML.SubElement(configs,
'hudson.plugins.parameterizedtrigger.BlockableBuildTriggerConfig')
tconfigs = XML.SubElement(tconfig, 'configs')
if project_def.has_key('predefined-parameters'):
if 'predefined-parameters' in project_def:
params = XML.SubElement(tconfigs,
'hudson.plugins.parameterizedtrigger.PredefinedBuildParameters')
'hudson.plugins.parameterizedtrigger.PredefinedBuildParameters')
properties = XML.SubElement(params, 'properties')
properties.text = project_def['predefined-parameters']
else:
@ -46,11 +46,14 @@ def trigger_builds(parser, xml_parent, data):
projects.text = project_def['project']
condition = XML.SubElement(tconfig, 'condition')
condition.text = 'ALWAYS'
trigger_with_no_params = XML.SubElement(tconfig, 'triggerWithNoParameters')
trigger_with_no_params = XML.SubElement(tconfig,
'triggerWithNoParameters')
trigger_with_no_params.text = 'false'
build_all_nodes_with_label = XML.SubElement(tconfig, 'buildAllNodesWithLabel')
build_all_nodes_with_label = XML.SubElement(tconfig,
'buildAllNodesWithLabel')
build_all_nodes_with_label.text = 'false'
class Builders(jenkins_jobs.modules.base.Base):
sequence = 60

View File

@ -28,7 +28,7 @@ class LogRotate(jenkins_jobs.modules.base.Base):
sequence = 10
def gen_xml(self, parser, xml_parent, data):
if data.has_key('logrotate'):
if 'logrotate' in data:
lr_xml = XML.SubElement(xml_parent, 'logRotator')
logrotate = data['logrotate']
lr_days = XML.SubElement(lr_xml, 'daysToKeep')

View File

@ -23,6 +23,7 @@
import xml.etree.ElementTree as XML
import jenkins_jobs.modules.base
class Maven(jenkins_jobs.modules.base.Base):
sequence = 0

View File

@ -18,12 +18,14 @@
import xml.etree.ElementTree as XML
import jenkins_jobs.modules.base
def github(parser, xml_parent, data):
github = XML.SubElement(xml_parent,
'com.coravy.hudson.plugins.github.GithubProjectProperty')
github_url = XML.SubElement(github, 'projectUrl')
github_url.text = data['url']
def throttle(parser, xml_parent, data):
throttle = XML.SubElement(xml_parent,
'hudson.plugins.throttleconcurrents.ThrottleJobProperty')
@ -40,6 +42,7 @@ def throttle(parser, xml_parent, data):
XML.SubElement(throttle, 'throttleOption').text = data.get('option')
XML.SubElement(throttle, 'configVersion').text = '1'
def authenticated_build(parser, xml_parent, data):
# TODO: generalize this
if data:
@ -48,6 +51,7 @@ def authenticated_build(parser, xml_parent, data):
XML.SubElement(security, 'permission').text = \
'hudson.model.Item.Build:authenticated'
def base_param(parser, xml_parent, data, do_default, ptype):
pdef = XML.SubElement(xml_parent, ptype)
XML.SubElement(pdef, 'name').text = data['name']
@ -59,26 +63,32 @@ def base_param(parser, xml_parent, data, do_default, ptype):
else:
XML.SubElement(pdef, 'defaultValue')
def string_param(parser, xml_parent, data):
base_param(parser, xml_parent, data, True,
'hudson.model.StringParameterDefinition')
def bool_param(parser, xml_parent, data):
base_param(parser, xml_parent, data, True,
'hudson.model.BooleanParameterDefinition')
def file_param(parser, xml_parent, data):
base_param(parser, xml_parent, data, False,
'hudson.model.FileParameterDefinition')
def text_param(parser, xml_parent, data):
base_param(parser, xml_parent, data, True,
'hudson.model.TextParameterDefinition')
def label_param(parser, xml_parent, data):
base_param(parser, xml_parent, data, True,
'org.jvnet.jenkins.plugins.nodelabelparameter.LabelParameterDefinition')
def http_endpoint(parser, xml_parent, data):
endpoint_element = XML.SubElement(xml_parent,
'com.tikal.hudson.plugins.notification.Endpoint')
@ -114,4 +124,3 @@ class Properties(jenkins_jobs.modules.base.Base):
for endpoint in notifications:
self._dispatch('notification', 'notifications',
parser, endpoints_element, endpoint)

View File

@ -18,6 +18,7 @@
import xml.etree.ElementTree as XML
import jenkins_jobs.modules.base
def archive(parser, xml_parent, data):
archiver = XML.SubElement(xml_parent, 'hudson.tasks.ArtifactArchiver')
artifacts = XML.SubElement(archiver, 'artifacts')
@ -32,6 +33,7 @@ def archive(parser, xml_parent, data):
else:
latest.text = 'false'
def trigger_parameterized_builds(parser, xml_parent, data):
tbuilder = XML.SubElement(xml_parent,
'hudson.plugins.parameterizedtrigger.BuildTrigger')
@ -40,9 +42,9 @@ def trigger_parameterized_builds(parser, xml_parent, data):
tconfig = XML.SubElement(configs,
'hudson.plugins.parameterizedtrigger.BuildTriggerConfig')
tconfigs = XML.SubElement(tconfig, 'configs')
if project_def.has_key('predefined-parameters'):
if 'predefined-parameters' in project_def:
params = XML.SubElement(tconfigs,
'hudson.plugins.parameterizedtrigger.PredefinedBuildParameters')
'hudson.plugins.parameterizedtrigger.PredefinedBuildParameters')
properties = XML.SubElement(params, 'properties')
properties.text = project_def['predefined-parameters']
else:
@ -55,6 +57,7 @@ def trigger_parameterized_builds(parser, xml_parent, data):
'triggerWithNoParameters')
trigger_with_no_params.text = 'false'
def coverage(parser, xml_parent, data):
cobertura = XML.SubElement(xml_parent,
'hudson.plugins.cobertura.CoberturaPublisher')
@ -62,8 +65,8 @@ def coverage(parser, xml_parent, data):
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'})
'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'
@ -78,8 +81,8 @@ def coverage(parser, xml_parent, data):
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'})
'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'
@ -94,8 +97,8 @@ def coverage(parser, xml_parent, data):
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'})
'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'
@ -123,40 +126,6 @@ def coverage(parser, xml_parent, data):
# docs.openstack.org $ftpdir/dest/dir exluding the excluded file type.
def ftp(parser, xml_parent, data):
"""
Example XML:
<publishers>
<jenkins.plugins.publish__over__ftp.BapFtpPublisherPlugin>
<consolePrefix>FTP: </consolePrefix>
<delegate>
<publishers>
<jenkins.plugins.publish__over__ftp.BapFtpPublisher>
<configName>docs.openstack.org</configName>
<verbose>true</verbose>
<transfers>
<jenkins.plugins.publish__over__ftp.BapFtpTransfer>
<remoteDirectory></remoteDirectory>
<sourceFiles>openstack-identity-api/target/docbkx/webhelp/api/openstack-identity-service/2.0/**</sourceFiles>
<excludes>**/*.xml,**/null*</excludes>
<removePrefix>openstack-identity-api/target/docbkx/webhelp</removePrefix>
<remoteDirectorySDF>false</remoteDirectorySDF>
<flatten>false</flatten>
<cleanRemote>false</cleanRemote>
<asciiMode>false</asciiMode>
</jenkins.plugins.publish__over__ftp.BapFtpTransfer>
</transfers>
<useWorkspaceInPromotion>false</useWorkspaceInPromotion>
<usePromotionTimestamp>false</usePromotionTimestamp>
</jenkins.plugins.publish__over__ftp.BapFtpPublisher>
</publishers>
<continueOnError>false</continueOnError>
<failOnError>false</failOnError>
<alwaysPublishFromMaster>false</alwaysPublishFromMaster>
<hostConfigurationAccess class="jenkins.plugins.publish_over_ftp.BapFtpPublisherPlugin" reference="../.."/>
</delegate>
</jenkins.plugins.publish__over__ftp.BapFtpPublisherPlugin>
</publishers>
"""
outer_ftp = XML.SubElement(xml_parent,
'jenkins.plugins.publish__over__ftp.BapFtpPublisherPlugin')
XML.SubElement(outer_ftp, 'consolePrefix').text = 'FTP: '
@ -168,7 +137,8 @@ def ftp(parser, xml_parent, data):
XML.SubElement(ftp, 'verbose').text = 'true'
transfers = XML.SubElement(ftp, 'transfers')
ftp_transfers = XML.SubElement(transfers, 'jenkins.plugins.publish__over__ftp.BapFtpTransfer')
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']
@ -187,6 +157,7 @@ def ftp(parser, xml_parent, data):
{'class': 'jenkins.plugins.publish_over_ftp.BapFtpPublisherPlugin',
'reference': '../..'})
# Jenkins Job module for coverage publishers
# To use you add the following into your YAML:
# publisher:
@ -211,14 +182,16 @@ def _pep8_add_entry(xml_parent, name):
XML.SubElement(tconfig, 'usePattern').text = 'false'
XML.SubElement(tconfig, 'pattern')
# Jenkins Job module for pep8 publishers
# No additional YAML needed
def pep8(parser, xml_parent, data):
violations = XML.SubElement(xml_parent,
'hudson.plugins.violations.ViolationsPublisher')
'hudson.plugins.violations.ViolationsPublisher')
config = XML.SubElement(violations, 'config')
suppressions = XML.SubElement(config, 'suppressions', {'class':'tree-set'})
suppressions = XML.SubElement(config, 'suppressions',
{'class': 'tree-set'})
XML.SubElement(suppressions, 'no-comparator')
configs = XML.SubElement(config, 'typeConfigs')
XML.SubElement(configs, 'no-comparator')
@ -254,6 +227,7 @@ def pep8(parser, xml_parent, data):
XML.SubElement(config, 'fauxProjectPath')
XML.SubElement(config, 'encoding').text = 'default'
# Jenkins Job module for generic scp publishing
# To use you add the following into your YAML:
# publish:
@ -276,6 +250,7 @@ def scp(parser, xml_parent, data):
else:
XML.SubElement(entry, 'keepHierarchy').text = 'false'
class Publishers(jenkins_jobs.modules.base.Base):
sequence = 70
@ -285,6 +260,3 @@ class Publishers(jenkins_jobs.modules.base.Base):
for action in data.get('publishers', []):
self._dispatch('publisher', 'publishers',
parser, publishers, action)

View File

@ -22,9 +22,10 @@
import xml.etree.ElementTree as XML
import jenkins_jobs.modules.base
def git(self, xml_parent, data):
scm = XML.SubElement(xml_parent,
'scm',{'class':'hudson.plugins.git.GitSCM'})
'scm', {'class': 'hudson.plugins.git.GitSCM'})
XML.SubElement(scm, 'configVersion').text = '2'
user = XML.SubElement(scm, 'userRemoteConfigs')
huser = XML.SubElement(user, 'hudson.plugins.git.UserRemoteConfig')
@ -46,9 +47,9 @@ def git(self, xml_parent, data):
XML.SubElement(scm, 'pruneBranches').text = 'false'
XML.SubElement(scm, 'remotePoll').text = 'false'
XML.SubElement(scm, 'buildChooser',
{'class':'hudson.plugins.git.util.DefaultBuildChooser'})
{'class': 'hudson.plugins.git.util.DefaultBuildChooser'})
XML.SubElement(scm, 'gitTool').text = 'Default'
XML.SubElement(scm, 'submoduleCfg', {'class':'list'})
XML.SubElement(scm, 'submoduleCfg', {'class': 'list'})
XML.SubElement(scm, 'relativeTargetDir')
XML.SubElement(scm, 'reference')
XML.SubElement(scm, 'excludedRegions')
@ -58,6 +59,7 @@ def git(self, xml_parent, data):
XML.SubElement(scm, 'skipTag').text = 'false'
XML.SubElement(scm, 'scmName')
class SCM(jenkins_jobs.modules.base.Base):
sequence = 30
@ -68,5 +70,4 @@ class SCM(jenkins_jobs.modules.base.Base):
self._dispatch('scm', 'scm',
parser, xml_parent, scm)
else:
XML.SubElement(xml_parent, 'scm', {'class':'hudson.scm.NullSCM'})
XML.SubElement(xml_parent, 'scm', {'class': 'hudson.scm.NullSCM'})

View File

@ -24,7 +24,11 @@
# overrideVotes: 'true'
# gerritBuildSuccessfulVerifiedValue: 1
# gerritBuildFailedVerifiedValue: -1
# failureMessage: 'This change was unable to be automatically merged with the current state of the repository. Please rebase your change and upload a new patchset.'
#
# failureMessage: 'This change was unable to be automatically merged
# with the current state of the repository. Please rebase your change
# and upload a new patchset.'
#
# projects:
# - projectCompareType: 'PLAIN'
# projectPattern: 'openstack/nova'
@ -36,11 +40,13 @@
# branchPattern: '**'
# ...
#
# triggerApprovalCategory and triggerApprovalValue only required if triggerOnCommentAddedEvent: 'true'
# triggerApprovalCategory and triggerApprovalValue only required
# if triggerOnCommentAddedEvent: 'true'
import xml.etree.ElementTree as XML
import jenkins_jobs.modules.base
def gerrit(parser, xml_parent, data):
projects = data['projects']
gtrig = XML.SubElement(xml_parent,
@ -71,7 +77,7 @@ def gerrit(parser, xml_parent, data):
data['triggerOnCommentAddedEvent']
XML.SubElement(gtrig, 'triggerOnRefUpdatedEvent').text = \
data['triggerOnRefUpdatedEvent']
if data.has_key('overrideVotes') and data['overrideVotes'] == 'true':
if 'overrideVotes' in data and data['overrideVotes'] == 'true':
XML.SubElement(gtrig, 'gerritBuildSuccessfulVerifiedValue').text = \
str(data['gerritBuildSuccessfulVerifiedValue'])
XML.SubElement(gtrig, 'gerritBuildFailedVerifiedValue').text = \
@ -87,6 +93,7 @@ def gerrit(parser, xml_parent, data):
XML.SubElement(gtrig, 'buildUnstableMessage')
XML.SubElement(gtrig, 'customUrl')
# Jenkins Job module for scm polling triggers
# To use add the following into your YAML:
# trigger:
@ -98,6 +105,7 @@ def pollscm(parser, xml_parent, data):
scmtrig = XML.SubElement(xml_parent, 'hudson.triggers.SCMTrigger')
XML.SubElement(scmtrig, 'spec').text = data
# Jenkins Job module for timed triggers
# To use add the following into your YAML:
# trigger:
@ -109,6 +117,7 @@ def timed(parser, xml_parent, data):
scmtrig = XML.SubElement(xml_parent, 'hudson.triggers.TimerTrigger')
XML.SubElement(scmtrig, 'spec').text = data
class Triggers(jenkins_jobs.modules.base.Base):
sequence = 50
@ -117,8 +126,7 @@ class Triggers(jenkins_jobs.modules.base.Base):
if not triggers:
return
trig_e = XML.SubElement(xml_parent, 'triggers', {'class':'vector'})
trig_e = XML.SubElement(xml_parent, 'triggers', {'class': 'vector'})
for trigger in triggers:
self._dispatch('trigger', 'triggers',
parser, trig_e, trigger)

View File

@ -30,10 +30,12 @@ def timeout(parser, xml_parent, data):
else:
failbuild.text = 'false'
def timestamps(parser, xml_parent, data):
XML.SubElement(xml_parent,
'hudson.plugins.timestamper.TimestamperBuildWrapper')
def ansicolor(parser, xml_parent, data):
XML.SubElement(xml_parent,
'hudson.plugins.ansicolor.AnsiColorBuildWrapper')
@ -48,4 +50,3 @@ class Wrappers(jenkins_jobs.modules.base.Base):
for wrap in data.get('wrappers', []):
self._dispatch('wrapper', 'wrappers',
parser, wrappers, wrap)

View File

@ -55,6 +55,7 @@ ZUUL_NOTIFICATIONS = [
{'url': 'http://127.0.0.1:8001/jenkins_endpoint'}}
]
class Zuul(jenkins_jobs.modules.base.Base):
sequence = 0

View File

@ -26,7 +26,7 @@ setup(name='jenkins_job_builder',
zip_safe=False,
packages=find_packages(),
entry_points = {
entry_points={
'jenkins_jobs.projects': [
'freestyle=jenkins_jobs.modules.project_freestyle:Freestyle',
'maven=jenkins_jobs.modules.project_maven:Maven',

16
tox.ini Normal file
View File

@ -0,0 +1,16 @@
[tox]
envlist = pep8, pyflakes
[tox:jenkins]
downloadcache = ~/cache/pip
[testenv:pep8]
deps = pep8==1.2
commands = pep8 --repeat --show-source --exclude=.venv,.tox,dist,doc,build .
[testenv:pyflakes]
deps = pyflakes
commands = pyflakes jenkins_jobs jenkins-jobs setup.py
[testenv:venv]
commands = {posargs}