diff --git a/README.rst b/README.rst index 935513a54..9ebee9375 100644 --- a/README.rst +++ b/README.rst @@ -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 diff --git a/doc/source/definition.rst b/doc/source/definition.rst index c5aa45986..f9e34a114 100644 --- a/doc/source/definition.rst +++ b/doc/source/definition.rst @@ -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 diff --git a/tests/base.py b/tests/base.py index 517cfc980..1bc8f5c8d 100644 --- a/tests/base.py +++ b/tests/base.py @@ -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 diff --git a/tests/jsonparser/__init__.py b/tests/jsonparser/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/jsonparser/fixtures/complete001.json b/tests/jsonparser/fixtures/complete001.json new file mode 100644 index 000000000..517e1cc2d --- /dev/null +++ b/tests/jsonparser/fixtures/complete001.json @@ -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" + } + ] + } + } +] \ No newline at end of file diff --git a/tests/jsonparser/fixtures/complete001.xml b/tests/jsonparser/fixtures/complete001.xml new file mode 100644 index 000000000..f90b2f59f --- /dev/null +++ b/tests/jsonparser/fixtures/complete001.xml @@ -0,0 +1,157 @@ + + + + <!-- Managed by Jenkins Job Builder --> + false + false + false + false + true + + + 2 + + + origin + +refs/heads/*:refs/remotes/origin/* + ssh://jenkins@review.openstack.org:29418/openstack-infra/jenkins-job-builder.git + + + + + origin/** + + + + + false + false + false + false + true + true + false + Default + + + + + + false + + false + false + + + + + + http://review.openstack.org/gitweb?p=openstack-infra/jenkins-job-builder.git + + + + + + + + PLAIN + openstack-infra/jenkins-job-builder + + + ANT + ** + + + + + + false + false + false + false + + false + false + true + false + false + + + False + + false + + + + 0 + 1 + -1 + -1 + -1 + 0 + 1 + -1 + -1 + -1 + Start message. + Failed message. + Success message. + Unstable message. + Not built message. + + + __ANY__ + + + + + #!/usr/bin/env python +# +print("Doing something cool with python") + + + + + + + 3 + true + false + 150 + 90 + elastic + + + + + #!/bin/bash +echo "Doing somethiung cool" + + + + #!/bin/zsh +echo "Doing somethin cool with zsh" + + + + target1 target2 + Standard Ant + + + + example.prop + EXAMPLE=foo-bar + + + + + + file1,file2*.txt + file2bad.txt + false + false + userContent + false + + + diff --git a/tests/jsonparser/fixtures/simple.json b/tests/jsonparser/fixtures/simple.json new file mode 100644 index 000000000..a47fe8db7 --- /dev/null +++ b/tests/jsonparser/fixtures/simple.json @@ -0,0 +1,13 @@ +[ + { + "job": { + "name": "simple", + "node": "centos", + "builders": [ + { + "shell": "echo This is my job" + } + ] + } + } +] \ No newline at end of file diff --git a/tests/jsonparser/fixtures/simple.xml b/tests/jsonparser/fixtures/simple.xml new file mode 100644 index 000000000..44d6abcfa --- /dev/null +++ b/tests/jsonparser/fixtures/simple.xml @@ -0,0 +1,20 @@ + + + + <!-- Managed by Jenkins Job Builder --> + false + false + false + false + centos + false + + + + + echo This is my job + + + + + \ No newline at end of file diff --git a/tests/jsonparser/test_jsonparser.py b/tests/jsonparser/test_jsonparser.py new file mode 100644 index 000000000..7b55e0a70 --- /dev/null +++ b/tests/jsonparser/test_jsonparser.py @@ -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')