From 8f0984169379a1845686d4debfbb7dfbce470978 Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Tue, 7 Aug 2012 14:11:29 -0700 Subject: [PATCH] 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 Reviewed-by: James E. Blair Tested-by: Jenkins --- .gitignore | 2 + example/ceilometer.yml | 80 +++++ example/cinder.yml | 10 + example/devstack-gate.yml | 273 +++++++++++++++ example/devstack.yml | 33 ++ example/gerrit-verification-status-plugin.yml | 35 ++ example/gerrit.yml | 159 +++++++++ example/gerritbot.yml | 90 +++++ example/gerritlib.yml | 45 +++ example/glance.yml | 10 + example/heat.yml | 7 + example/horizon.yml | 43 +++ example/jenkins-job-builder.yml | 34 ++ example/keystone.yml | 10 + example/macros.yml | 115 ++++++ example/mraas.yml | 82 +++++ example/nova.yml | 12 + example/openstack-ci-puppet.yml | 63 ++++ example/openstack-common.yml | 10 + example/openstack-publish-jobs.yml | 87 +++++ example/pbr.yml | 10 + example/pypi-jobs.yml | 85 +++++ example/pypi-mirror.yml | 64 ++++ example/python-bitrot-jobs.yml | 140 ++++++++ example/python-cinderclient.yml | 10 + example/python-glanceclient.yml | 10 + example/python-jobs.yml | 267 ++++++++++++++ example/python-keystoneclient.yml | 10 + example/python-novaclient.yml | 10 + example/python-openstackclient.yml | 10 + example/python-quantumclient.yml | 10 + example/python-swiftclient.yml | 10 + example/quantum.yml | 10 + example/reddwarf.yml | 7 + example/requirements.yml | 34 ++ example/swift.yml | 10 + example/tempest.yml | 67 ++++ example/zuul.yml | 79 +++++ jenkins-jobs | 47 +++ jenkins_jobs.py | 279 --------------- {modules => jenkins_jobs}/__init__.py | 0 jenkins_jobs/builder.py | 274 +++++++++++++++ jenkins_jobs/modules/__init__.py | 0 .../modules}/assignednode.py | 21 +- jenkins_jobs/modules/base.py | 58 +++ jenkins_jobs/modules/builders.py | 63 ++++ .../modules}/logrotate.py | 20 +- .../modules}/project_freestyle.py | 13 +- .../modules}/project_maven.py | 12 +- jenkins_jobs/modules/properties.py | 117 +++++++ jenkins_jobs/modules/publishers.py | 290 +++++++++++++++ jenkins_jobs/modules/scm.py | 72 ++++ jenkins_jobs/modules/triggers.py | 124 +++++++ jenkins_jobs/modules/wrappers.py | 51 +++ jenkins_jobs/modules/zuul.py | 85 +++++ modules/builders.py | 161 --------- modules/properties.py | 90 ----- modules/publishers.py | 329 ------------------ modules/scm.py | 74 ---- modules/triggers.py | 129 ------- modules/wrappers.py | 53 --- modules/zuul.py | 79 ----- projects/openstack/zuul.yml | 113 +++--- setup.py | 90 +++++ test.sh | 23 +- 65 files changed, 3398 insertions(+), 1312 deletions(-) create mode 100644 .gitignore create mode 100644 example/ceilometer.yml create mode 100644 example/cinder.yml create mode 100644 example/devstack-gate.yml create mode 100644 example/devstack.yml create mode 100644 example/gerrit-verification-status-plugin.yml create mode 100644 example/gerrit.yml create mode 100644 example/gerritbot.yml create mode 100644 example/gerritlib.yml create mode 100644 example/glance.yml create mode 100644 example/heat.yml create mode 100644 example/horizon.yml create mode 100644 example/jenkins-job-builder.yml create mode 100644 example/keystone.yml create mode 100644 example/macros.yml create mode 100644 example/mraas.yml create mode 100644 example/nova.yml create mode 100644 example/openstack-ci-puppet.yml create mode 100644 example/openstack-common.yml create mode 100644 example/openstack-publish-jobs.yml create mode 100644 example/pbr.yml create mode 100644 example/pypi-jobs.yml create mode 100644 example/pypi-mirror.yml create mode 100644 example/python-bitrot-jobs.yml create mode 100644 example/python-cinderclient.yml create mode 100644 example/python-glanceclient.yml create mode 100644 example/python-jobs.yml create mode 100644 example/python-keystoneclient.yml create mode 100644 example/python-novaclient.yml create mode 100644 example/python-openstackclient.yml create mode 100644 example/python-quantumclient.yml create mode 100644 example/python-swiftclient.yml create mode 100644 example/quantum.yml create mode 100644 example/reddwarf.yml create mode 100644 example/requirements.yml create mode 100644 example/swift.yml create mode 100644 example/tempest.yml create mode 100644 example/zuul.yml create mode 100755 jenkins-jobs delete mode 100644 jenkins_jobs.py rename {modules => jenkins_jobs}/__init__.py (100%) create mode 100644 jenkins_jobs/builder.py create mode 100644 jenkins_jobs/modules/__init__.py rename {modules => jenkins_jobs/modules}/assignednode.py (65%) create mode 100644 jenkins_jobs/modules/base.py create mode 100644 jenkins_jobs/modules/builders.py rename {modules => jenkins_jobs/modules}/logrotate.py (78%) rename {modules => jenkins_jobs/modules}/project_freestyle.py (80%) rename {modules => jenkins_jobs/modules}/project_maven.py (93%) create mode 100644 jenkins_jobs/modules/properties.py create mode 100644 jenkins_jobs/modules/publishers.py create mode 100644 jenkins_jobs/modules/scm.py create mode 100644 jenkins_jobs/modules/triggers.py create mode 100644 jenkins_jobs/modules/wrappers.py create mode 100644 jenkins_jobs/modules/zuul.py delete mode 100644 modules/builders.py delete mode 100644 modules/properties.py delete mode 100644 modules/publishers.py delete mode 100644 modules/scm.py delete mode 100644 modules/triggers.py delete mode 100644 modules/wrappers.py delete mode 100644 modules/zuul.py create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..7fdea582c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +*.egg-info diff --git a/example/ceilometer.yml b/example/ceilometer.yml new file mode 100644 index 000000000..a17dbc532 --- /dev/null +++ b/example/ceilometer.yml @@ -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 diff --git a/example/cinder.yml b/example/cinder.yml new file mode 100644 index 000000000..5a0499eed --- /dev/null +++ b/example/cinder.yml @@ -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 diff --git a/example/devstack-gate.yml b/example/devstack-gate.yml new file mode 100644 index 000000000..c26a1fe59 --- /dev/null +++ b/example/devstack-gate.yml @@ -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 diff --git a/example/devstack.yml b/example/devstack.yml new file mode 100644 index 000000000..e78ddf03c --- /dev/null +++ b/example/devstack.yml @@ -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 diff --git a/example/gerrit-verification-status-plugin.yml b/example/gerrit-verification-status-plugin.yml new file mode 100644 index 000000000..264a1cded --- /dev/null +++ b/example/gerrit-verification-status-plugin.yml @@ -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 diff --git a/example/gerrit.yml b/example/gerrit.yml new file mode 100644 index 000000000..3f200cc28 --- /dev/null +++ b/example/gerrit.yml @@ -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/' diff --git a/example/gerritbot.yml b/example/gerritbot.yml new file mode 100644 index 000000000..b5ba6b380 --- /dev/null +++ b/example/gerritbot.yml @@ -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' diff --git a/example/gerritlib.yml b/example/gerritlib.yml new file mode 100644 index 000000000..1e775c9e5 --- /dev/null +++ b/example/gerritlib.yml @@ -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' diff --git a/example/glance.yml b/example/glance.yml new file mode 100644 index 000000000..7806057eb --- /dev/null +++ b/example/glance.yml @@ -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 diff --git a/example/heat.yml b/example/heat.yml new file mode 100644 index 000000000..85ba5c00d --- /dev/null +++ b/example/heat.yml @@ -0,0 +1,7 @@ +- project: + name: heat + github-org: heat-api + node: oneiric + + jobs: + - python-jobs diff --git a/example/horizon.yml b/example/horizon.yml new file mode 100644 index 000000000..92970a1b7 --- /dev/null +++ b/example/horizon.yml @@ -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 diff --git a/example/jenkins-job-builder.yml b/example/jenkins-job-builder.yml new file mode 100644 index 000000000..29f395294 --- /dev/null +++ b/example/jenkins-job-builder.yml @@ -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 diff --git a/example/keystone.yml b/example/keystone.yml new file mode 100644 index 000000000..a1a0d9865 --- /dev/null +++ b/example/keystone.yml @@ -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 diff --git a/example/macros.yml b/example/macros.yml new file mode 100644 index 000000000..8af5dcad1 --- /dev/null +++ b/example/macros.yml @@ -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}' diff --git a/example/mraas.yml b/example/mraas.yml new file mode 100644 index 000000000..e148cef2c --- /dev/null +++ b/example/mraas.yml @@ -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 diff --git a/example/nova.yml b/example/nova.yml new file mode 100644 index 000000000..0dfd2a8eb --- /dev/null +++ b/example/nova.yml @@ -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 diff --git a/example/openstack-ci-puppet.yml b/example/openstack-ci-puppet.yml new file mode 100644 index 000000000..668039061 --- /dev/null +++ b/example/openstack-ci-puppet.yml @@ -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 diff --git a/example/openstack-common.yml b/example/openstack-common.yml new file mode 100644 index 000000000..16b5005b9 --- /dev/null +++ b/example/openstack-common.yml @@ -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 diff --git a/example/openstack-publish-jobs.yml b/example/openstack-publish-jobs.yml new file mode 100644 index 000000000..a78c53f35 --- /dev/null +++ b/example/openstack-publish-jobs.yml @@ -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' diff --git a/example/pbr.yml b/example/pbr.yml new file mode 100644 index 000000000..6025e33eb --- /dev/null +++ b/example/pbr.yml @@ -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 diff --git a/example/pypi-jobs.yml b/example/pypi-jobs.yml new file mode 100644 index 000000000..68fc96559 --- /dev/null +++ b/example/pypi-jobs.yml @@ -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' diff --git a/example/pypi-mirror.yml b/example/pypi-mirror.yml new file mode 100644 index 000000000..bed7e5808 --- /dev/null +++ b/example/pypi-mirror.yml @@ -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 diff --git a/example/python-bitrot-jobs.yml b/example/python-bitrot-jobs.yml new file mode 100644 index 000000000..5b1d6fc22 --- /dev/null +++ b/example/python-bitrot-jobs.yml @@ -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}' diff --git a/example/python-cinderclient.yml b/example/python-cinderclient.yml new file mode 100644 index 000000000..d05a16f76 --- /dev/null +++ b/example/python-cinderclient.yml @@ -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 diff --git a/example/python-glanceclient.yml b/example/python-glanceclient.yml new file mode 100644 index 000000000..691737e26 --- /dev/null +++ b/example/python-glanceclient.yml @@ -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 diff --git a/example/python-jobs.yml b/example/python-jobs.yml new file mode 100644 index 000000000..20233bb8d --- /dev/null +++ b/example/python-jobs.yml @@ -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 diff --git a/example/python-keystoneclient.yml b/example/python-keystoneclient.yml new file mode 100644 index 000000000..6d4f94d1c --- /dev/null +++ b/example/python-keystoneclient.yml @@ -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 diff --git a/example/python-novaclient.yml b/example/python-novaclient.yml new file mode 100644 index 000000000..08ac2a3ab --- /dev/null +++ b/example/python-novaclient.yml @@ -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 diff --git a/example/python-openstackclient.yml b/example/python-openstackclient.yml new file mode 100644 index 000000000..caac05c5a --- /dev/null +++ b/example/python-openstackclient.yml @@ -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 diff --git a/example/python-quantumclient.yml b/example/python-quantumclient.yml new file mode 100644 index 000000000..64c5c3f8d --- /dev/null +++ b/example/python-quantumclient.yml @@ -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 diff --git a/example/python-swiftclient.yml b/example/python-swiftclient.yml new file mode 100644 index 000000000..ab0e47b66 --- /dev/null +++ b/example/python-swiftclient.yml @@ -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 diff --git a/example/quantum.yml b/example/quantum.yml new file mode 100644 index 000000000..3bae88f7e --- /dev/null +++ b/example/quantum.yml @@ -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 diff --git a/example/reddwarf.yml b/example/reddwarf.yml new file mode 100644 index 000000000..7786f8e6e --- /dev/null +++ b/example/reddwarf.yml @@ -0,0 +1,7 @@ +- project: + name: reddwarf + github-org: stackforge + node: oneiric + + jobs: + - python-jobs diff --git a/example/requirements.yml b/example/requirements.yml new file mode 100644 index 000000000..c0c01a942 --- /dev/null +++ b/example/requirements.yml @@ -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 diff --git a/example/swift.yml b/example/swift.yml new file mode 100644 index 000000000..6faa2c651 --- /dev/null +++ b/example/swift.yml @@ -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 diff --git a/example/tempest.yml b/example/tempest.yml new file mode 100644 index 000000000..4f4739b0a --- /dev/null +++ b/example/tempest.yml @@ -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 diff --git a/example/zuul.yml b/example/zuul.yml new file mode 100644 index 000000000..bbe44c0b6 --- /dev/null +++ b/example/zuul.yml @@ -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 diff --git a/jenkins-jobs b/jenkins-jobs new file mode 100755 index 000000000..6e74058f5 --- /dev/null +++ b/jenkins-jobs @@ -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() diff --git a/jenkins_jobs.py b/jenkins_jobs.py deleted file mode 100644 index 92bce197a..000000000 --- a/jenkins_jobs.py +++ /dev/null @@ -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+\g<1>\n\s+([^<>\s].*?)\n\s+\g<1> + + FTP: + + + + docs.openstack.org + true + + + + openstack-identity-api/target/docbkx/webhelp/api/openstack-identity-service/2.0/** + **/*.xml,**/null* + openstack-identity-api/target/docbkx/webhelp + false + false + false + false + + + false + false + + + false + false + false + + + + + """ + 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) + + + diff --git a/jenkins_jobs/modules/scm.py b/jenkins_jobs/modules/scm.py new file mode 100644 index 000000000..470ce7de0 --- /dev/null +++ b/jenkins_jobs/modules/scm.py @@ -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'}) + diff --git a/jenkins_jobs/modules/triggers.py b/jenkins_jobs/modules/triggers.py new file mode 100644 index 000000000..abaa2620a --- /dev/null +++ b/jenkins_jobs/modules/triggers.py @@ -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) + diff --git a/jenkins_jobs/modules/wrappers.py b/jenkins_jobs/modules/wrappers.py new file mode 100644 index 000000000..e15513edd --- /dev/null +++ b/jenkins_jobs/modules/wrappers.py @@ -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) + diff --git a/jenkins_jobs/modules/zuul.py b/jenkins_jobs/modules/zuul.py new file mode 100644 index 000000000..338a50f07 --- /dev/null +++ b/jenkins_jobs/modules/zuul.py @@ -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 diff --git a/modules/builders.py b/modules/builders.py deleted file mode 100644 index 61110df6d..000000000 --- a/modules/builders.py +++ /dev/null @@ -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') diff --git a/modules/properties.py b/modules/properties.py deleted file mode 100644 index 964e17fbb..000000000 --- a/modules/properties.py +++ /dev/null @@ -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'] diff --git a/modules/publishers.py b/modules/publishers.py deleted file mode 100644 index a2022d75b..000000000 --- a/modules/publishers.py +++ /dev/null @@ -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: - - - FTP: - - - - docs.openstack.org - true - - - - openstack-identity-api/target/docbkx/webhelp/api/openstack-identity-service/2.0/** - **/*.xml,**/null* - openstack-identity-api/target/docbkx/webhelp - false - false - false - false - - - false - false - - - false - false - false - - - - - """ - 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'] diff --git a/modules/scm.py b/modules/scm.py deleted file mode 100644 index 1b8ffbabc..000000000 --- a/modules/scm.py +++ /dev/null @@ -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'}) - diff --git a/modules/triggers.py b/modules/triggers.py deleted file mode 100644 index 0e77dbc08..000000000 --- a/modules/triggers.py +++ /dev/null @@ -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 diff --git a/modules/wrappers.py b/modules/wrappers.py deleted file mode 100644 index bab009107..000000000 --- a/modules/wrappers.py +++ /dev/null @@ -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') diff --git a/modules/zuul.py b/modules/zuul.py deleted file mode 100644 index 54b59c373..000000000 --- a/modules/zuul.py +++ /dev/null @@ -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') diff --git a/projects/openstack/zuul.yml b/projects/openstack/zuul.yml index f7fc79f1d..2e04748bc 100644 --- a/projects/openstack/zuul.yml +++ b/projects/openstack/zuul.yml @@ -1,71 +1,62 @@ -project: - template: 'python_jobs' +#project: +# template: 'python_jobs' +# +#values: +# name: 'zuul' +# disabled: 'false' +# github_org: 'openstack-ci' +# review_site: 'review.openstack.org' +# node: 'precise' +# +#--- -values: - name: 'zuul' - disabled: 'false' - github_org: 'openstack-ci' - review_site: 'review.openstack.org' - node: 'precise' +- job: + name: gate-zuul-pyflakes + project-type: freestyle + concurrent: true + timeout: 20 + timeout_fail: true ---- -# pyflakes-gate -main: - name: 'gate-zuul-pyflakes' - review_site: 'review.openstack.org' - github_org: 'openstack-ci' - project: 'zuul' - concurrent: 'true' - timeout: 20 - timeout_fail: true + triggers: + - zuul -triggers: - - zuul + builders: + - gerrit_git_prep + - pyflakes -builders: - - gerrit_git_prep - - pyflakes + assignednode: + node: 'precise' -scm: - scm: 'false' +- job: + name: zuul-docs + project-type: freestyle + #review_site: 'review.openstack.org' + #github_org: 'openstack-ci' + #project: 'zuul' + #authenticatedBuild: 'false' + concurrent: true + timeout: 20 + timeout_fail: true -assignednode: - node: 'precise' + triggers: + - zuul_post ---- -# zuul-docs -main: - name: 'zuul-docs' - review_site: 'review.openstack.org' - github_org: 'openstack-ci' - project: 'zuul' - authenticatedBuild: 'false' - concurrent: 'true' - timeout: 20 - timeout_fail: true + logrotate: + daysToKeep: 28 + numToKeep: -1 + artifactDaysToKeep: -1 + artifactNumToKeep: -1 -triggers: - - zuul_post + builders: + - gerrit_git_prep + - docs -logrotate: - daysToKeep: 28 - numToKeep: -1 - artifactDaysToKeep: -1 - artifactNumToKeep: -1 + post_build_actions: + - scp: + site: '173.203.107.207' + source: 'doc/build/html/**/*' + target_path: 'ci/zuul' + keep_heirarchy: 'true' -builders: - - gerrit_git_prep - - docs - -post_build_actions: - - scp: - site: '173.203.107.207' - source: 'doc/build/html/**/*' - target_path: 'ci/zuul' - keep_heirarchy: 'true' - -scm: - scm: 'false' - -assignednode: - node: 'precise' + assignednode: + node: 'precise' diff --git a/setup.py b/setup.py new file mode 100644 index 000000000..94876b7c3 --- /dev/null +++ b/setup.py @@ -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', + ] + } + + ) diff --git a/test.sh b/test.sh index ce2bcb5d0..b5bec2a67 100755 --- a/test.sh +++ b/test.sh @@ -9,18 +9,19 @@ mkdir -p /tmp/jenkins_jobs_test/test if [ "$1" == "save" ] then - for x in `find projects/ -name *.yml` - do - echo $x - BASENAME=`basename $x` - python jenkins_jobs.py test $x > /tmp/jenkins_jobs_test/saved/$BASENAME.xml - done + rm -f /tmp/jenkins_jobs_test/saved/* + jenkins-jobs test -o /tmp/jenkins_jobs_test/saved/ example else - for x in `find projects/ -name *.yml` + rm -f /tmp/jenkins_jobs_test/test/* + jenkins-jobs test -o /tmp/jenkins_jobs_test/test/ example + for x in `(cd /tmp/jenkins_jobs_test/saved && find -type f)` do - echo $x - BASENAME=`basename $x` - python jenkins_jobs.py test $x > /tmp/jenkins_jobs_test/test/$BASENAME.xml + if ! diff -u /tmp/jenkins_jobs_test/saved/$x /tmp/jenkins_jobs_test/test/$x >/dev/null 2>&1 + then + echo "============================================================" + echo $x + echo "------------------------------------------------------------" + fi + diff -u /tmp/jenkins_jobs_test/saved/$x /tmp/jenkins_jobs_test/test/$x done - diff -r /tmp/jenkins_jobs_test/saved /tmp/jenkins_jobs_test/test fi