Refactor modules and templating.
Switch to using entry points for loading modules as well as individual buliders, triggers, publishers, etc. Remove most openstack-specific python code. Change templating so it's less repetitive -- a single project definition will suffice for multiple jobs or job-groups. This outputs XML that is identical to the current production XML, warts and all. There are significant improvements that can be made to the YAML in a separate change, as they will cause minor changes to existing jobs (adding timestamps, logrotate, etc.). These are mostly marked with TODO in this change. Change-Id: Idcfddb3b43b6cfef4b20919a84540706d7a0a0b1 Reviewed-on: https://review.openstack.org/11000 Approved: James E. Blair <corvus@inaugust.com> Reviewed-by: James E. Blair <corvus@inaugust.com> Tested-by: Jenkins
This commit is contained in:
parent
ae673c9ac2
commit
8f09841693
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.pyc
|
||||
*.egg-info
|
80
example/ceilometer.yml
Normal file
80
example/ceilometer.yml
Normal file
@ -0,0 +1,80 @@
|
||||
- project:
|
||||
name: ceilometer
|
||||
github-org: stackforge
|
||||
node: oneiric
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
|
||||
|
||||
- job:
|
||||
name: 'gate-ceilometer-python26-essex'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/stackforge/ceilometer
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
# TODO: logrotate this job
|
||||
#logrotate:
|
||||
# daysToKeep: 28
|
||||
# numToKeep: -1
|
||||
# artifactDaysToKeep: -1
|
||||
# artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- python26_essex
|
||||
|
||||
# >= precise does not have python2.6
|
||||
node: oneiric
|
||||
|
||||
|
||||
- job:
|
||||
name: 'gate-ceilometer-python27-essex'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/stackforge/ceilometer
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
# TODO: logrotate this job
|
||||
#logrotate:
|
||||
# daysToKeep: 28
|
||||
# numToKeep: -1
|
||||
# artifactDaysToKeep: -1
|
||||
# artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- python27_essex
|
||||
|
||||
node: oneiric
|
10
example/cinder.yml
Normal file
10
example/cinder.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: cinder
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- openstack-publish-jobs
|
273
example/devstack-gate.yml
Normal file
273
example/devstack-gate.yml
Normal file
@ -0,0 +1,273 @@
|
||||
- job:
|
||||
name: gate-devstack-gate-merge
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/devstack-gate
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
|
||||
|
||||
- job:
|
||||
name: gate-integration-tests-devstack-vm
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: devstack-precise
|
||||
|
||||
properties:
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
parameters:
|
||||
- label:
|
||||
name: NODE_LABEL
|
||||
description: Label of node to use for this build
|
||||
default: devstack-precise
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 40
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- trigger-builds:
|
||||
- project: devstack-update-inprogress
|
||||
predefined_parameters:
|
||||
DEVSTACK_NODE_NAME=${NODE_NAME}
|
||||
- shell: |
|
||||
#!/bin/bash -xe
|
||||
#
|
||||
# This job also gates devstack-gate, but in case a previous run fails,
|
||||
# we need to always make sure that we're starting with the latest copy
|
||||
# from master, before we start applying changes to it. If a previous run
|
||||
# leaves a bad copy of the gate script, we may get stuck.
|
||||
#
|
||||
if [[ ! -e devstack-gate ]]; then
|
||||
git clone https://review.openstack.org/p/openstack-ci/devstack-gate
|
||||
else
|
||||
cd devstack-gate
|
||||
git remote update
|
||||
git reset --hard
|
||||
git clean -x -f
|
||||
git checkout master
|
||||
git reset --hard remotes/origin/master
|
||||
git clean -x -f
|
||||
cd ..
|
||||
fi
|
||||
- shell: |
|
||||
#!/bin/bash -xe
|
||||
export PYTHONUNBUFFERED=true
|
||||
cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh
|
||||
./safe-devstack-vm-gate-wrap.sh
|
||||
|
||||
publishers:
|
||||
- archive:
|
||||
artifacts: logs/*
|
||||
- trigger-parameterized-builds:
|
||||
- project: devstack-update-complete
|
||||
when: complete
|
||||
predefined_parameters:
|
||||
DEVSTACK_NODE_NAME=${NODE_NAME}
|
||||
|
||||
|
||||
- job:
|
||||
name: gate-tempest-devstack-vm
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: devstack-precise
|
||||
|
||||
properties:
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
parameters:
|
||||
- label:
|
||||
name: NODE_LABEL
|
||||
description: Label of node to use for this build
|
||||
default: devstack-precise
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 90
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- trigger-builds:
|
||||
- project: devstack-update-inprogress
|
||||
predefined_parameters:
|
||||
DEVSTACK_NODE_NAME=${NODE_NAME}
|
||||
- shell: |
|
||||
#!/bin/bash -xe
|
||||
#
|
||||
# This job also gates devstack-gate, but in case a previous run fails,
|
||||
# we need to always make sure that we're starting with the latest copy
|
||||
# from master, before we start applying changes to it. If a previous run
|
||||
# leaves a bad copy of the gate script, we may get stuck.
|
||||
#
|
||||
if [[ ! -e devstack-gate ]]; then
|
||||
git clone https://review.openstack.org/p/openstack-ci/devstack-gate
|
||||
else
|
||||
cd devstack-gate
|
||||
git remote update
|
||||
git reset --hard
|
||||
git clean -x -f
|
||||
git checkout master
|
||||
git reset --hard remotes/origin/master
|
||||
git clean -x -f
|
||||
cd ..
|
||||
fi
|
||||
- shell: |
|
||||
#!/bin/bash -xe
|
||||
export PYTHONUNBUFFERED=true
|
||||
export DEVSTACK_GATE_TEMPEST=1
|
||||
cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh
|
||||
./safe-devstack-vm-gate-wrap.sh
|
||||
|
||||
publishers:
|
||||
- archive:
|
||||
artifacts: logs/*
|
||||
- trigger-parameterized-builds:
|
||||
- project: devstack-update-complete
|
||||
when: complete
|
||||
predefined_parameters:
|
||||
DEVSTACK_NODE_NAME=${NODE_NAME}
|
||||
|
||||
|
||||
# Called by devstack jobs to alert that they have started so that the
|
||||
# jenkins slave they are running on can be disabled.
|
||||
- job:
|
||||
name: devstack-update-inprogress
|
||||
project-type: freestyle
|
||||
concurrent: false
|
||||
node: master
|
||||
|
||||
properties:
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: 100
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 10
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
builders:
|
||||
- shell: |
|
||||
#!/bin/bash -xe
|
||||
|
||||
if [[ ! -e devstack-gate ]]; then
|
||||
git clone https://review.openstack.org/p/openstack-ci/devstack-gate
|
||||
else
|
||||
cd devstack-gate
|
||||
git remote update
|
||||
git pull --ff-only origin
|
||||
cd ..
|
||||
fi
|
||||
- shell: |
|
||||
#!/bin/bash -xe
|
||||
export PYTHONUNBUFFERED=true
|
||||
$WORKSPACE/devstack-gate/devstack-vm-inprogress.py $DEVSTACK_NODE_NAME
|
||||
|
||||
|
||||
# Called by devstack jobs to alert that they have completed so that the
|
||||
# jenkins slave may be deleted.
|
||||
- job:
|
||||
name: devstack-update-complete
|
||||
project-type: freestyle
|
||||
concurrent: false
|
||||
node: master
|
||||
|
||||
properties:
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: 100
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 10
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
builders:
|
||||
- shell: |
|
||||
#!/bin/bash -xe
|
||||
|
||||
if [[ ! -e devstack-gate ]]; then
|
||||
git clone https://review.openstack.org/p/openstack-ci/devstack-gate
|
||||
else
|
||||
cd devstack-gate
|
||||
git remote update
|
||||
git pull --ff-only origin
|
||||
cd ..
|
||||
fi
|
||||
- shell: |
|
||||
#!/bin/bash -xe
|
||||
export PYTHONUNBUFFERED=true
|
||||
$WORKSPACE/devstack-gate/devstack-vm-delete.py $DEVSTACK_NODE_NAME
|
33
example/devstack.yml
Normal file
33
example/devstack.yml
Normal file
@ -0,0 +1,33 @@
|
||||
- job:
|
||||
name: gate-devstack-merge
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-dev/devstack
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
# TODO: logrotate this job
|
||||
#logrotate:
|
||||
# daysToKeep: 28
|
||||
# numToKeep: -1
|
||||
# artifactDaysToKeep: -1
|
||||
# artifactNumToKeep: -1
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
35
example/gerrit-verification-status-plugin.yml
Normal file
35
example/gerrit-verification-status-plugin.yml
Normal file
@ -0,0 +1,35 @@
|
||||
- project:
|
||||
name: gerrit-verification-status-plugin
|
||||
github-org: openstack-ci
|
||||
node: precise
|
||||
|
||||
# TODO: standardize
|
||||
#jobs:
|
||||
#- gate-{name}-merge
|
||||
|
||||
- job:
|
||||
name: gate-gerrit-verification-status-plugin-merge
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/gerrit-verification-status-plugin
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
|
||||
node: precise
|
159
example/gerrit.yml
Normal file
159
example/gerrit.yml
Normal file
@ -0,0 +1,159 @@
|
||||
- project:
|
||||
name: gerrit
|
||||
github-org: openstack-ci
|
||||
node: precise
|
||||
|
||||
# TODO: standardize
|
||||
#jobs:
|
||||
# - gate-{name}-merge
|
||||
|
||||
|
||||
- job:
|
||||
name: gate-gerrit-merge
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/gerrit
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
|
||||
node: precise
|
||||
|
||||
|
||||
- job:
|
||||
name: check-gerrit-unittests
|
||||
project-type: maven
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 40
|
||||
fail: true
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/gerrit
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
prebuilders:
|
||||
- gerrit_git_prep
|
||||
- gerrit_preclean
|
||||
|
||||
maven:
|
||||
root_module:
|
||||
group_id: com.google.gerrit
|
||||
artifact_id: gerrit-parent
|
||||
goals: 'clean package -Dgerrit.include-documentation=1 -X'
|
||||
|
||||
postbuilders:
|
||||
- gerrit_postrun
|
||||
|
||||
publishers:
|
||||
- war:
|
||||
site: 'nova.openstack.org'
|
||||
warfile: 'gerrit-war/target/gerrit*.war'
|
||||
target: 'tarballs/ci/test/'
|
||||
|
||||
|
||||
- job:
|
||||
name: gate-gerrit-unittests
|
||||
project-type: maven
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 40
|
||||
fail: true
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/gerrit
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
prebuilders:
|
||||
- gerrit_git_prep
|
||||
- gerrit_preclean
|
||||
|
||||
maven:
|
||||
root_module:
|
||||
group_id: com.google.gerrit
|
||||
artifact_id: gerrit-parent
|
||||
goals: 'clean package -Dgerrit.include-documentation=1 -X'
|
||||
|
||||
postbuilders:
|
||||
- gerrit_postrun
|
||||
|
||||
|
||||
- job:
|
||||
name: gerrit-package
|
||||
project-type: maven
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 40
|
||||
fail: true
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/gerrit
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
prebuilders:
|
||||
- gerrit_git_prep
|
||||
- gerrit_preclean
|
||||
|
||||
maven:
|
||||
root_module:
|
||||
group_id: com.google.gerrit
|
||||
artifact_id: gerrit-parent
|
||||
goals: 'clean package -Dgerrit.include-documentation=1 -X'
|
||||
|
||||
postbuilders:
|
||||
- gerrit_postrun
|
||||
|
||||
publishers:
|
||||
- war:
|
||||
site: 'nova.openstack.org'
|
||||
warfile: 'gerrit-war/target/gerrit*.war'
|
||||
target: 'tarballs/ci/'
|
90
example/gerritbot.yml
Normal file
90
example/gerritbot.yml
Normal file
@ -0,0 +1,90 @@
|
||||
- project:
|
||||
name: gerritbot
|
||||
github-org: openstack-ci
|
||||
node: precise
|
||||
doc-publisher-site: ci.openstack.org
|
||||
tarball-publisher-site: ci.openstack.org
|
||||
|
||||
jobs:
|
||||
- gate-{name}-merge
|
||||
- gate-{name}-pep8
|
||||
- gate-{name}-pyflakes
|
||||
# TODO: standardize
|
||||
#- '{name}-sdist-tarball'
|
||||
#- '{name}-pypi'
|
||||
|
||||
- job:
|
||||
name: 'gerritbot-sdist-tarball'
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/openstack-ci/gerritbot'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- shell: |
|
||||
#!/bin/bash -xe
|
||||
BRANCH=$GERRIT_REFNAME
|
||||
BRANCH_PATH=`echo $BRANCH | tr / -`
|
||||
|
||||
tox -v -evenv python setup.py sdist
|
||||
cp dist/* dist/gerritbot-$BRANCH_PATH.tar.gz
|
||||
|
||||
publishers:
|
||||
- tarball:
|
||||
project: 'gerritbot'
|
||||
site: 'ci.openstack.org'
|
||||
|
||||
|
||||
- job:
|
||||
name: 'gerritbot-pypi'
|
||||
concurrent: true
|
||||
node: pypi
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/openstack-ci/gerritbot'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- shell: tox -v -evenv python setup.py sdist upload
|
||||
|
||||
publishers:
|
||||
- tarball:
|
||||
project: 'gerritbot'
|
||||
site: 'ci.openstack.org'
|
45
example/gerritlib.yml
Normal file
45
example/gerritlib.yml
Normal file
@ -0,0 +1,45 @@
|
||||
- project:
|
||||
name: gerritlib
|
||||
github-org: openstack-ci
|
||||
node: precise
|
||||
doc-publisher-site: ci.openstack.org
|
||||
tarball-publisher-site: ci.openstack.org
|
||||
|
||||
jobs:
|
||||
- gate-{name}-merge
|
||||
- gate-{name}-pep8
|
||||
- gate-{name}-pyflakes
|
||||
# TODO: standardize
|
||||
#- '{name}-pypi'
|
||||
|
||||
- job:
|
||||
name: 'gerritlib-pypi'
|
||||
concurrent: true
|
||||
node: pypi
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/openstack-ci/gerritlib'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- shell: tox -v -evenv python setup.py sdist upload
|
||||
|
||||
publishers:
|
||||
- tarball:
|
||||
project: 'ci'
|
||||
site: 'nova.openstack.org'
|
10
example/glance.yml
Normal file
10
example/glance.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: glance
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- openstack-publish-jobs
|
7
example/heat.yml
Normal file
7
example/heat.yml
Normal file
@ -0,0 +1,7 @@
|
||||
- project:
|
||||
name: heat
|
||||
github-org: heat-api
|
||||
node: oneiric
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
43
example/horizon.yml
Normal file
43
example/horizon.yml
Normal file
@ -0,0 +1,43 @@
|
||||
- project:
|
||||
name: horizon
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- openstack-publish-jobs
|
||||
|
||||
- job:
|
||||
name: gate-horizon-selenium
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack/horizon
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- selenium
|
34
example/jenkins-job-builder.yml
Normal file
34
example/jenkins-job-builder.yml
Normal file
@ -0,0 +1,34 @@
|
||||
- project:
|
||||
name: jenkins-job-builder
|
||||
github-org: openstack
|
||||
node: precise
|
||||
|
||||
# TODO: standardize
|
||||
#jobs:
|
||||
# - gate-{name}-merge
|
||||
|
||||
- job:
|
||||
name: gate-jenkins-job-builder-merge
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/jenkins-job-builder
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
10
example/keystone.yml
Normal file
10
example/keystone.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: keystone
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- openstack-publish-jobs
|
115
example/macros.yml
Normal file
115
example/macros.yml
Normal file
@ -0,0 +1,115 @@
|
||||
- builder:
|
||||
name: gerrit_git_prep
|
||||
builders:
|
||||
- shell: "/usr/local/jenkins/slave_scripts/gerrit-git-prep.sh review.openstack.org"
|
||||
|
||||
- builder:
|
||||
name: coverage
|
||||
builders:
|
||||
- shell: "/usr/local/jenkins/slave_scripts/run-cover.sh"
|
||||
|
||||
- builder:
|
||||
name: docs
|
||||
builders:
|
||||
- shell: "/usr/local/jenkins/slave_scripts/run-docs.sh"
|
||||
|
||||
- builder:
|
||||
name: maven_test
|
||||
builders:
|
||||
- shell: "mvn test"
|
||||
|
||||
- builder:
|
||||
name: maven_package
|
||||
builders:
|
||||
- shell: "mvn package"
|
||||
|
||||
- builder:
|
||||
name: gerrit_package
|
||||
builders:
|
||||
- shell: "/usr/local/jenkins/slave_scripts/package-gerrit.sh"
|
||||
|
||||
- builder:
|
||||
name: gerrit_preclean
|
||||
#TODO: multiline:
|
||||
builders:
|
||||
- shell: "#!/bin/bash -xe\nrm -fr ~/.m2\nrm -fr ~/.java\n./tools/version.sh --release"
|
||||
|
||||
- builder:
|
||||
name: gerrit_postrun
|
||||
builders:
|
||||
- shell: "./tools/version.sh --reset"
|
||||
|
||||
- builder:
|
||||
name: pep8
|
||||
builders:
|
||||
- shell: "set -o pipefail ; tox -v -epep8 | tee pep8.txt ; set +o pipefail"
|
||||
|
||||
- builder:
|
||||
name: pyflakes
|
||||
builders:
|
||||
- shell: "tox -v -epyflakes"
|
||||
|
||||
- builder:
|
||||
name: puppet_syntax
|
||||
builders:
|
||||
# TODO: remove blank line
|
||||
- shell: |
|
||||
|
||||
find . -iname *.pp | xargs puppet parser validate --modulepath=`pwd`/modules
|
||||
for f in `find . -iname *.erb` ; do
|
||||
erb -x -T '-' $f | ruby -c
|
||||
done
|
||||
|
||||
- builder:
|
||||
name: selenium
|
||||
builders:
|
||||
- shell: "/usr/local/jenkins/slave_scripts/run-selenium.sh"
|
||||
|
||||
- builder:
|
||||
name: python26
|
||||
builders:
|
||||
- shell: "/usr/local/jenkins/slave_scripts/run-tox.sh 26"
|
||||
- something:
|
||||
arg: value
|
||||
|
||||
- builder:
|
||||
name: python27
|
||||
builders:
|
||||
- shell: "/usr/local/jenkins/slave_scripts/run-tox.sh 27"
|
||||
|
||||
- builder:
|
||||
name: python26_essex
|
||||
builders:
|
||||
- shell: "/usr/local/jenkins/slave_scripts/run-tox.sh 26-essex"
|
||||
|
||||
- builder:
|
||||
name: python27_essex
|
||||
builders:
|
||||
- shell: "/usr/local/jenkins/slave_scripts/run-tox.sh 27-essex"
|
||||
|
||||
- builder:
|
||||
name: tarball
|
||||
builders:
|
||||
- shell: "/usr/local/jenkins/slave_scripts/create-tarball.sh {project}"
|
||||
|
||||
# ======================================================================
|
||||
|
||||
- publisher:
|
||||
name: tarball
|
||||
publishers:
|
||||
- archive:
|
||||
artifacts: 'dist/*.tar.gz'
|
||||
- scp:
|
||||
site: '{site}'
|
||||
source: 'dist/*.tar.gz'
|
||||
target: 'tarballs/{project}/'
|
||||
|
||||
- publisher:
|
||||
name: war
|
||||
publishers:
|
||||
- archive:
|
||||
artifacts: '{warfile}'
|
||||
- scp:
|
||||
site: '{site}'
|
||||
source: '{warfile}'
|
||||
target: '{target}'
|
82
example/mraas.yml
Normal file
82
example/mraas.yml
Normal file
@ -0,0 +1,82 @@
|
||||
- project:
|
||||
name: MRaaS
|
||||
github-org: stackforge
|
||||
node: precise
|
||||
|
||||
- job:
|
||||
name: gate-MRaaS-merge
|
||||
concurrent: false
|
||||
node: oneiric
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/stackforge/MRaaS
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- gerrit:
|
||||
triggerOnPatchsetUploadedEvent: 'false'
|
||||
triggerOnChangeMergedEvent: 'false'
|
||||
triggerOnCommentAddedEvent: 'true'
|
||||
triggerOnRefUpdatedEvent: 'false'
|
||||
triggerApprovalCategory: 'APRV'
|
||||
triggerApprovalValue: 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.'
|
||||
projects:
|
||||
- projectCompareType: 'PLAIN'
|
||||
projectPattern: 'stackforge/MRaaS'
|
||||
branchCompareType: 'ANT'
|
||||
branchPattern: '**'
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
|
||||
|
||||
- job:
|
||||
name: check-MRaaS-merge
|
||||
concurrent: false
|
||||
node: oneiric
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/stackforge/MRaaS
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- gerrit:
|
||||
triggerOnPatchsetUploadedEvent: 'true'
|
||||
triggerOnChangeMergedEvent: 'false'
|
||||
triggerOnCommentAddedEvent: 'false'
|
||||
triggerOnRefUpdatedEvent: 'false'
|
||||
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.'
|
||||
projects:
|
||||
- projectCompareType: 'PLAIN'
|
||||
projectPattern: 'stackforge/MRaaS'
|
||||
branchCompareType: 'ANT'
|
||||
branchPattern: '**'
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
12
example/nova.yml
Normal file
12
example/nova.yml
Normal file
@ -0,0 +1,12 @@
|
||||
- project:
|
||||
name: nova
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- python-diablo-bitrot-jobs
|
||||
- python-essex-bitrot-jobs
|
||||
- openstack-publish-jobs
|
63
example/openstack-ci-puppet.yml
Normal file
63
example/openstack-ci-puppet.yml
Normal file
@ -0,0 +1,63 @@
|
||||
- project:
|
||||
name: ci-puppet
|
||||
github-org: openstack
|
||||
node: precise
|
||||
|
||||
# TODO: standardize
|
||||
#jobs:
|
||||
# - gate-{name}-merge
|
||||
|
||||
- job:
|
||||
name: gate-ci-puppet-merge
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack/openstack-ci-puppet
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
|
||||
|
||||
- job:
|
||||
name: gate-ci-puppet-syntax
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack/openstack-ci-puppet
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- puppet_syntax
|
||||
- pyflakes
|
10
example/openstack-common.yml
Normal file
10
example/openstack-common.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: openstack-common
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- openstack-publish-jobs
|
87
example/openstack-publish-jobs.yml
Normal file
87
example/openstack-publish-jobs.yml
Normal file
@ -0,0 +1,87 @@
|
||||
- job-template:
|
||||
name: '{name}-docs'
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- docs
|
||||
|
||||
publishers:
|
||||
- ftp:
|
||||
site: '{doc-publisher-site}'
|
||||
source: 'doc/build/html/**'
|
||||
target: 'developer/{name}'
|
||||
remove-prefix: 'doc/build/html'
|
||||
excludes: ''
|
||||
|
||||
- job-template:
|
||||
name: '{name}-tarball'
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- tarball:
|
||||
project: '{name}'
|
||||
|
||||
publishers:
|
||||
- tarball:
|
||||
project: '{name}'
|
||||
site: '{tarball-publisher-site}'
|
||||
|
||||
- job-group:
|
||||
name: openstack-publish-jobs
|
||||
jobs:
|
||||
- '{name}-docs'
|
||||
- '{name}-tarball'
|
10
example/pbr.yml
Normal file
10
example/pbr.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: pbr
|
||||
github-org: openstack-dev
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- pypi-jobs
|
85
example/pypi-jobs.yml
Normal file
85
example/pypi-jobs.yml
Normal file
@ -0,0 +1,85 @@
|
||||
- job-template:
|
||||
name: '{name}-sdist-tarball'
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- shell: |
|
||||
#!/bin/bash -xe
|
||||
BRANCH=$GERRIT_REFNAME
|
||||
BRANCH_PATH=`echo $BRANCH | tr / -`
|
||||
|
||||
tox -v -evenv python setup.py sdist
|
||||
cp dist/* dist/{name}-$BRANCH_PATH.tar.gz
|
||||
|
||||
publishers:
|
||||
- tarball:
|
||||
project: '{name}'
|
||||
site: '{tarball-publisher-site}'
|
||||
|
||||
|
||||
- job-template:
|
||||
name: '{name}-pypi'
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: pypi
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- shell: tox -v -evenv python setup.py sdist upload
|
||||
|
||||
publishers:
|
||||
- tarball:
|
||||
project: '{name}'
|
||||
site: '{tarball-publisher-site}'
|
||||
|
||||
- job-group:
|
||||
name: pypi-jobs
|
||||
jobs:
|
||||
- '{name}-docs'
|
||||
- '{name}-sdist-tarball'
|
||||
- '{name}-pypi'
|
64
example/pypi-mirror.yml
Normal file
64
example/pypi-mirror.yml
Normal file
@ -0,0 +1,64 @@
|
||||
- project:
|
||||
name: pypi-mirror
|
||||
github-org: openstack-ci
|
||||
node: precise
|
||||
|
||||
# TODO: standardize
|
||||
#jobs:
|
||||
# - gate-{name}-merge
|
||||
# - gate-{name}-pyflakes
|
||||
|
||||
- job:
|
||||
name: gate-pypi-mirror-merge
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/pypi-mirror
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
|
||||
- job:
|
||||
name: gate-pypi-mirror-pyflakes
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/pypi-mirror
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- pyflakes
|
140
example/python-bitrot-jobs.yml
Normal file
140
example/python-bitrot-jobs.yml
Normal file
@ -0,0 +1,140 @@
|
||||
- job-template:
|
||||
name: 'periodic-{name}-python26-{branch-name}'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- timed: '@daily'
|
||||
|
||||
builders:
|
||||
- python26
|
||||
|
||||
scm:
|
||||
- git:
|
||||
url: 'git://github.com/{github-org}/{name}.git'
|
||||
branches:
|
||||
- 'origin/{branch}'
|
||||
|
||||
# >= precise does not have python2.6
|
||||
node: oneiric
|
||||
|
||||
|
||||
- job-template:
|
||||
name: 'periodic-{name}-python27-{branch-name}'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- timed: '@daily'
|
||||
|
||||
builders:
|
||||
- python27
|
||||
|
||||
scm:
|
||||
- git:
|
||||
url: 'git://github.com/{github-org}/{name}.git'
|
||||
branches:
|
||||
- 'origin/{branch}'
|
||||
|
||||
node: '{node}'
|
||||
|
||||
|
||||
- job-template:
|
||||
name: 'periodic-{name}-docs-{branch-name}'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- timed: '@daily'
|
||||
|
||||
builders:
|
||||
- docs
|
||||
|
||||
scm:
|
||||
- git:
|
||||
url: 'git://github.com/{github-org}/{name}.git'
|
||||
branches:
|
||||
- 'origin/{branch}'
|
||||
|
||||
node: '{node}'
|
||||
|
||||
|
||||
- job-group:
|
||||
name: python-diablo-bitrot-jobs
|
||||
branch: 'stable/diablo'
|
||||
branch-name: 'stable-diablo'
|
||||
node: oneiric
|
||||
jobs:
|
||||
- 'periodic-{name}-python26-{branch-name}'
|
||||
- 'periodic-{name}-python27-{branch-name}'
|
||||
- 'periodic-{name}-docs-{branch-name}'
|
||||
|
||||
- job-group:
|
||||
name: python-essex-bitrot-jobs
|
||||
branch: 'stable/essex'
|
||||
branch-name: 'stable-essex'
|
||||
node: precise
|
||||
jobs:
|
||||
- 'periodic-{name}-python26-{branch-name}'
|
||||
- 'periodic-{name}-python27-{branch-name}'
|
||||
- 'periodic-{name}-docs-{branch-name}'
|
10
example/python-cinderclient.yml
Normal file
10
example/python-cinderclient.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: python-cinderclient
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- pypi-jobs
|
10
example/python-glanceclient.yml
Normal file
10
example/python-glanceclient.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: python-glanceclient
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- pypi-jobs
|
267
example/python-jobs.yml
Normal file
267
example/python-jobs.yml
Normal file
@ -0,0 +1,267 @@
|
||||
- job-template:
|
||||
name: '{name}-coverage'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- coverage
|
||||
|
||||
publishers:
|
||||
- coverage
|
||||
|
||||
node: '{node}'
|
||||
|
||||
|
||||
- job-template:
|
||||
name: 'gate-{name}-pep8'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- pep8
|
||||
|
||||
publishers:
|
||||
- pep8
|
||||
|
||||
node: '{node}'
|
||||
|
||||
|
||||
- job-template:
|
||||
name: 'gate-{name}-python26'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- python26
|
||||
|
||||
# >= precise does not have python2.6
|
||||
node: oneiric
|
||||
|
||||
|
||||
- job-template:
|
||||
name: 'gate-{name}-python27'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
parameters:
|
||||
- label:
|
||||
name: NODE_LABEL
|
||||
description: Label of node to use for this build
|
||||
default: '{node}'
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- python27
|
||||
|
||||
node: '{node}'
|
||||
|
||||
|
||||
- job-template:
|
||||
name: 'gate-{name}-merge'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
|
||||
node: '{node}'
|
||||
|
||||
|
||||
- job-template:
|
||||
name: 'gate-{name}-docs'
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- docs
|
||||
|
||||
node: '{node}'
|
||||
|
||||
|
||||
- job-template:
|
||||
name: 'gate-{name}-pyflakes'
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: 'https://github.com/{github-org}/{name}'
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- pyflakes
|
||||
|
||||
|
||||
- job-group:
|
||||
name: python-jobs
|
||||
jobs:
|
||||
- '{name}-coverage'
|
||||
- 'gate-{name}-merge'
|
||||
- 'gate-{name}-pep8'
|
||||
- 'gate-{name}-python26'
|
||||
- 'gate-{name}-python27'
|
||||
- 'gate-{name}-docs'
|
||||
# pyflakes isn't standard
|
10
example/python-keystoneclient.yml
Normal file
10
example/python-keystoneclient.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: python-keystoneclient
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- pypi-jobs
|
10
example/python-novaclient.yml
Normal file
10
example/python-novaclient.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: python-novaclient
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- pypi-jobs
|
10
example/python-openstackclient.yml
Normal file
10
example/python-openstackclient.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: python-openstackclient
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- pypi-jobs
|
10
example/python-quantumclient.yml
Normal file
10
example/python-quantumclient.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: python-quantumclient
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- pypi-jobs
|
10
example/python-swiftclient.yml
Normal file
10
example/python-swiftclient.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: python-swiftclient
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: swift.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- pypi-jobs
|
10
example/quantum.yml
Normal file
10
example/quantum.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: quantum
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- openstack-publish-jobs
|
7
example/reddwarf.yml
Normal file
7
example/reddwarf.yml
Normal file
@ -0,0 +1,7 @@
|
||||
- project:
|
||||
name: reddwarf
|
||||
github-org: stackforge
|
||||
node: oneiric
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
34
example/requirements.yml
Normal file
34
example/requirements.yml
Normal file
@ -0,0 +1,34 @@
|
||||
- project:
|
||||
name: requirements
|
||||
github-org: openstack
|
||||
node: oneiric
|
||||
|
||||
# TODO: standardize
|
||||
#jobs:
|
||||
# - gate-{name}-merge
|
||||
|
||||
- job:
|
||||
name: gate-requirements-merge
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack/requirements
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
|
||||
node: precise
|
10
example/swift.yml
Normal file
10
example/swift.yml
Normal file
@ -0,0 +1,10 @@
|
||||
- project:
|
||||
name: swift
|
||||
github-org: openstack
|
||||
node: precise
|
||||
tarball-publisher-site: nova.openstack.org
|
||||
doc-publisher-site: docs.openstack.org
|
||||
|
||||
jobs:
|
||||
- python-jobs
|
||||
- openstack-publish-jobs
|
67
example/tempest.yml
Normal file
67
example/tempest.yml
Normal file
@ -0,0 +1,67 @@
|
||||
- project:
|
||||
name: tempest
|
||||
github-org: openstack
|
||||
node: precise
|
||||
|
||||
# TODO: standardize
|
||||
#jobs:
|
||||
# - gate-{name}-merge
|
||||
# - gate-{name}-pep8
|
||||
|
||||
- job:
|
||||
name: gate-tempest-merge
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/tempest
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
|
||||
node: precise
|
||||
|
||||
- job:
|
||||
name: gate-tempest-pep8
|
||||
concurrent: true
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/tempest
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- pep8
|
||||
|
||||
publishers:
|
||||
- pep8
|
||||
|
||||
node: precise
|
79
example/zuul.yml
Normal file
79
example/zuul.yml
Normal file
@ -0,0 +1,79 @@
|
||||
- project:
|
||||
name: zuul
|
||||
github-org: openstack-ci
|
||||
node: precise
|
||||
jobs:
|
||||
- python-jobs
|
||||
# TODO: standardize these
|
||||
#- gate-{name}-pyflakes
|
||||
#- '{name}-docs
|
||||
|
||||
- job:
|
||||
name: gate-zuul-pyflakes
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/zuul
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- pyflakes
|
||||
|
||||
|
||||
- job:
|
||||
name: zuul-docs
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
node: precise
|
||||
|
||||
properties:
|
||||
- github:
|
||||
url: https://github.com/openstack-ci/zuul
|
||||
- throttle:
|
||||
max-per-node: 0
|
||||
max-total: 0
|
||||
option: project
|
||||
enabled: false
|
||||
|
||||
wrappers:
|
||||
- timeout:
|
||||
timeout: 30
|
||||
fail: true
|
||||
- timestamps
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- docs
|
||||
|
||||
publishers:
|
||||
- scp:
|
||||
site: '173.203.107.207'
|
||||
source: 'doc/build/html/**/*'
|
||||
target: 'ci/zuul'
|
||||
keep-hierarchy: true
|
47
jenkins-jobs
Executable file
47
jenkins-jobs
Executable file
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import jenkins_jobs.builder
|
||||
import argparse
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
subparser = parser.add_subparsers(help='update, test or delete job',
|
||||
dest='command')
|
||||
parser_update = subparser.add_parser('update')
|
||||
parser_update.add_argument('path', help='Path to YAML file or directory')
|
||||
parser_update.add_argument('name', help='name of job')
|
||||
parser_test = subparser.add_parser('test')
|
||||
parser_test.add_argument('path', help='Path to YAML file or directory')
|
||||
parser_test.add_argument('-o', dest='output_dir', help='Path to output XML')
|
||||
parser_test.add_argument('name', help='name of job', nargs='?')
|
||||
parser_delete = subparser.add_parser('delete')
|
||||
parser_delete.add_argument('name', help='name of job')
|
||||
parser.add_argument('--conf', dest='conf', help='Configuration file')
|
||||
options = parser.parse_args()
|
||||
|
||||
if options.conf:
|
||||
conf = options.conf
|
||||
else:
|
||||
conf = 'jenkins_jobs.ini'
|
||||
|
||||
if not options.command == 'test':
|
||||
conffp = open(conf, 'r')
|
||||
config = ConfigParser.ConfigParser()
|
||||
config.readfp(conffp)
|
||||
else:
|
||||
config = {}
|
||||
|
||||
builder = jenkins_jobs.builder.Builder(config.get('jenkins','url'),
|
||||
config.get('jenkins','user'),
|
||||
config.get('jenkins','password'))
|
||||
|
||||
if options.command == 'delete':
|
||||
builder.delete_job()
|
||||
elif options.command == 'update':
|
||||
builder.update_job()
|
||||
elif options.command == 'test':
|
||||
builder.update_job(options.path, options.name,
|
||||
output_dir=options.output_dir)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
279
jenkins_jobs.py
279
jenkins_jobs.py
@ -1,279 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Manage jobs in Jenkins server
|
||||
|
||||
import os
|
||||
import argparse
|
||||
import hashlib
|
||||
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 modules
|
||||
|
||||
class JenkinsJobsException(Exception): pass
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
subparser = parser.add_subparsers(help='update, test or delete job', dest='command')
|
||||
parser_update = subparser.add_parser('update')
|
||||
parser_update.add_argument('file', help='YAML file for update')
|
||||
parser_update = subparser.add_parser('test')
|
||||
parser_update.add_argument('file', help='YAML file for test')
|
||||
parser_delete = subparser.add_parser('delete')
|
||||
parser_delete.add_argument('name', help='name of job')
|
||||
parser.add_argument('--conf', dest='conf', help='Configuration file')
|
||||
options = parser.parse_args()
|
||||
|
||||
if options.conf:
|
||||
conf = options.conf
|
||||
else:
|
||||
conf = 'jenkins_jobs.ini'
|
||||
|
||||
if not options.command == 'test':
|
||||
conffp = open(conf, 'r')
|
||||
config = ConfigParser.ConfigParser()
|
||||
config.readfp(conffp)
|
||||
|
||||
class YamlParser(object):
|
||||
def __init__(self, yfile):
|
||||
self.registry = ModuleRegistry()
|
||||
self.data = yaml.load_all(yfile)
|
||||
self.it = self.data.__iter__()
|
||||
self.job_name = None
|
||||
self.template_data = None
|
||||
self.current = None
|
||||
self.current_template = None
|
||||
self.template_it = None
|
||||
self.reading_template = False
|
||||
self.eof = False
|
||||
self.seek_next_xml()
|
||||
|
||||
def process_template(self):
|
||||
project_data = self.current['project']
|
||||
template_file = file('templates/' + project_data['template'] + '.yml', 'r')
|
||||
template = template_file.read()
|
||||
template_file.close()
|
||||
values = self.current['values'].iteritems()
|
||||
for key, value in values:
|
||||
key = '@' + key.upper() + '@'
|
||||
template = template.replace(key, value)
|
||||
template_steam = StringIO(template)
|
||||
self.template_data = yaml.load_all(template_steam)
|
||||
self.template_it = self.template_data.__iter__()
|
||||
self.reading_template = True
|
||||
|
||||
def get_next_xml(self):
|
||||
if not self.eof:
|
||||
if self.reading_template:
|
||||
data = XmlParser(self.current_template, self.registry)
|
||||
self.job_name = self.current_template['main']['name']
|
||||
else:
|
||||
data = XmlParser(self.current, self.registry)
|
||||
self.job_name = self.current['main']['name']
|
||||
self.seek_next_xml()
|
||||
return data
|
||||
else:
|
||||
raise JenkinsJobsException('End of file')
|
||||
|
||||
def seek_next_xml(self):
|
||||
if self.reading_template:
|
||||
try:
|
||||
self.current_template = self.template_it.next()
|
||||
return
|
||||
except StopIteration:
|
||||
self.reading_template = False
|
||||
try:
|
||||
self.current = self.it.next()
|
||||
except StopIteration:
|
||||
self.eof = True
|
||||
|
||||
if self.current.has_key('project'):
|
||||
self.process_template()
|
||||
self.current_template = self.template_it.next()
|
||||
|
||||
def get_name(self):
|
||||
return self.job_name
|
||||
|
||||
class ModuleRegistry(object):
|
||||
# TODO: make this extensible
|
||||
|
||||
def __init__(self):
|
||||
self.modules = []
|
||||
self.handlers = {}
|
||||
|
||||
for importer, modname, ispkg in pkgutil.iter_modules(modules.__path__):
|
||||
module = __import__('modules.'+modname, fromlist=['register'])
|
||||
register = getattr(module, 'register', None)
|
||||
if register:
|
||||
register(self)
|
||||
|
||||
def registerModule(self, mod):
|
||||
self.modules.append(mod)
|
||||
self.modules.sort(lambda a, b: cmp(a.sequence, b.sequence))
|
||||
|
||||
def registerHandler(self, category, name, method):
|
||||
cat_dict = self.handlers.get(category, {})
|
||||
if not cat_dict:
|
||||
self.handlers[category] = cat_dict
|
||||
cat_dict[name] = method
|
||||
|
||||
def getHandler(self, category, name):
|
||||
return self.handlers[category][name]
|
||||
|
||||
class XmlParser(object):
|
||||
def __init__(self, data, registry):
|
||||
self.data = data
|
||||
self.registry = registry
|
||||
self._build()
|
||||
|
||||
def _build(self):
|
||||
for module in self.registry.modules:
|
||||
if hasattr(module, 'root_xml'):
|
||||
element = module.root_xml(self.data)
|
||||
if element is not None:
|
||||
self.xml = element
|
||||
|
||||
for module in self.registry.modules:
|
||||
if hasattr(module, 'handle_data'):
|
||||
module.handle_data(self.data)
|
||||
|
||||
XML.SubElement(self.xml, 'actions')
|
||||
description = XML.SubElement(self.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"
|
||||
XML.SubElement(self.xml, 'keepDependencies').text = 'false'
|
||||
if self.data['main'].get('disabled'):
|
||||
XML.SubElement(self.xml, 'disabled').text = 'true'
|
||||
else:
|
||||
XML.SubElement(self.xml, 'disabled').text = 'false'
|
||||
XML.SubElement(self.xml, 'blockBuildWhenDownstreamBuilding').text = 'false'
|
||||
XML.SubElement(self.xml, 'blockBuildWhenUpstreamBuilding').text = 'false'
|
||||
if self.data['main'].get('concurrent'):
|
||||
XML.SubElement(self.xml, 'concurrentBuild').text = 'true'
|
||||
else:
|
||||
XML.SubElement(self.xml, 'concurrentBuild').text = 'false'
|
||||
|
||||
for module in self.registry.modules:
|
||||
if hasattr(module, 'gen_xml'):
|
||||
module.gen_xml(self.xml, self.data)
|
||||
|
||||
def md5(self):
|
||||
return hashlib.md5(self.output()).hexdigest()
|
||||
|
||||
# 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=' ')
|
||||
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 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):
|
||||
return True
|
||||
return False
|
||||
|
||||
def has_changed(self, job, md5):
|
||||
if self.data.has_key(job) and self.data[job] == md5:
|
||||
return False
|
||||
return True
|
||||
|
||||
class Jenkins(object):
|
||||
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 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 delete_job(self, job_name):
|
||||
if self.is_job(job_name):
|
||||
self.jenkins.delete_job(job_name)
|
||||
|
||||
def delete_job():
|
||||
remote_jenkins = Jenkins(config.get('jenkins','url'), config.get('jenkins','user'), config.get('jenkins','password'))
|
||||
remote_jenkins.delete_job(options.name)
|
||||
|
||||
def update_job(test = False):
|
||||
if os.path.isdir(options.file):
|
||||
files_to_process = [os.path.join(options.file, f)
|
||||
for f in os.listdir(options.file)]
|
||||
else:
|
||||
files_to_process = [options.file]
|
||||
cache = CacheStorage()
|
||||
if not test:
|
||||
remote_jenkins = Jenkins(config.get('jenkins','url'), config.get('jenkins','user'), config.get('jenkins','password'))
|
||||
for in_file in files_to_process:
|
||||
yparse = YamlParser(open(in_file, 'r'))
|
||||
while True:
|
||||
try:
|
||||
xml = yparse.get_next_xml()
|
||||
job = yparse.get_name()
|
||||
if test:
|
||||
print xml.output()
|
||||
continue
|
||||
md5 = xml.md5()
|
||||
if remote_jenkins.is_job(job) and not cache.is_cached(job):
|
||||
old_md5 = remote_jenkins.get_job_md5(job)
|
||||
cache.set(job, old_md5)
|
||||
|
||||
if cache.has_changed(job, md5):
|
||||
remote_jenkins.update_job(job, xml.output())
|
||||
cache.set(job, md5)
|
||||
except JenkinsJobsException:
|
||||
break
|
||||
|
||||
if options.command == 'delete':
|
||||
delete_job()
|
||||
elif options.command == 'update':
|
||||
update_job()
|
||||
elif options.command == 'test':
|
||||
update_job(True)
|
||||
|
274
jenkins_jobs/builder.py
Normal file
274
jenkins_jobs/builder.py
Normal file
@ -0,0 +1,274 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Manage jobs in Jenkins server
|
||||
|
||||
import os
|
||||
import hashlib
|
||||
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):
|
||||
self.registry = ModuleRegistry()
|
||||
self.data = {}
|
||||
self.jobs = []
|
||||
|
||||
def parse(self, fn):
|
||||
data = yaml.load(open(fn))
|
||||
for item in data:
|
||||
cls, dfn = item.items()[0]
|
||||
group = self.data.get(cls, {})
|
||||
name = dfn['name']
|
||||
group[name] = dfn
|
||||
self.data[cls] = group
|
||||
|
||||
def getJob(self, name):
|
||||
return self.data.get('job', {}).get(name, None)
|
||||
|
||||
def getJobGroup(self, name):
|
||||
return self.data.get('job-group', {}).get(name, None)
|
||||
|
||||
def getJobTemplate(self, name):
|
||||
return self.data.get('job-template', {}).get(name, None)
|
||||
|
||||
def generateXML(self):
|
||||
changed = True
|
||||
while changed:
|
||||
changed = False
|
||||
for module in self.registry.modules:
|
||||
if hasattr(module, 'handle_data'):
|
||||
if module.handle_data(self):
|
||||
changed = True
|
||||
|
||||
for job in self.data.get('job', {}).values():
|
||||
self.getXMLForJob(job)
|
||||
for project in self.data.get('project', {}).values():
|
||||
for jobname in project.get('jobs', []):
|
||||
job = self.getJob(jobname)
|
||||
if job:
|
||||
# Just naming an existing defined job
|
||||
continue
|
||||
# see if it's a job group
|
||||
group = self.getJobGroup(jobname)
|
||||
if group:
|
||||
for group_jobname in group['jobs']:
|
||||
job = self.getJob(group_jobname)
|
||||
if job:
|
||||
continue
|
||||
template = self.getJobTemplate(group_jobname)
|
||||
# Allow a group to override parameters set by a project
|
||||
d = {}
|
||||
d.update(project)
|
||||
d.update(group)
|
||||
# Except name, since the group's name is not useful
|
||||
d['name'] = project['name']
|
||||
if template:
|
||||
self.getXMLForTemplateJob(d, template)
|
||||
continue
|
||||
# see if it's a template
|
||||
template = self.getJobTemplate(jobname)
|
||||
if template:
|
||||
self.getXMLForTemplateJob(project, template)
|
||||
|
||||
def getXMLForTemplateJob(self, project, template):
|
||||
s = yaml.dump(template, default_flow_style=False)
|
||||
s = s.format(**project)
|
||||
data = yaml.load(s)
|
||||
self.getXMLForJob(data)
|
||||
|
||||
def getXMLForJob(self, data):
|
||||
kind = data.get('project-type', 'freestyle')
|
||||
for ep in pkg_resources.iter_entry_points(
|
||||
group='jenkins_jobs.projects', name=kind):
|
||||
Mod = ep.load()
|
||||
mod = Mod(self.registry)
|
||||
xml = mod.root_xml(data)
|
||||
self.gen_xml(xml, data)
|
||||
job = XmlJob(xml, data['name'])
|
||||
self.jobs.append(job)
|
||||
break
|
||||
|
||||
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"
|
||||
XML.SubElement(xml, 'keepDependencies').text = 'false'
|
||||
if data.get('disabled'):
|
||||
XML.SubElement(xml, 'disabled').text = 'true'
|
||||
else:
|
||||
XML.SubElement(xml, 'disabled').text = 'false'
|
||||
XML.SubElement(xml, 'blockBuildWhenDownstreamBuilding').text = 'false'
|
||||
XML.SubElement(xml, 'blockBuildWhenUpstreamBuilding').text = 'false'
|
||||
if data.get('concurrent'):
|
||||
XML.SubElement(xml, 'concurrentBuild').text = 'true'
|
||||
else:
|
||||
XML.SubElement(xml, 'concurrentBuild').text = 'false'
|
||||
|
||||
for module in self.registry.modules:
|
||||
if hasattr(module, 'gen_xml'):
|
||||
module.gen_xml(self, xml, data)
|
||||
|
||||
|
||||
class ModuleRegistry(object):
|
||||
# TODO: make this extensible
|
||||
|
||||
def __init__(self):
|
||||
self.modules = []
|
||||
self.handlers = {}
|
||||
|
||||
for entrypoint in pkg_resources.iter_entry_points(
|
||||
group='jenkins_jobs.modules'):
|
||||
Mod = entrypoint.load()
|
||||
mod = Mod(self)
|
||||
self.modules.append(mod)
|
||||
self.modules.sort(lambda a, b: cmp(a.sequence, b.sequence))
|
||||
|
||||
def registerHandler(self, category, name, method):
|
||||
cat_dict = self.handlers.get(category, {})
|
||||
if not cat_dict:
|
||||
self.handlers[category] = cat_dict
|
||||
cat_dict[name] = method
|
||||
|
||||
def getHandler(self, category, name):
|
||||
return self.handlers[category][name]
|
||||
|
||||
class XmlJob(object):
|
||||
def __init__(self, xml, name):
|
||||
self.xml = xml
|
||||
self.name = name
|
||||
|
||||
def md5(self):
|
||||
return hashlib.md5(self.output()).hexdigest()
|
||||
|
||||
# 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=' ')
|
||||
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 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):
|
||||
return True
|
||||
return False
|
||||
|
||||
def has_changed(self, job, md5):
|
||||
if self.data.has_key(job) and self.data[job] == md5:
|
||||
return False
|
||||
return True
|
||||
|
||||
class Jenkins(object):
|
||||
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 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 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):
|
||||
self.jenkins = Jenkins(jenkins_url, jenkins_user, jenkins_password)
|
||||
self.cache = CacheStorage()
|
||||
|
||||
def delete_job(self):
|
||||
self.jenkins.delete_job(options.name)
|
||||
|
||||
def update_job(self, fn, name=None, output_dir=None):
|
||||
if os.path.isdir(fn):
|
||||
files_to_process = [os.path.join(fn, f)
|
||||
for f in os.listdir(fn)
|
||||
if (f.endswith('.yml') or f.endswith('.yaml'))]
|
||||
else:
|
||||
files_to_process = [fn]
|
||||
parser = YamlParser()
|
||||
for in_file in files_to_process:
|
||||
parser.parse(in_file)
|
||||
parser.generateXML()
|
||||
|
||||
parser.jobs.sort(lambda a,b: cmp(a.name, b.name))
|
||||
for job in parser.jobs:
|
||||
if name and job.name != name:
|
||||
continue
|
||||
if output_dir:
|
||||
#print '='*70
|
||||
#print job.name
|
||||
#print '-'*70
|
||||
if name:
|
||||
print job.output()
|
||||
continue
|
||||
fn = os.path.join(output_dir, job.name)
|
||||
f = open(fn, 'w')
|
||||
f.write(job.output())
|
||||
f.close()
|
||||
continue
|
||||
md5 = job.md5()
|
||||
if (remote_jenkins.is_job(job.nam)
|
||||
and not self.cache.is_cached(job.name)):
|
||||
old_md5 = remote_jenkins.get_job_md5(job.name)
|
||||
self.cache.set(job.name, old_md5)
|
||||
|
||||
if self.cache.has_changed(job.name, md5):
|
||||
remote_jenkins.update_job(job.name, xml.output())
|
||||
self.cache.set(job.name, md5)
|
||||
|
||||
|
||||
|
0
jenkins_jobs/modules/__init__.py
Normal file
0
jenkins_jobs/modules/__init__.py
Normal file
@ -1,5 +1,4 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
# 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.
|
||||
@ -19,18 +18,14 @@
|
||||
# - node: 'oneiric'
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
import jenkins_jobs.modules.base
|
||||
|
||||
|
||||
def register(registry):
|
||||
mod = AssignedNode()
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class AssignedNode(object):
|
||||
class AssignedNode(jenkins_jobs.modules.base.Base):
|
||||
sequence = 40
|
||||
|
||||
def gen_xml(self, xml_parent, data):
|
||||
node = data['assignednode']['node']
|
||||
XML.SubElement(xml_parent, 'assignedNode').text = node
|
||||
XML.SubElement(xml_parent, 'canRoam').text = 'false'
|
||||
|
||||
def gen_xml(self, parser, xml_parent, data):
|
||||
node = data.get('node', None)
|
||||
if node:
|
||||
XML.SubElement(xml_parent, 'assignedNode').text = node
|
||||
XML.SubElement(xml_parent, 'canRoam').text = 'false'
|
58
jenkins_jobs/modules/base.py
Normal file
58
jenkins_jobs/modules/base.py
Normal file
@ -0,0 +1,58 @@
|
||||
# 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.
|
||||
|
||||
# Base class for a jenkins_jobs module
|
||||
|
||||
import pkg_resources
|
||||
import yaml
|
||||
|
||||
|
||||
class Base(object):
|
||||
sequence = 10
|
||||
|
||||
def __init__(self, registry):
|
||||
self.registry = registry
|
||||
|
||||
def _dispatch(self, component_type, component_list_type,
|
||||
parser, xml_parent,
|
||||
component, template_data={}):
|
||||
if isinstance(component, dict):
|
||||
# The component is a sigleton dictionary of name: dict(args)
|
||||
name, component_data = component.items()[0]
|
||||
if template_data:
|
||||
# Template data contains values that should be interpolated
|
||||
# into the component definition
|
||||
s = yaml.dump(component_data, default_flow_style=False)
|
||||
s = s.format(**template_data)
|
||||
component_data = yaml.load(s)
|
||||
else:
|
||||
# The component is a simple string name, eg "run-tests"
|
||||
name = component
|
||||
component_data = {}
|
||||
|
||||
# Look for a component function defined in an entry point
|
||||
for ep in pkg_resources.iter_entry_points(
|
||||
group='jenkins_jobs.{0}'.format(component_list_type), name=name):
|
||||
func = ep.load()
|
||||
func(parser, xml_parent, component_data)
|
||||
else:
|
||||
# Otherwise, see if it's defined as a macro
|
||||
component = parser.data.get(component_type, {}).get(name)
|
||||
if component:
|
||||
for b in component[component_list_type]:
|
||||
# Pass component_data in as template data to this function
|
||||
# so that if the macro is invoked with arguments,
|
||||
# the arguments are interpolated into the real defn.
|
||||
self._dispatch(component_type, component_list_type,
|
||||
parser, xml_parent, b, component_data)
|
63
jenkins_jobs/modules/builders.py
Normal file
63
jenkins_jobs/modules/builders.py
Normal file
@ -0,0 +1,63 @@
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for builders
|
||||
# To use add the folowing into your YAML:
|
||||
# builders:
|
||||
# - 'gerrit_git_prep'
|
||||
# - 'python26'
|
||||
|
||||
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')
|
||||
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'):
|
||||
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 = 'ALWAYS'
|
||||
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.text = 'false'
|
||||
|
||||
class Builders(jenkins_jobs.modules.base.Base):
|
||||
sequence = 60
|
||||
|
||||
def gen_xml(self, parser, xml_parent, data):
|
||||
for alias in ['prebuilders', 'builders', 'postbuilders']:
|
||||
if alias in data:
|
||||
builders = XML.SubElement(xml_parent, alias)
|
||||
for builder in data[alias]:
|
||||
self._dispatch('builder', 'builders',
|
||||
parser, builders, builder)
|
@ -1,5 +1,4 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
# 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.
|
||||
@ -22,23 +21,16 @@
|
||||
# artifactNumToKeep: -1
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
import jenkins_jobs.modules.base
|
||||
|
||||
|
||||
def register(registry):
|
||||
mod = LogRotate()
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class LogRotate(object):
|
||||
class LogRotate(jenkins_jobs.modules.base.Base):
|
||||
sequence = 10
|
||||
|
||||
def handle_data(self, data):
|
||||
self.data = data
|
||||
|
||||
def gen_xml(self, xml_parent, data):
|
||||
if self.data.has_key('logrotate'):
|
||||
def gen_xml(self, parser, xml_parent, data):
|
||||
if data.has_key('logrotate'):
|
||||
lr_xml = XML.SubElement(xml_parent, 'logRotator')
|
||||
logrotate = self.data['logrotate']
|
||||
logrotate = data['logrotate']
|
||||
lr_days = XML.SubElement(lr_xml, 'daysToKeep')
|
||||
lr_days.text = str(logrotate['daysToKeep'])
|
||||
lr_num = XML.SubElement(lr_xml, 'numToKeep')
|
@ -1,5 +1,4 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
# 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.
|
||||
@ -22,18 +21,12 @@
|
||||
# goals: 'test'
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
import jenkins_jobs.modules.base
|
||||
|
||||
|
||||
def register(registry):
|
||||
mod = Freestyle()
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class Freestyle(object):
|
||||
class Freestyle(jenkins_jobs.modules.base.Base):
|
||||
sequence = 0
|
||||
|
||||
def root_xml(self, data):
|
||||
if 'maven' in data:
|
||||
return None
|
||||
xml_parent = XML.Element('project')
|
||||
return xml_parent
|
@ -1,5 +1,4 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
# 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.
|
||||
@ -22,14 +21,9 @@
|
||||
# goals: 'test'
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
import jenkins_jobs.modules.base
|
||||
|
||||
|
||||
def register(registry):
|
||||
mod = Maven()
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class Maven(object):
|
||||
class Maven(jenkins_jobs.modules.base.Base):
|
||||
sequence = 0
|
||||
|
||||
def root_xml(self, data):
|
117
jenkins_jobs/modules/properties.py
Normal file
117
jenkins_jobs/modules/properties.py
Normal file
@ -0,0 +1,117 @@
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for job properties
|
||||
# No additional YAML needed
|
||||
|
||||
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')
|
||||
XML.SubElement(throttle, 'maxConcurrentPerNode').text = str(
|
||||
data.get('max-per-node'))
|
||||
XML.SubElement(throttle, 'maxConcurrentTotal').text = str(
|
||||
data.get('max-total'))
|
||||
# TODO: What's "categories"?
|
||||
#XML.SubElement(throttle, 'categories')
|
||||
if data.get('enabled', True):
|
||||
XML.SubElement(throttle, 'throttleEnabled').text = 'true'
|
||||
else:
|
||||
XML.SubElement(throttle, 'throttleEnabled').text = 'false'
|
||||
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:
|
||||
security = XML.SubElement(xml_parent,
|
||||
'hudson.security.AuthorizationMatrixProperty')
|
||||
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']
|
||||
XML.SubElement(pdef, 'description').text = data['description']
|
||||
if do_default:
|
||||
default = data.get('default', None)
|
||||
if default:
|
||||
XML.SubElement(pdef, 'defaultValue').text = default
|
||||
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')
|
||||
XML.SubElement(endpoint_element, 'protocol').text = 'HTTP'
|
||||
XML.SubElement(endpoint_element, 'url').text = data['url']
|
||||
|
||||
|
||||
class Properties(jenkins_jobs.modules.base.Base):
|
||||
sequence = 20
|
||||
|
||||
def gen_xml(self, parser, xml_parent, data):
|
||||
properties = XML.SubElement(xml_parent, 'properties')
|
||||
|
||||
for prop in data.get('properties', []):
|
||||
self._dispatch('property', 'properties',
|
||||
parser, properties, prop)
|
||||
|
||||
parameters = data.get('parameters', [])
|
||||
if parameters:
|
||||
pdefp = XML.SubElement(properties,
|
||||
'hudson.model.ParametersDefinitionProperty')
|
||||
pdefs = XML.SubElement(pdefp, 'parameterDefinitions')
|
||||
for param in parameters:
|
||||
self._dispatch('parameter', 'parameters',
|
||||
parser, pdefs, param)
|
||||
|
||||
notifications = data.get('notifications', [])
|
||||
if notifications:
|
||||
notify_element = XML.SubElement(properties,
|
||||
'com.tikal.hudson.plugins.notification.HudsonNotificationProperty')
|
||||
endpoints_element = XML.SubElement(notify_element, 'endpoints')
|
||||
|
||||
for endpoint in notifications:
|
||||
self._dispatch('notification', 'notifications',
|
||||
parser, endpoints_element, endpoint)
|
||||
|
290
jenkins_jobs/modules/publishers.py
Normal file
290
jenkins_jobs/modules/publishers.py
Normal file
@ -0,0 +1,290 @@
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for coverage publishers
|
||||
# No additional YAML needed
|
||||
|
||||
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')
|
||||
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):
|
||||
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 project_def.has_key('predefined_parameters'):
|
||||
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):
|
||||
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'
|
||||
|
||||
|
||||
# Jenkins Job module for publishing via ftp
|
||||
# publish:
|
||||
# site: 'docs.openstack.org'
|
||||
# remote_dir: 'dest/dir'
|
||||
# source_files: 'base/source/dir/**'
|
||||
# remove_prefix: 'base/source/dir'
|
||||
# excludes: '**/*.exludedfiletype'
|
||||
#
|
||||
# This will upload everything under $workspace/base/source/dir to
|
||||
# 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: '
|
||||
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': '../..'})
|
||||
|
||||
# Jenkins Job module for coverage publishers
|
||||
# To use you add the following into your YAML:
|
||||
# publisher:
|
||||
# results: 'nosetests.xml'
|
||||
|
||||
def junit(parser, xml_parent, data):
|
||||
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 _pep8_add_entry(xml_parent, name):
|
||||
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 = '10'
|
||||
XML.SubElement(tconfig, 'max').text = '999'
|
||||
XML.SubElement(tconfig, 'unstable').text = '999'
|
||||
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')
|
||||
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')
|
||||
|
||||
_pep8_add_entry(configs, 'checkstyle')
|
||||
_pep8_add_entry(configs, 'codenarc')
|
||||
_pep8_add_entry(configs, 'cpd')
|
||||
_pep8_add_entry(configs, 'cpplint')
|
||||
_pep8_add_entry(configs, 'csslint')
|
||||
_pep8_add_entry(configs, 'findbugs')
|
||||
_pep8_add_entry(configs, 'fxcop')
|
||||
_pep8_add_entry(configs, 'gendarme')
|
||||
_pep8_add_entry(configs, 'jcreport')
|
||||
_pep8_add_entry(configs, 'jslint')
|
||||
|
||||
entry = XML.SubElement(configs, 'entry')
|
||||
XML.SubElement(entry, 'string').text = 'pep8'
|
||||
tconfig = XML.SubElement(entry, 'hudson.plugins.violations.TypeConfig')
|
||||
XML.SubElement(tconfig, 'type').text = 'pep8'
|
||||
XML.SubElement(tconfig, 'min').text = '0'
|
||||
XML.SubElement(tconfig, 'max').text = '1'
|
||||
XML.SubElement(tconfig, 'unstable').text = '1'
|
||||
XML.SubElement(tconfig, 'usePattern').text = 'false'
|
||||
XML.SubElement(tconfig, 'pattern').text = '**/pep8.txt'
|
||||
|
||||
_pep8_add_entry(configs, 'pmd')
|
||||
_pep8_add_entry(configs, 'pylint')
|
||||
_pep8_add_entry(configs, 'simian')
|
||||
_pep8_add_entry(configs, 'stylecop')
|
||||
|
||||
XML.SubElement(config, 'limit').text = '100'
|
||||
XML.SubElement(config, 'sourcePathPattern')
|
||||
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:
|
||||
# site: 'openstack-ci.openstack.org'
|
||||
# source: 'doc/build/html/**/*'
|
||||
# target_path: 'ci/zuul'
|
||||
# keep_heirarchy: 'true'
|
||||
|
||||
def scp(parser, xml_parent, data):
|
||||
site = data['site']
|
||||
scp = XML.SubElement(xml_parent,
|
||||
'be.certipost.hudson.plugin.SCPRepositoryPublisher')
|
||||
XML.SubElement(scp, 'siteName').text = site
|
||||
entries = XML.SubElement(scp, 'entries')
|
||||
entry = XML.SubElement(entries, 'be.certipost.hudson.plugin.Entry')
|
||||
XML.SubElement(entry, 'filePath').text = data['target']
|
||||
XML.SubElement(entry, 'sourceFile').text = data['source']
|
||||
if data.get('keep-hierarchy', False):
|
||||
XML.SubElement(entry, 'keepHierarchy').text = 'true'
|
||||
else:
|
||||
XML.SubElement(entry, 'keepHierarchy').text = 'false'
|
||||
|
||||
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)
|
||||
|
||||
|
||||
|
72
jenkins_jobs/modules/scm.py
Normal file
72
jenkins_jobs/modules/scm.py
Normal file
@ -0,0 +1,72 @@
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for scm
|
||||
# To use add the folowing into your YAML:
|
||||
# scm:
|
||||
# scm: 'true'
|
||||
# or
|
||||
# scm: 'false'
|
||||
|
||||
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'})
|
||||
XML.SubElement(scm, 'configVersion').text = '2'
|
||||
user = XML.SubElement(scm, 'userRemoteConfigs')
|
||||
huser = XML.SubElement(user, 'hudson.plugins.git.UserRemoteConfig')
|
||||
XML.SubElement(huser, 'name').text = 'origin'
|
||||
XML.SubElement(huser, 'refspec').text = \
|
||||
'+refs/heads/*:refs/remotes/origin/*'
|
||||
XML.SubElement(huser, 'url').text = data['url']
|
||||
xml_branches = XML.SubElement(scm, 'branches')
|
||||
branches = data.get('branches', ['**'])
|
||||
for branch in branches:
|
||||
bspec = XML.SubElement(xml_branches, 'hudson.plugins.git.BranchSpec')
|
||||
XML.SubElement(bspec, 'name').text = branch
|
||||
XML.SubElement(scm, 'disableSubmodules').text = 'false'
|
||||
XML.SubElement(scm, 'recursiveSubmodules').text = 'false'
|
||||
XML.SubElement(scm, 'doGenerateSubmoduleConfigurations').text = 'false'
|
||||
XML.SubElement(scm, 'authorOrCommitter').text = 'false'
|
||||
XML.SubElement(scm, 'clean').text = 'false'
|
||||
XML.SubElement(scm, 'wipeOutWorkspace').text = 'true'
|
||||
XML.SubElement(scm, 'pruneBranches').text = 'false'
|
||||
XML.SubElement(scm, 'remotePoll').text = 'false'
|
||||
XML.SubElement(scm, 'buildChooser',
|
||||
{'class':'hudson.plugins.git.util.DefaultBuildChooser'})
|
||||
XML.SubElement(scm, 'gitTool').text = 'Default'
|
||||
XML.SubElement(scm, 'submoduleCfg', {'class':'list'})
|
||||
XML.SubElement(scm, 'relativeTargetDir')
|
||||
XML.SubElement(scm, 'reference')
|
||||
XML.SubElement(scm, 'excludedRegions')
|
||||
XML.SubElement(scm, 'excludedUsers')
|
||||
XML.SubElement(scm, 'gitConfigName')
|
||||
XML.SubElement(scm, 'gitConfigEmail')
|
||||
XML.SubElement(scm, 'skipTag').text = 'false'
|
||||
XML.SubElement(scm, 'scmName')
|
||||
|
||||
class SCM(jenkins_jobs.modules.base.Base):
|
||||
sequence = 30
|
||||
|
||||
def gen_xml(self, parser, xml_parent, data):
|
||||
scms = data.get('scm', [])
|
||||
if scms:
|
||||
for scm in data.get('scm', []):
|
||||
self._dispatch('scm', 'scm',
|
||||
parser, xml_parent, scm)
|
||||
else:
|
||||
XML.SubElement(xml_parent, 'scm', {'class':'hudson.scm.NullSCM'})
|
||||
|
124
jenkins_jobs/modules/triggers.py
Normal file
124
jenkins_jobs/modules/triggers.py
Normal file
@ -0,0 +1,124 @@
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for gerrit triggers
|
||||
# To use add the following into your YAML:
|
||||
# trigger:
|
||||
# triggerOnPatchsetUploadedEvent: 'false'
|
||||
# triggerOnChangeMergedEvent: 'false'
|
||||
# triggerOnCommentAddedEvent: 'true'
|
||||
# triggerOnRefUpdatedEvent: 'false'
|
||||
# triggerApprovalCategory: 'APRV'
|
||||
# triggerApprovalValue: 1
|
||||
# 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.'
|
||||
# projects:
|
||||
# - projectCompareType: 'PLAIN'
|
||||
# projectPattern: 'openstack/nova'
|
||||
# branchCompareType: 'ANT'
|
||||
# branchPattern: '**'
|
||||
# - projectCompareType: 'PLAIN'
|
||||
# projectPattern: 'openstack/glance'
|
||||
# branchCompareType: 'ANT'
|
||||
# branchPattern: '**'
|
||||
# ...
|
||||
#
|
||||
# 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,
|
||||
'com.sonyericsson.hudson.plugins.gerrit.trigger.'
|
||||
'hudsontrigger.GerritTrigger')
|
||||
XML.SubElement(gtrig, 'spec')
|
||||
gprojects = XML.SubElement(gtrig, 'gerritProjects')
|
||||
for project in projects:
|
||||
gproj = XML.SubElement(gprojects,
|
||||
'com.sonyericsson.hudson.plugins.gerrit.'
|
||||
'trigger.hudsontrigger.data.GerritProject')
|
||||
XML.SubElement(gproj, 'compareType').text = \
|
||||
project['projectCompareType']
|
||||
XML.SubElement(gproj, 'pattern').text = project['projectPattern']
|
||||
branches = XML.SubElement(gproj, 'branches')
|
||||
gbranch = XML.SubElement(branches, 'com.sonyericsson.hudson.plugins.'
|
||||
'gerrit.trigger.hudsontrigger.data.Branch')
|
||||
XML.SubElement(gbranch, 'compareType').text = \
|
||||
project['branchCompareType']
|
||||
XML.SubElement(gbranch, 'pattern').text = project['branchPattern']
|
||||
XML.SubElement(gtrig, 'silentMode').text = 'false'
|
||||
XML.SubElement(gtrig, 'escapeQuotes').text = 'true'
|
||||
XML.SubElement(gtrig, 'triggerOnPatchsetUploadedEvent').text = \
|
||||
data['triggerOnPatchsetUploadedEvent']
|
||||
XML.SubElement(gtrig, 'triggerOnChangeMergedEvent').text = \
|
||||
data['triggerOnChangeMergedEvent']
|
||||
XML.SubElement(gtrig, 'triggerOnCommentAddedEvent').text = \
|
||||
data['triggerOnCommentAddedEvent']
|
||||
XML.SubElement(gtrig, 'triggerOnRefUpdatedEvent').text = \
|
||||
data['triggerOnRefUpdatedEvent']
|
||||
if data.has_key('overrideVotes') and data['overrideVotes'] == 'true':
|
||||
XML.SubElement(gtrig, 'gerritBuildSuccessfulVerifiedValue').text = \
|
||||
str(data['gerritBuildSuccessfulVerifiedValue'])
|
||||
XML.SubElement(gtrig, 'gerritBuildFailedVerifiedValue').text = \
|
||||
str(data['gerritBuildFailedVerifiedValue'])
|
||||
if data['triggerOnCommentAddedEvent'] == 'true':
|
||||
XML.SubElement(gtrig, 'commentAddedTriggerApprovalCategory').text = \
|
||||
data['triggerApprovalCategory']
|
||||
XML.SubElement(gtrig, 'commentAddedTriggerApprovalValue').text = \
|
||||
str(data['triggerApprovalValue'])
|
||||
XML.SubElement(gtrig, 'buildStartMessage')
|
||||
XML.SubElement(gtrig, 'buildFailureMessage').text = data['failureMessage']
|
||||
XML.SubElement(gtrig, 'buildSuccessfulMessage')
|
||||
XML.SubElement(gtrig, 'buildUnstableMessage')
|
||||
XML.SubElement(gtrig, 'customUrl')
|
||||
|
||||
# Jenkins Job module for scm polling triggers
|
||||
# To use add the following into your YAML:
|
||||
# trigger:
|
||||
# pollscm: '@midnight'
|
||||
# or
|
||||
# pollscm: '*/15 * * * *'
|
||||
|
||||
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:
|
||||
# timed: '@midnight'
|
||||
# or
|
||||
# timed: '*/15 * * * *'
|
||||
|
||||
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
|
||||
|
||||
def gen_xml(self, parser, xml_parent, data):
|
||||
triggers = data.get('triggers', [])
|
||||
if not triggers:
|
||||
return
|
||||
|
||||
trig_e = XML.SubElement(xml_parent, 'triggers', {'class':'vector'})
|
||||
for trigger in triggers:
|
||||
self._dispatch('trigger', 'triggers',
|
||||
parser, trig_e, trigger)
|
||||
|
51
jenkins_jobs/modules/wrappers.py
Normal file
51
jenkins_jobs/modules/wrappers.py
Normal file
@ -0,0 +1,51 @@
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for wrappers
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
import jenkins_jobs.modules.base
|
||||
|
||||
|
||||
def timeout(parser, xml_parent, data):
|
||||
twrapper = XML.SubElement(xml_parent,
|
||||
'hudson.plugins.build__timeout.BuildTimeoutWrapper')
|
||||
tminutes = XML.SubElement(twrapper, 'timeoutMinutes')
|
||||
tminutes.text = str(data['timeout'])
|
||||
failbuild = XML.SubElement(twrapper, 'failBuild')
|
||||
fail = data.get('fail', False)
|
||||
if fail:
|
||||
failbuild.text = 'true'
|
||||
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')
|
||||
|
||||
|
||||
class Wrappers(jenkins_jobs.modules.base.Base):
|
||||
sequence = 80
|
||||
|
||||
def gen_xml(self, parser, xml_parent, data):
|
||||
wrappers = XML.SubElement(xml_parent, 'buildWrappers')
|
||||
|
||||
for wrap in data.get('wrappers', []):
|
||||
self._dispatch('wrapper', 'wrappers',
|
||||
parser, wrappers, wrap)
|
||||
|
85
jenkins_jobs/modules/zuul.py
Normal file
85
jenkins_jobs/modules/zuul.py
Normal file
@ -0,0 +1,85 @@
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for Zuul
|
||||
|
||||
import jenkins_jobs.modules.base
|
||||
|
||||
|
||||
ZUUL_PARAMETERS = [
|
||||
{'string':
|
||||
{'description': 'Zuul provided key to link builds with Gerrit events',
|
||||
'name': 'UUID'}},
|
||||
{'string':
|
||||
{'description': 'Zuul provided project name',
|
||||
'name': 'GERRIT_PROJECT'}},
|
||||
{'string':
|
||||
{'description': 'Zuul provided branch name',
|
||||
'name': 'GERRIT_BRANCH'}},
|
||||
{'string':
|
||||
{'description': 'Zuul provided list of dependent changes to merge',
|
||||
'name': 'GERRIT_CHANGES'}},
|
||||
]
|
||||
|
||||
ZUUL_POST_PARAMETERS = [
|
||||
{'string':
|
||||
{'description': 'Zuul provided key to link builds with Gerrit events',
|
||||
'name': 'UUID'}},
|
||||
{'string':
|
||||
{'description': 'Zuul provided project name',
|
||||
'name': 'GERRIT_PROJECT'}},
|
||||
{'string':
|
||||
{'description': 'Zuul provided ref name',
|
||||
'name': 'GERRIT_REFNAME'}},
|
||||
{'string':
|
||||
{'description': 'Zuul provided old reference for ref-updated',
|
||||
'name': 'GERRIT_OLDREV'}},
|
||||
{'string':
|
||||
{'description': 'Zuul provided new reference for ref-updated',
|
||||
'name': 'GERRIT_NEWREV'}},
|
||||
]
|
||||
|
||||
ZUUL_NOTIFICATIONS = [
|
||||
{'http':
|
||||
{'url': 'http://127.0.0.1:8001/jenkins_endpoint'}}
|
||||
]
|
||||
|
||||
class Zuul(jenkins_jobs.modules.base.Base):
|
||||
sequence = 0
|
||||
|
||||
def handle_data(self, parser):
|
||||
changed = False
|
||||
jobs = (parser.data.get('job', {}).values() +
|
||||
parser.data.get('job-template', {}).values())
|
||||
for job in jobs:
|
||||
triggers = job.get('triggers')
|
||||
if not triggers:
|
||||
continue
|
||||
|
||||
if ('zuul' not in job.get('triggers', []) and
|
||||
'zuul_post' not in job.get('triggers', [])):
|
||||
continue
|
||||
if 'parameters' not in job:
|
||||
job['parameters'] = []
|
||||
if 'notifications' not in job:
|
||||
job['notifications'] = []
|
||||
job['notifications'].extend(ZUUL_NOTIFICATIONS)
|
||||
if 'zuul' in job.get('triggers', []):
|
||||
job['parameters'].extend(ZUUL_PARAMETERS)
|
||||
job['triggers'].remove('zuul')
|
||||
if 'zuul_post' in job.get('triggers', []):
|
||||
job['parameters'].extend(ZUUL_POST_PARAMETERS)
|
||||
job['triggers'].remove('zuul_post')
|
||||
changed = True
|
||||
return changed
|
@ -1,161 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for builders
|
||||
# To use add the folowing into your YAML:
|
||||
# builders:
|
||||
# - 'gerrit_git_prep'
|
||||
# - 'python26'
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
|
||||
|
||||
def register(registry):
|
||||
mod = Builders(registry)
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class Builders(object):
|
||||
sequence = 60
|
||||
|
||||
def __init__(self, registry):
|
||||
self.registry = registry
|
||||
for f in dir(self):
|
||||
if not f.startswith('_builder_'):
|
||||
continue
|
||||
self.registry.registerHandler('builder', f[len('_builder_'):],
|
||||
getattr(self, f))
|
||||
|
||||
def handle_data(self, data):
|
||||
self.data = data
|
||||
|
||||
def gen_xml(self, xml_parent, data):
|
||||
for alias in ['prebuilders', 'builders', 'postbuilders']:
|
||||
if alias in data:
|
||||
builders = XML.SubElement(xml_parent, alias)
|
||||
for builder in data[alias]:
|
||||
if isinstance(builder, dict):
|
||||
for key, value in builder.items():
|
||||
func = self.registry.getHandler('builder', key)
|
||||
func(builders, value)
|
||||
else:
|
||||
func = self.registry.getHandler('builder', builder)
|
||||
func(builders)
|
||||
|
||||
def _add_script(self, xml_parent, script):
|
||||
shell = XML.SubElement(xml_parent, 'hudson.tasks.Shell')
|
||||
XML.SubElement(shell, 'command').text = script
|
||||
|
||||
def _builder_coverage(self, xml_parent):
|
||||
self._add_script(xml_parent, '/usr/local/jenkins/slave_scripts/run-cover.sh')
|
||||
|
||||
def _builder_docs(self, xml_parent):
|
||||
self._add_script(xml_parent, '/usr/local/jenkins/slave_scripts/run-docs.sh')
|
||||
|
||||
def _builder_gerrit_git_prep(self, xml_parent):
|
||||
self._add_script(xml_parent, '/usr/local/jenkins/slave_scripts/gerrit-git-prep.sh {site}'.format(site=self.data['main']['review_site']))
|
||||
|
||||
def _builder_maven_test(self, xml_parent):
|
||||
self._add_script(xml_parent, 'mvn test')
|
||||
|
||||
def _builder_maven_package(self, xml_parent):
|
||||
self._add_script(xml_parent, 'mvn package')
|
||||
|
||||
def _builder_gerrit_package(self, xml_parent):
|
||||
self._add_script(xml_parent,
|
||||
'/usr/local/jenkins/slave_scripts/package-gerrit.sh')
|
||||
|
||||
def _builder_gerrit_preclean(self, xml_parent):
|
||||
self._add_script(xml_parent, "#!/bin/bash -xe\n\
|
||||
rm -fr ~/.m2\n\
|
||||
rm -fr ~/.java\n\
|
||||
./tools/version.sh --release")
|
||||
|
||||
def _builder_gerrit_postrun(self, xml_parent):
|
||||
self._add_script(xml_parent, "./tools/version.sh --reset")
|
||||
|
||||
def _builder_pep8(self, xml_parent):
|
||||
self._add_script(xml_parent, 'set -o pipefail ; tox -v -epep8 | tee pep8.txt ; set +o pipefail')
|
||||
|
||||
def _builder_pyflakes(self, xml_parent):
|
||||
self._add_script(xml_parent, 'tox -v -epyflakes')
|
||||
|
||||
def _builder_puppet_syntax(self, xml_parent):
|
||||
self._add_script(xml_parent, """
|
||||
find . -iname *.pp | xargs puppet parser validate --modulepath=`pwd`/modules
|
||||
for f in `find . -iname *.erb` ; do
|
||||
erb -x -T '-' $f | ruby -c
|
||||
done
|
||||
""")
|
||||
|
||||
def _builder_selenium(self, xml_parent):
|
||||
self._add_script(xml_parent, '/usr/local/jenkins/slave_scripts/run-selenium.sh')
|
||||
|
||||
def _builder_shell(self, xml_parent, data):
|
||||
self._add_script(xml_parent, data)
|
||||
|
||||
def _builder_trigger_builds(self, xml_parent, data):
|
||||
tbuilder = XML.SubElement(xml_parent, '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'):
|
||||
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 = 'ALWAYS'
|
||||
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.text = 'false'
|
||||
|
||||
def _builder_python26(self, xml_parent):
|
||||
self._add_script(xml_parent, '/usr/local/jenkins/slave_scripts/run-tox.sh 26')
|
||||
|
||||
def _builder_python27(self, xml_parent):
|
||||
self._add_script(xml_parent, '/usr/local/jenkins/slave_scripts/run-tox.sh 27')
|
||||
|
||||
def _builder_python26_essex(self, xml_parent):
|
||||
self._add_script(xml_parent, '/usr/local/jenkins/slave_scripts/run-tox.sh 26-essex')
|
||||
|
||||
def _builder_python27_essex(self, xml_parent):
|
||||
self._add_script(xml_parent, '/usr/local/jenkins/slave_scripts/run-tox.sh 27-essex')
|
||||
|
||||
def _builder_tarball(self, xml_parent):
|
||||
self._add_script(xml_parent,
|
||||
'/usr/local/jenkins/slave_scripts/create-tarball.sh %s' % self.data['main']['project'])
|
||||
|
||||
def _builder_ppa(self, xml_parent):
|
||||
self._add_script(xml_parent, 'rm -rf build dist.zip\n\
|
||||
mkdir build')
|
||||
copy = XML.SubElement(xml_parent, 'hudson.plugins.copyartifact.CopyArtifact')
|
||||
XML.SubElement(copy, 'projectName').text = '%s-tarball' % self.data['main']['project']
|
||||
XML.SubElement(copy, 'filter').text = 'dist/*.tar.gz'
|
||||
XML.SubElement(copy, 'target').text = 'build'
|
||||
selector = XML.SubElement(copy, 'selector', {'class':'hudson.plugins.copyartifact.StatusBuildSelector'})
|
||||
XML.SubElement(selector, 'parameterName').text = 'BUILD_SELECTOR'
|
||||
self._add_script(xml_parent, '#!/bin/bash\n\
|
||||
\n\
|
||||
#export DO_UPLOAD="no"\n\
|
||||
export PROJECT="<%= project %>"\n\
|
||||
export GERRIT_REFNAME=$BRANCH\n\
|
||||
/usr/local/jenkins/slave_scripts/create-ppa-package.sh')
|
@ -1,90 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for job properties
|
||||
# No additional YAML needed
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
|
||||
|
||||
def register(registry):
|
||||
mod = Properties()
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class Properties(object):
|
||||
sequence = 20
|
||||
|
||||
def handle_data(self, data):
|
||||
self.data = data
|
||||
|
||||
def gen_xml(self, xml_parent, data):
|
||||
main = self.data['main']
|
||||
properties = XML.SubElement(xml_parent, 'properties')
|
||||
if main.get('project'):
|
||||
github = XML.SubElement(properties, 'com.coravy.hudson.plugins.github.GithubProjectProperty')
|
||||
github_url = XML.SubElement(github, 'projectUrl')
|
||||
github_url.text = "https://github.com/{org}/{project}".format(
|
||||
org=main['github_org'], project=main['project'])
|
||||
throttle = XML.SubElement(properties, 'hudson.plugins.throttleconcurrents.ThrottleJobProperty')
|
||||
XML.SubElement(throttle, 'maxConcurrentPerNode').text = '0'
|
||||
XML.SubElement(throttle, 'maxConcurrentTotal').text = '0'
|
||||
#XML.SubElement(throttle, 'categories')
|
||||
XML.SubElement(throttle, 'throttleEnabled').text = 'false'
|
||||
XML.SubElement(throttle, 'throttleOption').text = 'project'
|
||||
XML.SubElement(throttle, 'configVersion').text = '1'
|
||||
if main.has_key('authenticatedBuild') and main['authenticatedBuild'] == 'true':
|
||||
security = XML.SubElement(properties, 'hudson.security.AuthorizationMatrixProperty')
|
||||
XML.SubElement(security, 'permission').text = 'hudson.model.Item.Build:authenticated'
|
||||
self.do_parameters(properties)
|
||||
self.do_notifications(properties)
|
||||
|
||||
parameter_types = {
|
||||
'string': 'hudson.model.StringParameterDefinition',
|
||||
'bool': 'hudson.model.BooleanParameterDefinition',
|
||||
'file': 'hudson.model.FileParameterDefinition',
|
||||
'text': 'hudson.model.TextParameterDefinition',
|
||||
'label': 'org.jvnet.jenkins.plugins.nodelabelparameter.LabelParameterDefinition',
|
||||
# Others require more work
|
||||
}
|
||||
|
||||
def do_parameters(self, xml_parent):
|
||||
params = self.data.get('parameters', None)
|
||||
if not params:
|
||||
return
|
||||
pdefp = XML.SubElement(xml_parent, 'hudson.model.ParametersDefinitionProperty')
|
||||
pdefs = XML.SubElement(pdefp, 'parameterDefinitions')
|
||||
for param in params:
|
||||
ptype = self.parameter_types.get(param['type'])
|
||||
pdef = XML.SubElement(pdefs, ptype)
|
||||
XML.SubElement(pdef, 'name').text = param['name']
|
||||
XML.SubElement(pdef, 'description').text = param['description']
|
||||
if param['type'] != 'file':
|
||||
default = param.get('default', None)
|
||||
if default:
|
||||
XML.SubElement(pdef, 'defaultValue').text = default
|
||||
else:
|
||||
XML.SubElement(pdef, 'defaultValue')
|
||||
|
||||
def do_notifications(self, xml_parent):
|
||||
endpoints = self.data.get('notification_endpoints', None)
|
||||
if not endpoints:
|
||||
return
|
||||
notify_element = XML.SubElement(xml_parent, 'com.tikal.hudson.plugins.notification.HudsonNotificationProperty')
|
||||
endpoints_element = XML.SubElement(notify_element, 'endpoints')
|
||||
for ep in endpoints:
|
||||
endpoint_element = XML.SubElement(endpoints_element, 'com.tikal.hudson.plugins.notification.Endpoint')
|
||||
XML.SubElement(endpoint_element, 'protocol').text = ep['protocol']
|
||||
XML.SubElement(endpoint_element, 'url').text = ep['URL']
|
@ -1,329 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for coverage publishers
|
||||
# No additional YAML needed
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
|
||||
|
||||
def register(registry):
|
||||
mod = Publishers(registry)
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class Publishers(object):
|
||||
sequence = 70
|
||||
|
||||
def __init__(self, registry):
|
||||
self.registry = registry
|
||||
for f in dir(self):
|
||||
if not f.startswith('_publisher_'):
|
||||
continue
|
||||
self.registry.registerHandler('publisher', f[len('_publisher_'):],
|
||||
getattr(self, f))
|
||||
|
||||
def handle_data(self, data):
|
||||
self.data = data
|
||||
|
||||
def gen_xml(self, xml_parent, data):
|
||||
publishers = XML.SubElement(xml_parent, 'publishers')
|
||||
actions = self.data.get('post_build_actions', [])
|
||||
for action in actions:
|
||||
if isinstance(action, dict):
|
||||
for key, value in action.items():
|
||||
func = self.registry.getHandler('publisher', key)
|
||||
func(publishers, value)
|
||||
else:
|
||||
func = self.registry.getHandler('publisher', action)
|
||||
func(publishers)
|
||||
|
||||
def _publisher_archive(self, xml_parent, data):
|
||||
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 _publisher_trigger_parameterized_builds(self, xml_parent, data):
|
||||
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 project_def.has_key('predefined_parameters'):
|
||||
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 _publisher_coverage(self, xml_parent):
|
||||
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'
|
||||
|
||||
# Jenkins Job module for publishing via ftp
|
||||
# publish:
|
||||
# site: 'docs.openstack.org'
|
||||
# remote_dir: 'dest/dir'
|
||||
# source_files: 'base/source/dir/**'
|
||||
# remove_prefix: 'base/source/dir'
|
||||
# excludes: '**/*.exludedfiletype'
|
||||
#
|
||||
# This will upload everything under $workspace/base/source/dir to
|
||||
# docs.openstack.org $ftpdir/dest/dir exluding the excluded file type.
|
||||
|
||||
def _publisher_ftp(self, 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: '
|
||||
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['remote_dir']
|
||||
XML.SubElement(ftp_transfers, 'sourceFiles').text = data['source_files']
|
||||
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': '../..'})
|
||||
|
||||
# Jenkins Job module for coverage publishers
|
||||
# To use you add the following into your YAML:
|
||||
# publisher:
|
||||
# results: 'nosetests.xml'
|
||||
|
||||
def _publisher_junit(self, xml_parent, data):
|
||||
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')
|
||||
|
||||
# Jenkins Job module for pep8 publishers
|
||||
# No additional YAML needed
|
||||
|
||||
def _pep8_add_entry(self, xml_parent, name):
|
||||
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 = '10'
|
||||
XML.SubElement(tconfig, 'max').text = '999'
|
||||
XML.SubElement(tconfig, 'unstable').text = '999'
|
||||
XML.SubElement(tconfig, 'usePattern').text = 'false'
|
||||
XML.SubElement(tconfig, 'pattern')
|
||||
|
||||
def _publisher_pep8(self, xml_parent):
|
||||
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')
|
||||
|
||||
self._pep8_add_entry(configs, 'checkstyle')
|
||||
self._pep8_add_entry(configs, 'codenarc')
|
||||
self._pep8_add_entry(configs, 'cpd')
|
||||
self._pep8_add_entry(configs, 'cpplint')
|
||||
self._pep8_add_entry(configs, 'csslint')
|
||||
self._pep8_add_entry(configs, 'findbugs')
|
||||
self._pep8_add_entry(configs, 'fxcop')
|
||||
self._pep8_add_entry(configs, 'gendarme')
|
||||
self._pep8_add_entry(configs, 'jcreport')
|
||||
self._pep8_add_entry(configs, 'jslint')
|
||||
|
||||
entry = XML.SubElement(configs, 'entry')
|
||||
XML.SubElement(entry, 'string').text = 'pep8'
|
||||
tconfig = XML.SubElement(entry, 'hudson.plugins.violations.TypeConfig')
|
||||
XML.SubElement(tconfig, 'type').text = 'pep8'
|
||||
XML.SubElement(tconfig, 'min').text = '0'
|
||||
XML.SubElement(tconfig, 'max').text = '1'
|
||||
XML.SubElement(tconfig, 'unstable').text = '1'
|
||||
XML.SubElement(tconfig, 'usePattern').text = 'false'
|
||||
XML.SubElement(tconfig, 'pattern').text = '**/pep8.txt'
|
||||
|
||||
self._pep8_add_entry(configs, 'pmd')
|
||||
self._pep8_add_entry(configs, 'pylint')
|
||||
self._pep8_add_entry(configs, 'simian')
|
||||
self._pep8_add_entry(configs, 'stylecop')
|
||||
|
||||
XML.SubElement(config, 'limit').text = '100'
|
||||
XML.SubElement(config, 'sourcePathPattern')
|
||||
XML.SubElement(config, 'fauxProjectPath')
|
||||
XML.SubElement(config, 'encoding').text = 'default'
|
||||
|
||||
# Jenkins Job module for PPA publishers
|
||||
# No additional YAML needed
|
||||
|
||||
def _publisher_ppa(self, xml_parent):
|
||||
archiver = XML.SubElement(xml_parent, 'hudson.tasks.ArtifactArchiver')
|
||||
XML.SubElement(archiver, 'artifacts').text = 'build/*.dsc,build/*.tar.gz,build/*.changes'
|
||||
XML.SubElement(archiver, 'latestOnly').text = 'false'
|
||||
|
||||
# Jenkins Job module for tarball publishers
|
||||
# To use you add the following into your YAML:
|
||||
# publish:
|
||||
# site: 'glance.openstack.org'
|
||||
# dir: 'glance'
|
||||
|
||||
def _publisher_tarball(self, xml_parent, data):
|
||||
site = data['site']
|
||||
archiver = XML.SubElement(xml_parent, 'hudson.tasks.ArtifactArchiver')
|
||||
XML.SubElement(archiver, 'artifacts').text = 'dist/*.tar.gz'
|
||||
XML.SubElement(archiver, 'latestOnly').text = 'false'
|
||||
scp = XML.SubElement(xml_parent, 'be.certipost.hudson.plugin.SCPRepositoryPublisher')
|
||||
XML.SubElement(scp, 'siteName').text = site
|
||||
entries = XML.SubElement(scp, 'entries')
|
||||
entry = XML.SubElement(entries, 'be.certipost.hudson.plugin.Entry')
|
||||
XML.SubElement(entry, 'filePath').text = 'tarballs/{proj}/'.format(proj=data['project'])
|
||||
XML.SubElement(entry, 'sourceFile').text = 'dist/*.tar.gz'
|
||||
XML.SubElement(entry, 'keepHierarchy').text = 'false'
|
||||
|
||||
# Jenkins Job module for war publishers
|
||||
# To use you add the following into your YAML:
|
||||
# publish:
|
||||
# site: 'nova.openstack.org'
|
||||
# warfile: 'gerrit-war/target/gerrit*.war'
|
||||
# target_path: 'tarballs/ci/'
|
||||
|
||||
def _publisher_war(self, xml_parent, data):
|
||||
site = data['site']
|
||||
archiver = XML.SubElement(xml_parent, 'hudson.tasks.ArtifactArchiver')
|
||||
XML.SubElement(archiver, 'artifacts').text = data['warfile']
|
||||
XML.SubElement(archiver, 'latestOnly').text = 'false'
|
||||
scp = XML.SubElement(xml_parent, 'be.certipost.hudson.plugin.SCPRepositoryPublisher')
|
||||
XML.SubElement(scp, 'siteName').text = site
|
||||
entries = XML.SubElement(scp, 'entries')
|
||||
entry = XML.SubElement(entries, 'be.certipost.hudson.plugin.Entry')
|
||||
XML.SubElement(entry, 'filePath').text = data['target_path']
|
||||
XML.SubElement(entry, 'sourceFile').text = data['warfile']
|
||||
XML.SubElement(entry, 'keepHierarchy').text = 'false'
|
||||
|
||||
# Jenkins Job module for generic scp publishing
|
||||
# To use you add the following into your YAML:
|
||||
# publish:
|
||||
# site: 'openstack-ci.openstack.org'
|
||||
# source: 'doc/build/html/**/*'
|
||||
# target_path: 'ci/zuul'
|
||||
# keep_heirarchy: 'true'
|
||||
|
||||
def _publisher_scp(self, xml_parent, data):
|
||||
site = data['site']
|
||||
scp = XML.SubElement(xml_parent, 'be.certipost.hudson.plugin.SCPRepositoryPublisher')
|
||||
XML.SubElement(scp, 'siteName').text = site
|
||||
entries = XML.SubElement(scp, 'entries')
|
||||
entry = XML.SubElement(entries, 'be.certipost.hudson.plugin.Entry')
|
||||
XML.SubElement(entry, 'filePath').text = data['target_path']
|
||||
XML.SubElement(entry, 'sourceFile').text = data['source']
|
||||
XML.SubElement(entry, 'keepHierarchy').text = data['keep_heirarchy']
|
@ -1,74 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for scm
|
||||
# To use add the folowing into your YAML:
|
||||
# scm:
|
||||
# scm: 'true'
|
||||
# or
|
||||
# scm: 'false'
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
|
||||
|
||||
def register(registry):
|
||||
mod = SCM()
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class SCM(object):
|
||||
sequence = 30
|
||||
|
||||
def handle_data(self, data):
|
||||
self.data = data
|
||||
|
||||
def gen_xml(self, xml_parent, data):
|
||||
main = self.data['main']
|
||||
scm_enabled = self.data['scm']['scm']
|
||||
if scm_enabled == 'true':
|
||||
scm = XML.SubElement(xml_parent, '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')
|
||||
XML.SubElement(huser, 'name').text = 'origin'
|
||||
XML.SubElement(huser, 'refspec').text = '+refs/heads/*:refs/remotes/origin/*'
|
||||
XML.SubElement(huser, 'url').text = 'git://github.com/{org}/{project}.git'.format(org=main['github_org'], project=main['project'])
|
||||
xml_branches = XML.SubElement(scm, 'branches')
|
||||
branches = self.data['scm'].get('branches', ['**'])
|
||||
for branch in branches:
|
||||
bspec = XML.SubElement(xml_branches, 'hudson.plugins.git.BranchSpec')
|
||||
XML.SubElement(bspec, 'name').text = branch
|
||||
XML.SubElement(scm, 'disableSubmodules').text = 'false'
|
||||
XML.SubElement(scm, 'recursiveSubmodules').text = 'false'
|
||||
XML.SubElement(scm, 'doGenerateSubmoduleConfigurations').text = 'false'
|
||||
XML.SubElement(scm, 'authorOrCommitter').text = 'false'
|
||||
XML.SubElement(scm, 'clean').text = 'false'
|
||||
XML.SubElement(scm, 'wipeOutWorkspace').text = 'true'
|
||||
XML.SubElement(scm, 'pruneBranches').text = 'false'
|
||||
XML.SubElement(scm, 'remotePoll').text = 'false'
|
||||
XML.SubElement(scm, 'buildChooser', {'class':'hudson.plugins.git.util.DefaultBuildChooser'})
|
||||
XML.SubElement(scm, 'gitTool').text = 'Default'
|
||||
XML.SubElement(scm, 'submoduleCfg', {'class':'list'})
|
||||
XML.SubElement(scm, 'relativeTargetDir')
|
||||
XML.SubElement(scm, 'reference')
|
||||
XML.SubElement(scm, 'excludedRegions')
|
||||
XML.SubElement(scm, 'excludedUsers')
|
||||
XML.SubElement(scm, 'gitConfigName')
|
||||
XML.SubElement(scm, 'gitConfigEmail')
|
||||
XML.SubElement(scm, 'skipTag').text = 'false'
|
||||
XML.SubElement(scm, 'scmName')
|
||||
else:
|
||||
XML.SubElement(xml_parent, 'scm', {'class':'hudson.scm.NullSCM'})
|
||||
|
@ -1,129 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for gerrit triggers
|
||||
# To use add the following into your YAML:
|
||||
# trigger:
|
||||
# triggerOnPatchsetUploadedEvent: 'false'
|
||||
# triggerOnChangeMergedEvent: 'false'
|
||||
# triggerOnCommentAddedEvent: 'true'
|
||||
# triggerOnRefUpdatedEvent: 'false'
|
||||
# triggerApprovalCategory: 'APRV'
|
||||
# triggerApprovalValue: 1
|
||||
# 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.'
|
||||
# projects:
|
||||
# - projectCompareType: 'PLAIN'
|
||||
# projectPattern: 'openstack/nova'
|
||||
# branchCompareType: 'ANT'
|
||||
# branchPattern: '**'
|
||||
# - projectCompareType: 'PLAIN'
|
||||
# projectPattern: 'openstack/glance'
|
||||
# branchCompareType: 'ANT'
|
||||
# branchPattern: '**'
|
||||
# ...
|
||||
#
|
||||
# triggerApprovalCategory and triggerApprovalValue only required if triggerOnCommentAddedEvent: 'true'
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
|
||||
|
||||
def register(registry):
|
||||
mod = Triggers(registry)
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class Triggers(object):
|
||||
sequence = 50
|
||||
|
||||
def __init__(self, registry):
|
||||
self.registry = registry
|
||||
for f in dir(self):
|
||||
if not f.startswith('_trigger_'):
|
||||
continue
|
||||
self.registry.registerHandler('trigger', f[len('_trigger_'):],
|
||||
getattr(self, f))
|
||||
|
||||
def handle_data(self, data):
|
||||
self.data = data
|
||||
|
||||
def gen_xml(self, xml_parent, data):
|
||||
actions = self.data.get('triggers', [])
|
||||
if not actions:
|
||||
return
|
||||
triggers = XML.SubElement(xml_parent, 'triggers', {'class':'vector'})
|
||||
for action in actions:
|
||||
if isinstance(action, dict):
|
||||
for key, value in action.items():
|
||||
func = self.registry.getHandler('trigger', key)
|
||||
func(triggers, value)
|
||||
else:
|
||||
func = self.registry.getHandler('trigger', action)
|
||||
func(triggers)
|
||||
|
||||
def _trigger_gerrit(self, xml_parent, data):
|
||||
projects = data['projects']
|
||||
gtrig = XML.SubElement(xml_parent, 'com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritTrigger')
|
||||
XML.SubElement(gtrig, 'spec')
|
||||
gprojects = XML.SubElement(gtrig, 'gerritProjects')
|
||||
for project in projects:
|
||||
gproj = XML.SubElement(gprojects, 'com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.GerritProject')
|
||||
XML.SubElement(gproj, 'compareType').text = project['projectCompareType']
|
||||
XML.SubElement(gproj, 'pattern').text = project['projectPattern']
|
||||
branches = XML.SubElement(gproj, 'branches')
|
||||
gbranch = XML.SubElement(branches, 'com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.Branch')
|
||||
XML.SubElement(gbranch, 'compareType').text = project['branchCompareType']
|
||||
XML.SubElement(gbranch, 'pattern').text = project['branchPattern']
|
||||
XML.SubElement(gtrig, 'silentMode').text = 'false'
|
||||
XML.SubElement(gtrig, 'escapeQuotes').text = 'true'
|
||||
XML.SubElement(gtrig, 'triggerOnPatchsetUploadedEvent').text = data['triggerOnPatchsetUploadedEvent']
|
||||
XML.SubElement(gtrig, 'triggerOnChangeMergedEvent').text = data['triggerOnChangeMergedEvent']
|
||||
XML.SubElement(gtrig, 'triggerOnCommentAddedEvent').text = data['triggerOnCommentAddedEvent']
|
||||
XML.SubElement(gtrig, 'triggerOnRefUpdatedEvent').text = data['triggerOnRefUpdatedEvent']
|
||||
if data.has_key('overrideVotes') and data['overrideVotes'] == 'true':
|
||||
XML.SubElement(gtrig, 'gerritBuildSuccessfulVerifiedValue').text = str(data['gerritBuildSuccessfulVerifiedValue'])
|
||||
XML.SubElement(gtrig, 'gerritBuildFailedVerifiedValue').text = str(data['gerritBuildFailedVerifiedValue'])
|
||||
if data['triggerOnCommentAddedEvent'] == 'true':
|
||||
XML.SubElement(gtrig, 'commentAddedTriggerApprovalCategory').text = data['triggerApprovalCategory']
|
||||
XML.SubElement(gtrig, 'commentAddedTriggerApprovalValue').text = str(data['triggerApprovalValue'])
|
||||
XML.SubElement(gtrig, 'buildStartMessage')
|
||||
XML.SubElement(gtrig, 'buildFailureMessage').text = data['failureMessage']
|
||||
XML.SubElement(gtrig, 'buildSuccessfulMessage')
|
||||
XML.SubElement(gtrig, 'buildUnstableMessage')
|
||||
XML.SubElement(gtrig, 'customUrl')
|
||||
|
||||
# Jenkins Job module for scm polling triggers
|
||||
# To use add the following into your YAML:
|
||||
# trigger:
|
||||
# pollscm: '@midnight'
|
||||
# or
|
||||
# pollscm: '*/15 * * * *'
|
||||
|
||||
def _trigger_pollscm(self, 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:
|
||||
# timed: '@midnight'
|
||||
# or
|
||||
# timed: '*/15 * * * *'
|
||||
|
||||
def _trigger_timed(self, xml_parent, data):
|
||||
scmtrig = XML.SubElement(xml_parent, 'hudson.triggers.TimerTrigger')
|
||||
XML.SubElement(scmtrig, 'spec').text = data
|
@ -1,53 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for wrappers
|
||||
|
||||
import xml.etree.ElementTree as XML
|
||||
|
||||
def register(registry):
|
||||
mod = Wrappers()
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class Wrappers(object):
|
||||
sequence = 80
|
||||
|
||||
def gen_xml(self, xml_parent, data):
|
||||
wrappers = XML.SubElement(xml_parent, 'buildWrappers')
|
||||
|
||||
if 'timeout' in data['main']:
|
||||
self._timeout(wrappers, data)
|
||||
if 'ansicolor' in data['main']:
|
||||
self._ansicolor(wrappers, data)
|
||||
if 'timestamps' in data['main']:
|
||||
self._timestamps(wrappers, data)
|
||||
|
||||
def _timeout(self, xml_parent, data):
|
||||
twrapper = XML.SubElement(xml_parent, 'hudson.plugins.build__timeout.BuildTimeoutWrapper')
|
||||
tminutes = XML.SubElement(twrapper, 'timeoutMinutes')
|
||||
tminutes.text = str(data['main']['timeout'])
|
||||
failbuild = XML.SubElement(twrapper, 'failBuild')
|
||||
fail = data['main'].get('timeout_fail', False)
|
||||
if fail:
|
||||
failbuild.text = 'true'
|
||||
else:
|
||||
failbuild.text = 'false'
|
||||
|
||||
def _timestamps(self, xml_parent, data):
|
||||
XML.SubElement(xml_parent, 'hudson.plugins.timestamper.TimestamperBuildWrapper')
|
||||
|
||||
def _ansicolor(self, xml_parent, data):
|
||||
XML.SubElement(xml_parent, 'hudson.plugins.ansicolor.AnsiColorBuildWrapper')
|
@ -1,79 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# Copyright (C) 2012 OpenStack, LLC.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Jenkins Job module for Zuul
|
||||
|
||||
ZUUL_PARAMETERS = [
|
||||
{'description': 'Zuul provided key to link builds with Gerrit events',
|
||||
'name': 'UUID',
|
||||
'type': 'string'},
|
||||
{'description': 'Zuul provided project name',
|
||||
'name': 'GERRIT_PROJECT',
|
||||
'type': 'string'},
|
||||
{'description': 'Zuul provided branch name',
|
||||
'name': 'GERRIT_BRANCH',
|
||||
'type': 'string'},
|
||||
{'description': 'Zuul provided list of dependent changes to merge',
|
||||
'name': 'GERRIT_CHANGES',
|
||||
'type': 'string'}
|
||||
]
|
||||
|
||||
ZUUL_POST_PARAMETERS = [
|
||||
{'description': 'Zuul provided key to link builds with Gerrit events',
|
||||
'name': 'UUID',
|
||||
'type': 'string'},
|
||||
{'description': 'Zuul provided project name',
|
||||
'name': 'GERRIT_PROJECT',
|
||||
'type': 'string'},
|
||||
{'description': 'Zuul provided ref name',
|
||||
'name': 'GERRIT_REFNAME',
|
||||
'type': 'string'},
|
||||
{'description': 'Zuul provided old reference for ref-updated',
|
||||
'name': 'GERRIT_OLDREV',
|
||||
'type': 'string'},
|
||||
{'description': 'Zuul provided new reference for ref-updated',
|
||||
'name': 'GERRIT_NEWREV',
|
||||
'type': 'string'}
|
||||
]
|
||||
|
||||
ZUUL_NOTIFICATIONS = [
|
||||
{'URL': 'http://127.0.0.1:8001/jenkins_endpoint',
|
||||
'protocol': 'HTTP'}
|
||||
]
|
||||
|
||||
|
||||
def register(registry):
|
||||
mod = Zuul()
|
||||
registry.registerModule(mod)
|
||||
|
||||
|
||||
class Zuul(object):
|
||||
sequence = 0
|
||||
|
||||
def handle_data(self, data):
|
||||
if ('zuul' not in data.get('triggers', []) and
|
||||
'zuul_post' not in data.get('triggers', [])):
|
||||
return
|
||||
if 'parameters' not in data:
|
||||
data['parameters'] = []
|
||||
if 'notification_endpoints' not in data:
|
||||
data['notification_endpoints'] = []
|
||||
data['notification_endpoints'].extend(ZUUL_NOTIFICATIONS)
|
||||
if 'zuul' in data.get('triggers', []):
|
||||
data['parameters'].extend(ZUUL_PARAMETERS)
|
||||
data['triggers'].remove('zuul')
|
||||
if 'zuul_post' in data.get('triggers', []):
|
||||
data['parameters'].extend(ZUUL_POST_PARAMETERS)
|
||||
data['triggers'].remove('zuul_post')
|
@ -1,71 +1,62 @@
|
||||
project:
|
||||
template: 'python_jobs'
|
||||
#project:
|
||||
# template: 'python_jobs'
|
||||
#
|
||||
#values:
|
||||
# name: 'zuul'
|
||||
# disabled: 'false'
|
||||
# github_org: 'openstack-ci'
|
||||
# review_site: 'review.openstack.org'
|
||||
# node: 'precise'
|
||||
#
|
||||
#---
|
||||
|
||||
values:
|
||||
name: 'zuul'
|
||||
disabled: 'false'
|
||||
github_org: 'openstack-ci'
|
||||
review_site: 'review.openstack.org'
|
||||
node: 'precise'
|
||||
- job:
|
||||
name: gate-zuul-pyflakes
|
||||
project-type: freestyle
|
||||
concurrent: true
|
||||
timeout: 20
|
||||
timeout_fail: true
|
||||
|
||||
---
|
||||
# pyflakes-gate
|
||||
main:
|
||||
name: 'gate-zuul-pyflakes'
|
||||
review_site: 'review.openstack.org'
|
||||
github_org: 'openstack-ci'
|
||||
project: 'zuul'
|
||||
concurrent: 'true'
|
||||
timeout: 20
|
||||
timeout_fail: true
|
||||
triggers:
|
||||
- zuul
|
||||
|
||||
triggers:
|
||||
- zuul
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- pyflakes
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- pyflakes
|
||||
assignednode:
|
||||
node: 'precise'
|
||||
|
||||
scm:
|
||||
scm: 'false'
|
||||
- job:
|
||||
name: zuul-docs
|
||||
project-type: freestyle
|
||||
#review_site: 'review.openstack.org'
|
||||
#github_org: 'openstack-ci'
|
||||
#project: 'zuul'
|
||||
#authenticatedBuild: 'false'
|
||||
concurrent: true
|
||||
timeout: 20
|
||||
timeout_fail: true
|
||||
|
||||
assignednode:
|
||||
node: 'precise'
|
||||
triggers:
|
||||
- zuul_post
|
||||
|
||||
---
|
||||
# zuul-docs
|
||||
main:
|
||||
name: 'zuul-docs'
|
||||
review_site: 'review.openstack.org'
|
||||
github_org: 'openstack-ci'
|
||||
project: 'zuul'
|
||||
authenticatedBuild: 'false'
|
||||
concurrent: 'true'
|
||||
timeout: 20
|
||||
timeout_fail: true
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
|
||||
triggers:
|
||||
- zuul_post
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- docs
|
||||
|
||||
logrotate:
|
||||
daysToKeep: 28
|
||||
numToKeep: -1
|
||||
artifactDaysToKeep: -1
|
||||
artifactNumToKeep: -1
|
||||
post_build_actions:
|
||||
- scp:
|
||||
site: '173.203.107.207'
|
||||
source: 'doc/build/html/**/*'
|
||||
target_path: 'ci/zuul'
|
||||
keep_heirarchy: 'true'
|
||||
|
||||
builders:
|
||||
- gerrit_git_prep
|
||||
- docs
|
||||
|
||||
post_build_actions:
|
||||
- scp:
|
||||
site: '173.203.107.207'
|
||||
source: 'doc/build/html/**/*'
|
||||
target_path: 'ci/zuul'
|
||||
keep_heirarchy: 'true'
|
||||
|
||||
scm:
|
||||
scm: 'false'
|
||||
|
||||
assignednode:
|
||||
node: 'precise'
|
||||
assignednode:
|
||||
node: 'precise'
|
||||
|
90
setup.py
Normal file
90
setup.py
Normal file
@ -0,0 +1,90 @@
|
||||
# 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.
|
||||
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
setup(name='jenkins_job_builder',
|
||||
version='0.1',
|
||||
description="Manage Jenkins jobs with YAML",
|
||||
license='Apache License (2.0)',
|
||||
author='Hewlett-Packard Development Company, L.P.',
|
||||
author_email='openstack@lists.launchpad.net',
|
||||
scripts=['jenkins-jobs'],
|
||||
include_package_data=True,
|
||||
zip_safe=False,
|
||||
packages=find_packages(),
|
||||
|
||||
entry_points = {
|
||||
'jenkins_jobs.projects': [
|
||||
'freestyle=jenkins_jobs.modules.project_freestyle:Freestyle',
|
||||
'maven=jenkins_jobs.modules.project_maven:Maven',
|
||||
],
|
||||
'jenkins_jobs.builders': [
|
||||
'shell=jenkins_jobs.modules.builders:shell',
|
||||
'trigger-builds=jenkins_jobs.modules.builders:trigger_builds',
|
||||
],
|
||||
'jenkins_jobs.properties': [
|
||||
'github=jenkins_jobs.modules.properties:github',
|
||||
'throttle=jenkins_jobs.modules.properties:throttle',
|
||||
'authenticated-build=jenkins_jobs.modules.properties:'
|
||||
'authenticated_build',
|
||||
],
|
||||
'jenkins_jobs.parameters': [
|
||||
'string=jenkins_jobs.modules.properties:string_param',
|
||||
'bool=jenkins_jobs.modules.properties:bool_param',
|
||||
'file=jenkins_jobs.modules.properties:file_param',
|
||||
'text=jenkins_jobs.modules.properties:text_param',
|
||||
'label=jenkins_jobs.modules.properties:label_param',
|
||||
],
|
||||
'jenkins_jobs.notifications': [
|
||||
'http=jenkins_jobs.modules.properties:http_endpoint',
|
||||
],
|
||||
'jenkins_jobs.publishers': [
|
||||
'archive=jenkins_jobs.modules.publishers:archive',
|
||||
'trigger-parameterized-builds='
|
||||
'jenkins_jobs.modules.publishers:trigger_parameterized_builds',
|
||||
'coverage=jenkins_jobs.modules.publishers:coverage',
|
||||
'ftp=jenkins_jobs.modules.publishers:ftp',
|
||||
'junit=jenkins_jobs.modules.publishers:junit',
|
||||
'pep8=jenkins_jobs.modules.publishers:pep8',
|
||||
'scp=jenkins_jobs.modules.publishers:scp',
|
||||
],
|
||||
'jenkins_jobs.scm': [
|
||||
'git=jenkins_jobs.modules.scm:git',
|
||||
],
|
||||
'jenkins_jobs.triggers': [
|
||||
'gerrit=jenkins_jobs.modules.triggers:gerrit',
|
||||
'pollscm=jenkins_jobs.modules.triggers:pollscm',
|
||||
'timed=jenkins_jobs.modules.triggers:timed',
|
||||
],
|
||||
'jenkins_jobs.wrappers': [
|
||||
'timeout=jenkins_jobs.modules.wrappers:timeout',
|
||||
'timestamps=jenkins_jobs.modules.wrappers:timestamps',
|
||||
'ansicolor=jenkins_jobs.modules.wrappers:ansicolor',
|
||||
],
|
||||
'jenkins_jobs.modules': [
|
||||
'assignednode=jenkins_jobs.modules.assignednode:AssignedNode',
|
||||
'builders=jenkins_jobs.modules.builders:Builders',
|
||||
'logrotate=jenkins_jobs.modules.logrotate:LogRotate',
|
||||
'properties=jenkins_jobs.modules.properties:Properties',
|
||||
'publishers=jenkins_jobs.modules.publishers:Publishers',
|
||||
'scm=jenkins_jobs.modules.scm:SCM',
|
||||
'triggers=jenkins_jobs.modules.triggers:Triggers',
|
||||
'wrappers=jenkins_jobs.modules.wrappers:Wrappers',
|
||||
'zuul=jenkins_jobs.modules.zuul:Zuul',
|
||||
]
|
||||
}
|
||||
|
||||
)
|
23
test.sh
23
test.sh
@ -9,18 +9,19 @@ mkdir -p /tmp/jenkins_jobs_test/test
|
||||
|
||||
if [ "$1" == "save" ]
|
||||
then
|
||||
for x in `find projects/ -name *.yml`
|
||||
do
|
||||
echo $x
|
||||
BASENAME=`basename $x`
|
||||
python jenkins_jobs.py test $x > /tmp/jenkins_jobs_test/saved/$BASENAME.xml
|
||||
done
|
||||
rm -f /tmp/jenkins_jobs_test/saved/*
|
||||
jenkins-jobs test -o /tmp/jenkins_jobs_test/saved/ example
|
||||
else
|
||||
for x in `find projects/ -name *.yml`
|
||||
rm -f /tmp/jenkins_jobs_test/test/*
|
||||
jenkins-jobs test -o /tmp/jenkins_jobs_test/test/ example
|
||||
for x in `(cd /tmp/jenkins_jobs_test/saved && find -type f)`
|
||||
do
|
||||
echo $x
|
||||
BASENAME=`basename $x`
|
||||
python jenkins_jobs.py test $x > /tmp/jenkins_jobs_test/test/$BASENAME.xml
|
||||
if ! diff -u /tmp/jenkins_jobs_test/saved/$x /tmp/jenkins_jobs_test/test/$x >/dev/null 2>&1
|
||||
then
|
||||
echo "============================================================"
|
||||
echo $x
|
||||
echo "------------------------------------------------------------"
|
||||
fi
|
||||
diff -u /tmp/jenkins_jobs_test/saved/$x /tmp/jenkins_jobs_test/test/$x
|
||||
done
|
||||
diff -r /tmp/jenkins_jobs_test/saved /tmp/jenkins_jobs_test/test
|
||||
fi
|
||||
|
Loading…
Reference in New Issue
Block a user