Document that jjb supports json job definitions

Add documentation to let users know that they can also define jobs
in JSON.  Create a new test suite to verify that jjb can correctly
generate jenkins xml from json definitions.

Change-Id: Idb5216b0b56837d0f4dd2298986149be66bd217e
This commit is contained in:
Khai Do 2015-07-27 22:49:41 -07:00
parent f1c34249cc
commit e52bb31fa1
9 changed files with 394 additions and 8 deletions

View File

@ -1,11 +1,11 @@
README
======
Jenkins Job Builder takes simple descriptions of Jenkins_ jobs in YAML_ format,
and uses them to configure Jenkins. You can keep your job descriptions in human
readable text format in a version control system to make changes and auditing
easier. It also has a flexible template system, so creating many similarly
configured jobs is easy.
Jenkins Job Builder takes simple descriptions of Jenkins_ jobs in YAML_ or JSON_
format and uses them to configure Jenkins. You can keep your job descriptions in
human readable text format in a version control system to make changes and
auditing easier. It also has a flexible template system, so creating many
similarly configured jobs is easy.
To install::
@ -77,6 +77,7 @@ Then install the required python packages using pip_::
.. _Jenkins: http://jenkins-ci.org/
.. _YAML: http://www.yaml.org/
.. _JSON: http://json.org/
.. _pep8: https://pypi.python.org/pypi/pep8
.. _pyflakes: https://pypi.python.org/pypi/pyflakes
.. _tox: https://testrun.org/tox

View File

@ -2,10 +2,10 @@ Job Definitions
===============
The job definitions for Jenkins Job Builder are kept in any number of
YAML files, in whatever way you would like to organize them. When you
YAML or JSON files, in whatever way you would like to organize them. When you
invoke ``jenkins-jobs`` you may specify either the path of a single
YAML file, or a directory. If you choose a directory, all of
the .yaml (or .yml) files in that directory will be read, and all the
the .yaml/.yml or .json files in that directory will be read, and all the
jobs they define will be created or updated.
Definitions

View File

@ -78,7 +78,7 @@ def get_scenarios(fixtures_path, in_ext='yaml', out_ext='xml',
if plugins_info_candidate not in files:
plugins_info_candidate = None
conf_candidate = re.sub(r'\.yaml$', '.conf', input_filename)
conf_candidate = re.sub(r'\.yaml$|\.json$', '.conf', input_filename)
# If present, add the configuration file
if conf_candidate not in files:
conf_candidate = None

View File

View File

@ -0,0 +1,168 @@
[
{
"wrapper": {
"name": "timeout-wrapper",
"wrappers": [
{
"timeout": {
"fail": true,
"elastic-percentage": 150,
"elastic-default-timeout": 90,
"type": "elastic"
}
}
]
}
},
{
"wrapper": {
"name": "pre-scm-shell-ant",
"wrappers": [
{
"pre-scm-buildstep": [
{
"shell": "#!/bin/bash\necho \"Doing somethiung cool\"\n"
},
{
"shell": "#!/bin/zsh\necho \"Doing somethin cool with zsh\"\n"
},
{
"ant": {
"targets": "target1 target2",
"ant-name": "Standard Ant"
}
},
{
"inject": {
"properties-file": "example.prop",
"properties-content": "EXAMPLE=foo-bar"
}
}
]
}
]
}
},
{
"wrapper": {
"name": "copy-files",
"wrappers": [
{
"copy-to-slave": {
"includes": [
"file1",
"file2*.txt"
],
"excludes": [
"file2bad.txt"
]
}
}
]
}
},
{
"trigger": {
"name": "gerrit-review",
"triggers": [
{
"gerrit": {
"trigger-on-patchset-uploaded-event": true,
"trigger-on-change-merged-event": false,
"trigger-on-ref-updated-event": false,
"trigger-on-comment-added-event": false,
"override-votes": true,
"gerrit-build-started-verified-value": 0,
"gerrit-build-successful-verified-value": 1,
"gerrit-build-failed-verified-value": -1,
"gerrit-build-unstable-verified-value": -1,
"gerrit-build-notbuilt-verified-value": -1,
"gerrit-build-started-codereview-value": 0,
"gerrit-build-successful-codereview-value": 1,
"gerrit-build-failed-codereview-value": -1,
"gerrit-build-unstable-codereview-value": -1,
"gerrit-build-notbuilt-codereview-value": -1,
"projects": [
{
"project-compare-type": "PLAIN",
"project-pattern": "{project_pattern}",
"branches": [
{
"branch-compare-type": "ANT",
"branch-pattern": "**"
}
]
}
],
"start-message": "Start message.",
"failure-message": "Failed message.",
"successful-message": "Success message.",
"unstable-message": "Unstable message.",
"notbuilt-message": "Not built message."
}
}
]
}
},
{
"scm": {
"name": "gerrit-scm",
"scm": [
{
"git": {
"url": "ssh://jenkins@review.openstack.org:29418/{project_pattern}.git",
"branches": [
"origin/**"
],
"name": "origin",
"prune": true,
"clean": true,
"browser": "gitweb",
"browser-url": "http://review.openstack.org/gitweb?p={project_pattern}.git",
"choosing-strategy": "gerrit"
}
}
]
}
},
{
"project": {
"name": "complete001",
"version": [
1.2
],
"jobs": [
"complete001_{version}"
]
}
},
{
"job-template": {
"name": "complete001_{version}",
"scm": [
{
"gerrit-scm": {
"project_pattern": "openstack-infra/jenkins-job-builder"
}
}
],
"triggers": [
{
"gerrit-review": {
"project_pattern": "openstack-infra/jenkins-job-builder"
}
}
],
"wrappers": [
"timeout-wrapper",
"pre-scm-shell-ant",
"copy-files"
],
"builders": [
{
"shell": "#!/usr/bin/env python\n#\nprint(\"Doing something cool with python\")\n"
}
]
}
}
]

View File

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<project>
<actions/>
<description>&lt;!-- Managed by Jenkins Job Builder --&gt;</description>
<keepDependencies>false</keepDependencies>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<concurrentBuild>false</concurrentBuild>
<canRoam>true</canRoam>
<properties/>
<scm class="hudson.plugins.git.GitSCM">
<configVersion>2</configVersion>
<userRemoteConfigs>
<hudson.plugins.git.UserRemoteConfig>
<name>origin</name>
<refspec>+refs/heads/*:refs/remotes/origin/*</refspec>
<url>ssh://jenkins@review.openstack.org:29418/openstack-infra/jenkins-job-builder.git</url>
</hudson.plugins.git.UserRemoteConfig>
</userRemoteConfigs>
<branches>
<hudson.plugins.git.BranchSpec>
<name>origin/**</name>
</hudson.plugins.git.BranchSpec>
</branches>
<excludedUsers/>
<buildChooser class="com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritTriggerBuildChooser"/>
<disableSubmodules>false</disableSubmodules>
<recursiveSubmodules>false</recursiveSubmodules>
<doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
<authorOrCommitter>false</authorOrCommitter>
<wipeOutWorkspace>true</wipeOutWorkspace>
<pruneBranches>true</pruneBranches>
<remotePoll>false</remotePoll>
<gitTool>Default</gitTool>
<submoduleCfg class="list"/>
<relativeTargetDir/>
<reference/>
<gitConfigName/>
<gitConfigEmail/>
<skipTag>false</skipTag>
<scmName/>
<useShallowClone>false</useShallowClone>
<ignoreNotifyCommit>false</ignoreNotifyCommit>
<extensions>
<hudson.plugins.git.extensions.impl.CleanCheckout/>
<hudson.plugins.git.extensions.impl.WipeWorkspace/>
</extensions>
<browser class="hudson.plugins.git.browser.GitWeb">
<url>http://review.openstack.org/gitweb?p=openstack-infra/jenkins-job-builder.git</url>
</browser>
</scm>
<triggers class="vector">
<com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritTrigger>
<spec/>
<gerritProjects>
<com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.GerritProject>
<compareType>PLAIN</compareType>
<pattern>openstack-infra/jenkins-job-builder</pattern>
<branches>
<com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.Branch>
<compareType>ANT</compareType>
<pattern>**</pattern>
</com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.Branch>
</branches>
</com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.GerritProject>
</gerritProjects>
<skipVote>
<onSuccessful>false</onSuccessful>
<onFailed>false</onFailed>
<onUnstable>false</onUnstable>
<onNotBuilt>false</onNotBuilt>
</skipVote>
<silentMode>false</silentMode>
<silentStartMode>false</silentStartMode>
<escapeQuotes>true</escapeQuotes>
<noNameAndEmailParameters>false</noNameAndEmailParameters>
<readableMessage>false</readableMessage>
<dependencyJobsNames/>
<notificationLevel/>
<dynamicTriggerConfiguration>False</dynamicTriggerConfiguration>
<triggerConfigURL/>
<allowTriggeringUnreviewedPatches>false</allowTriggeringUnreviewedPatches>
<triggerOnEvents>
<com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.events.PluginPatchsetCreatedEvent/>
</triggerOnEvents>
<gerritBuildStartedVerifiedValue>0</gerritBuildStartedVerifiedValue>
<gerritBuildSuccessfulVerifiedValue>1</gerritBuildSuccessfulVerifiedValue>
<gerritBuildFailedVerifiedValue>-1</gerritBuildFailedVerifiedValue>
<gerritBuildUnstableVerifiedValue>-1</gerritBuildUnstableVerifiedValue>
<gerritBuildNotBuiltVerifiedValue>-1</gerritBuildNotBuiltVerifiedValue>
<gerritBuildStartedCodeReviewValue>0</gerritBuildStartedCodeReviewValue>
<gerritBuildSuccessfulCodeReviewValue>1</gerritBuildSuccessfulCodeReviewValue>
<gerritBuildFailedCodeReviewValue>-1</gerritBuildFailedCodeReviewValue>
<gerritBuildUnstableCodeReviewValue>-1</gerritBuildUnstableCodeReviewValue>
<gerritBuildNotBuiltCodeReviewValue>-1</gerritBuildNotBuiltCodeReviewValue>
<buildStartMessage>Start message.</buildStartMessage>
<buildFailureMessage>Failed message.</buildFailureMessage>
<buildSuccessfulMessage>Success message.</buildSuccessfulMessage>
<buildUnstableMessage>Unstable message.</buildUnstableMessage>
<buildNotBuiltMessage>Not built message.</buildNotBuiltMessage>
<buildUnsuccessfulFilepath/>
<customUrl/>
<serverName>__ANY__</serverName>
</com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritTrigger>
</triggers>
<builders>
<hudson.tasks.Shell>
<command>#!/usr/bin/env python
#
print(&quot;Doing something cool with python&quot;)
</command>
</hudson.tasks.Shell>
</builders>
<publishers/>
<buildWrappers>
<hudson.plugins.build__timeout.BuildTimeoutWrapper>
<timeoutMinutes>3</timeoutMinutes>
<failBuild>true</failBuild>
<writingDescription>false</writingDescription>
<timeoutPercentage>150</timeoutPercentage>
<timeoutMinutesElasticDefault>90</timeoutMinutesElasticDefault>
<timeoutType>elastic</timeoutType>
</hudson.plugins.build__timeout.BuildTimeoutWrapper>
<org.jenkinsci.plugins.preSCMbuildstep.PreSCMBuildStepsWrapper>
<buildSteps>
<hudson.tasks.Shell>
<command>#!/bin/bash
echo &quot;Doing somethiung cool&quot;
</command>
</hudson.tasks.Shell>
<hudson.tasks.Shell>
<command>#!/bin/zsh
echo &quot;Doing somethin cool with zsh&quot;
</command>
</hudson.tasks.Shell>
<hudson.tasks.Ant>
<targets>target1 target2</targets>
<antName>Standard Ant</antName>
</hudson.tasks.Ant>
<EnvInjectBuilder>
<info>
<propertiesFilePath>example.prop</propertiesFilePath>
<propertiesContent>EXAMPLE=foo-bar</propertiesContent>
</info>
</EnvInjectBuilder>
</buildSteps>
</org.jenkinsci.plugins.preSCMbuildstep.PreSCMBuildStepsWrapper>
<com.michelin.cio.hudson.plugins.copytoslave.CopyToSlaveBuildWrapper>
<includes>file1,file2*.txt</includes>
<excludes>file2bad.txt</excludes>
<flatten>false</flatten>
<includeAntExcludes>false</includeAntExcludes>
<relativeTo>userContent</relativeTo>
<hudsonHomeRelative>false</hudsonHomeRelative>
</com.michelin.cio.hudson.plugins.copytoslave.CopyToSlaveBuildWrapper>
</buildWrappers>
</project>

View File

@ -0,0 +1,13 @@
[
{
"job": {
"name": "simple",
"node": "centos",
"builders": [
{
"shell": "echo This is my job"
}
]
}
}
]

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<project>
<actions/>
<description>&lt;!-- Managed by Jenkins Job Builder --&gt;</description>
<keepDependencies>false</keepDependencies>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<concurrentBuild>false</concurrentBuild>
<assignedNode>centos</assignedNode>
<canRoam>false</canRoam>
<properties/>
<scm class="hudson.scm.NullSCM"/>
<builders>
<hudson.tasks.Shell>
<command>echo This is my job</command>
</hudson.tasks.Shell>
</builders>
<publishers/>
<buildWrappers/>
</project>

View File

@ -0,0 +1,27 @@
# Joint copyright:
# - Copyright 2012,2013 Wikimedia Foundation
# - Copyright 2012,2013 Antoine "hashar" Musso
# - Copyright 2013 Arnaud Fabre
#
# 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.
import os
from testtools import TestCase
from testscenarios.testcase import TestWithScenarios
from tests.base import get_scenarios, SingleJobTestCase
class TestCaseModuleJsonParser(TestWithScenarios, TestCase,
SingleJobTestCase):
fixtures_path = os.path.join(os.path.dirname(__file__), 'fixtures')
scenarios = get_scenarios(fixtures_path, in_ext='json', out_ext='xml')