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 2012 Hewlett-Packard Development Company, L.P.
|
||||||
# Copyright (C) 2012 OpenStack, LLC.
|
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -19,18 +18,14 @@
|
|||||||
# - node: 'oneiric'
|
# - node: 'oneiric'
|
||||||
|
|
||||||
import xml.etree.ElementTree as XML
|
import xml.etree.ElementTree as XML
|
||||||
|
import jenkins_jobs.modules.base
|
||||||
|
|
||||||
|
|
||||||
def register(registry):
|
class AssignedNode(jenkins_jobs.modules.base.Base):
|
||||||
mod = AssignedNode()
|
|
||||||
registry.registerModule(mod)
|
|
||||||
|
|
||||||
|
|
||||||
class AssignedNode(object):
|
|
||||||
sequence = 40
|
sequence = 40
|
||||||
|
|
||||||
def gen_xml(self, xml_parent, data):
|
def gen_xml(self, parser, xml_parent, data):
|
||||||
node = data['assignednode']['node']
|
node = data.get('node', None)
|
||||||
XML.SubElement(xml_parent, 'assignedNode').text = node
|
if node:
|
||||||
XML.SubElement(xml_parent, 'canRoam').text = 'false'
|
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 2012 Hewlett-Packard Development Company, L.P.
|
||||||
# Copyright (C) 2012 OpenStack, LLC.
|
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -22,23 +21,16 @@
|
|||||||
# artifactNumToKeep: -1
|
# artifactNumToKeep: -1
|
||||||
|
|
||||||
import xml.etree.ElementTree as XML
|
import xml.etree.ElementTree as XML
|
||||||
|
import jenkins_jobs.modules.base
|
||||||
|
|
||||||
|
|
||||||
def register(registry):
|
class LogRotate(jenkins_jobs.modules.base.Base):
|
||||||
mod = LogRotate()
|
|
||||||
registry.registerModule(mod)
|
|
||||||
|
|
||||||
|
|
||||||
class LogRotate(object):
|
|
||||||
sequence = 10
|
sequence = 10
|
||||||
|
|
||||||
def handle_data(self, data):
|
def gen_xml(self, parser, xml_parent, data):
|
||||||
self.data = data
|
if data.has_key('logrotate'):
|
||||||
|
|
||||||
def gen_xml(self, xml_parent, data):
|
|
||||||
if self.data.has_key('logrotate'):
|
|
||||||
lr_xml = XML.SubElement(xml_parent, 'logRotator')
|
lr_xml = XML.SubElement(xml_parent, 'logRotator')
|
||||||
logrotate = self.data['logrotate']
|
logrotate = data['logrotate']
|
||||||
lr_days = XML.SubElement(lr_xml, 'daysToKeep')
|
lr_days = XML.SubElement(lr_xml, 'daysToKeep')
|
||||||
lr_days.text = str(logrotate['daysToKeep'])
|
lr_days.text = str(logrotate['daysToKeep'])
|
||||||
lr_num = XML.SubElement(lr_xml, 'numToKeep')
|
lr_num = XML.SubElement(lr_xml, 'numToKeep')
|
@ -1,5 +1,4 @@
|
|||||||
#! /usr/bin/env python
|
# Copyright 2012 Hewlett-Packard Development Company, L.P.
|
||||||
# Copyright (C) 2012 OpenStack, LLC.
|
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -22,18 +21,12 @@
|
|||||||
# goals: 'test'
|
# goals: 'test'
|
||||||
|
|
||||||
import xml.etree.ElementTree as XML
|
import xml.etree.ElementTree as XML
|
||||||
|
import jenkins_jobs.modules.base
|
||||||
|
|
||||||
|
|
||||||
def register(registry):
|
class Freestyle(jenkins_jobs.modules.base.Base):
|
||||||
mod = Freestyle()
|
|
||||||
registry.registerModule(mod)
|
|
||||||
|
|
||||||
|
|
||||||
class Freestyle(object):
|
|
||||||
sequence = 0
|
sequence = 0
|
||||||
|
|
||||||
def root_xml(self, data):
|
def root_xml(self, data):
|
||||||
if 'maven' in data:
|
|
||||||
return None
|
|
||||||
xml_parent = XML.Element('project')
|
xml_parent = XML.Element('project')
|
||||||
return xml_parent
|
return xml_parent
|
@ -1,5 +1,4 @@
|
|||||||
#! /usr/bin/env python
|
# Copyright 2012 Hewlett-Packard Development Company, L.P.
|
||||||
# Copyright (C) 2012 OpenStack, LLC.
|
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -22,14 +21,9 @@
|
|||||||
# goals: 'test'
|
# goals: 'test'
|
||||||
|
|
||||||
import xml.etree.ElementTree as XML
|
import xml.etree.ElementTree as XML
|
||||||
|
import jenkins_jobs.modules.base
|
||||||
|
|
||||||
|
class Maven(jenkins_jobs.modules.base.Base):
|
||||||
def register(registry):
|
|
||||||
mod = Maven()
|
|
||||||
registry.registerModule(mod)
|
|
||||||
|
|
||||||
|
|
||||||
class Maven(object):
|
|
||||||
sequence = 0
|
sequence = 0
|
||||||
|
|
||||||
def root_xml(self, data):
|
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:
|
#project:
|
||||||
template: 'python_jobs'
|
# template: 'python_jobs'
|
||||||
|
#
|
||||||
|
#values:
|
||||||
|
# name: 'zuul'
|
||||||
|
# disabled: 'false'
|
||||||
|
# github_org: 'openstack-ci'
|
||||||
|
# review_site: 'review.openstack.org'
|
||||||
|
# node: 'precise'
|
||||||
|
#
|
||||||
|
#---
|
||||||
|
|
||||||
values:
|
- job:
|
||||||
name: 'zuul'
|
name: gate-zuul-pyflakes
|
||||||
disabled: 'false'
|
project-type: freestyle
|
||||||
github_org: 'openstack-ci'
|
concurrent: true
|
||||||
review_site: 'review.openstack.org'
|
timeout: 20
|
||||||
node: 'precise'
|
timeout_fail: true
|
||||||
|
|
||||||
---
|
triggers:
|
||||||
# pyflakes-gate
|
- zuul
|
||||||
main:
|
|
||||||
name: 'gate-zuul-pyflakes'
|
|
||||||
review_site: 'review.openstack.org'
|
|
||||||
github_org: 'openstack-ci'
|
|
||||||
project: 'zuul'
|
|
||||||
concurrent: 'true'
|
|
||||||
timeout: 20
|
|
||||||
timeout_fail: true
|
|
||||||
|
|
||||||
triggers:
|
builders:
|
||||||
- zuul
|
- gerrit_git_prep
|
||||||
|
- pyflakes
|
||||||
|
|
||||||
builders:
|
assignednode:
|
||||||
- gerrit_git_prep
|
node: 'precise'
|
||||||
- pyflakes
|
|
||||||
|
|
||||||
scm:
|
- job:
|
||||||
scm: 'false'
|
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:
|
triggers:
|
||||||
node: 'precise'
|
- zuul_post
|
||||||
|
|
||||||
---
|
logrotate:
|
||||||
# zuul-docs
|
daysToKeep: 28
|
||||||
main:
|
numToKeep: -1
|
||||||
name: 'zuul-docs'
|
artifactDaysToKeep: -1
|
||||||
review_site: 'review.openstack.org'
|
artifactNumToKeep: -1
|
||||||
github_org: 'openstack-ci'
|
|
||||||
project: 'zuul'
|
|
||||||
authenticatedBuild: 'false'
|
|
||||||
concurrent: 'true'
|
|
||||||
timeout: 20
|
|
||||||
timeout_fail: true
|
|
||||||
|
|
||||||
triggers:
|
builders:
|
||||||
- zuul_post
|
- gerrit_git_prep
|
||||||
|
- docs
|
||||||
|
|
||||||
logrotate:
|
post_build_actions:
|
||||||
daysToKeep: 28
|
- scp:
|
||||||
numToKeep: -1
|
site: '173.203.107.207'
|
||||||
artifactDaysToKeep: -1
|
source: 'doc/build/html/**/*'
|
||||||
artifactNumToKeep: -1
|
target_path: 'ci/zuul'
|
||||||
|
keep_heirarchy: 'true'
|
||||||
|
|
||||||
builders:
|
assignednode:
|
||||||
- gerrit_git_prep
|
node: 'precise'
|
||||||
- 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'
|
|
||||||
|
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" ]
|
if [ "$1" == "save" ]
|
||||||
then
|
then
|
||||||
for x in `find projects/ -name *.yml`
|
rm -f /tmp/jenkins_jobs_test/saved/*
|
||||||
do
|
jenkins-jobs test -o /tmp/jenkins_jobs_test/saved/ example
|
||||||
echo $x
|
|
||||||
BASENAME=`basename $x`
|
|
||||||
python jenkins_jobs.py test $x > /tmp/jenkins_jobs_test/saved/$BASENAME.xml
|
|
||||||
done
|
|
||||||
else
|
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
|
do
|
||||||
echo $x
|
if ! diff -u /tmp/jenkins_jobs_test/saved/$x /tmp/jenkins_jobs_test/test/$x >/dev/null 2>&1
|
||||||
BASENAME=`basename $x`
|
then
|
||||||
python jenkins_jobs.py test $x > /tmp/jenkins_jobs_test/test/$BASENAME.xml
|
echo "============================================================"
|
||||||
|
echo $x
|
||||||
|
echo "------------------------------------------------------------"
|
||||||
|
fi
|
||||||
|
diff -u /tmp/jenkins_jobs_test/saved/$x /tmp/jenkins_jobs_test/test/$x
|
||||||
done
|
done
|
||||||
diff -r /tmp/jenkins_jobs_test/saved /tmp/jenkins_jobs_test/test
|
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user