scms: MultiSCM is generated for scms hidden in macro
This patch fixes problem with generating MultiSCM in case that scms are encapsulated in macro. This patch includes simple tests to cover if-branches for this change. Example: - scm: name: xxx scm: - git: ... - scm: name: yyy scm: - git: ... - scm: name: xxx-and-yyy scm: - xxx - yyy - job: name: my-job scm: - xxx-and-yyy Change-Id: If3e7b3d19e51545a5623ee060fb7673a7a989233 Signed-off-by: Lukas Bednar <lbednar@redhat.com> Closes-bug: #1285515
This commit is contained in:
parent
564953609c
commit
34ea32ba80
@ -18,14 +18,17 @@ The SCM module allows you to specify the source code location for the
|
||||
project. It adds the ``scm`` attribute to the :ref:`Job` definition,
|
||||
which accepts any number of scm definitions.
|
||||
|
||||
Note: Adding more than one scm definition requires the Jenkins `Multiple
|
||||
SCMs plugin.
|
||||
<https://wiki.jenkins-ci.org/display/JENKINS/Multiple+SCMs+Plugin>`_
|
||||
|
||||
**Component**: scm
|
||||
:Macro: scm
|
||||
:Entry Point: jenkins_jobs.scm
|
||||
|
||||
The scm module allows referencing multiple repositories in a Jenkins job.
|
||||
Note: Adding more than one scm definition requires the Jenkins `Multiple
|
||||
SCMs plugin.
|
||||
<https://wiki.jenkins-ci.org/display/JENKINS/Multiple+SCMs+Plugin>`_
|
||||
|
||||
Example of multiple repositories in a single job:
|
||||
.. literalinclude:: /../../tests/macros/scm/multi-scms001.yaml
|
||||
"""
|
||||
|
||||
|
||||
@ -537,14 +540,16 @@ class SCM(jenkins_jobs.modules.base.Base):
|
||||
component_list_type = 'scm'
|
||||
|
||||
def gen_xml(self, parser, xml_parent, data):
|
||||
scms = data.get('scm', [])
|
||||
if scms:
|
||||
if len(scms) > 1:
|
||||
scms_parent = XML.Element('scms')
|
||||
for scm in data.get('scm', []):
|
||||
self.registry.dispatch('scm', parser, scms_parent, scm)
|
||||
scms_count = len(scms_parent)
|
||||
if scms_count == 0:
|
||||
XML.SubElement(xml_parent, 'scm', {'class': 'hudson.scm.NullSCM'})
|
||||
elif scms_count == 1:
|
||||
xml_parent.append(scms_parent[0])
|
||||
else:
|
||||
class_name = 'org.jenkinsci.plugins.multiplescms.MultiSCM'
|
||||
xml_attribs = {'class': class_name}
|
||||
xml_parent = XML.SubElement(xml_parent, 'scm', xml_attribs)
|
||||
xml_parent = XML.SubElement(xml_parent, 'scms')
|
||||
for scm in data.get('scm', []):
|
||||
self.registry.dispatch('scm', parser, xml_parent, scm)
|
||||
else:
|
||||
XML.SubElement(xml_parent, 'scm', {'class': 'hudson.scm.NullSCM'})
|
||||
xml_parent.append(scms_parent)
|
||||
|
@ -22,8 +22,10 @@ import logging
|
||||
import os
|
||||
import re
|
||||
import doctest
|
||||
import operator
|
||||
import testtools
|
||||
import xml.etree.ElementTree as XML
|
||||
from ConfigParser import ConfigParser
|
||||
import yaml
|
||||
from jenkins_jobs.builder import XmlJob, YamlParser, ModuleRegistry
|
||||
from jenkins_jobs.modules import (project_flow,
|
||||
@ -120,3 +122,40 @@ class BaseTestCase(object):
|
||||
doctest.NORMALIZE_WHITESPACE |
|
||||
doctest.REPORT_NDIFF)
|
||||
)
|
||||
|
||||
|
||||
class SingleJobTestCase(BaseTestCase):
|
||||
def test_yaml_snippet(self):
|
||||
if not self.xml_filename or not self.yaml_filename:
|
||||
return
|
||||
|
||||
xml_filepath = os.path.join(self.fixtures_path, self.xml_filename)
|
||||
expected_xml = u"%s" % open(xml_filepath, 'r').read()
|
||||
|
||||
yaml_filepath = os.path.join(self.fixtures_path, self.yaml_filename)
|
||||
|
||||
if self.conf_filename:
|
||||
config = ConfigParser()
|
||||
conf_filepath = os.path.join(self.fixtures_path,
|
||||
self.conf_filename)
|
||||
config.readfp(open(conf_filepath))
|
||||
else:
|
||||
config = None
|
||||
parser = YamlParser(config)
|
||||
parser.parse(yaml_filepath)
|
||||
|
||||
# Generate the XML tree
|
||||
parser.generateXML()
|
||||
|
||||
parser.jobs.sort(key=operator.attrgetter('name'))
|
||||
|
||||
# Prettify generated XML
|
||||
pretty_xml = "\n".join(job.output() for job in parser.jobs)
|
||||
|
||||
self.assertThat(
|
||||
pretty_xml,
|
||||
testtools.matchers.DocTestMatches(expected_xml,
|
||||
doctest.ELLIPSIS |
|
||||
doctest.NORMALIZE_WHITESPACE |
|
||||
doctest.REPORT_NDIFF)
|
||||
)
|
||||
|
0
tests/macros/__init__.py
Normal file
0
tests/macros/__init__.py
Normal file
86
tests/macros/scm/multi-scms001.xml
Normal file
86
tests/macros/scm/multi-scms001.xml
Normal file
@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project>
|
||||
<actions/>
|
||||
<description><!-- Managed by Jenkins Job Builder --></description>
|
||||
<keepDependencies>false</keepDependencies>
|
||||
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
|
||||
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
|
||||
<concurrentBuild>false</concurrentBuild>
|
||||
<canRoam>true</canRoam>
|
||||
<properties/>
|
||||
<scm class="org.jenkinsci.plugins.multiplescms.MultiSCM">
|
||||
<scms>
|
||||
<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/first.git</url>
|
||||
</hudson.plugins.git.UserRemoteConfig>
|
||||
</userRemoteConfigs>
|
||||
<branches>
|
||||
<hudson.plugins.git.BranchSpec>
|
||||
<name>origin/master</name>
|
||||
</hudson.plugins.git.BranchSpec>
|
||||
</branches>
|
||||
<excludedUsers/>
|
||||
<buildChooser class="hudson.plugins.git.util.DefaultBuildChooser"/>
|
||||
<disableSubmodules>false</disableSubmodules>
|
||||
<recursiveSubmodules>false</recursiveSubmodules>
|
||||
<doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
|
||||
<authorOrCommitter>false</authorOrCommitter>
|
||||
<clean>false</clean>
|
||||
<wipeOutWorkspace>true</wipeOutWorkspace>
|
||||
<pruneBranches>false</pruneBranches>
|
||||
<remotePoll>false</remotePoll>
|
||||
<gitTool>Default</gitTool>
|
||||
<submoduleCfg class="list"/>
|
||||
<relativeTargetDir/>
|
||||
<reference/>
|
||||
<gitConfigName/>
|
||||
<gitConfigEmail/>
|
||||
<skipTag>false</skipTag>
|
||||
<scmName/>
|
||||
<useShallowClone>false</useShallowClone>
|
||||
</scm>
|
||||
<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/second.git</url>
|
||||
</hudson.plugins.git.UserRemoteConfig>
|
||||
</userRemoteConfigs>
|
||||
<branches>
|
||||
<hudson.plugins.git.BranchSpec>
|
||||
<name>origin/master</name>
|
||||
</hudson.plugins.git.BranchSpec>
|
||||
</branches>
|
||||
<excludedUsers/>
|
||||
<buildChooser class="hudson.plugins.git.util.DefaultBuildChooser"/>
|
||||
<disableSubmodules>false</disableSubmodules>
|
||||
<recursiveSubmodules>false</recursiveSubmodules>
|
||||
<doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
|
||||
<authorOrCommitter>false</authorOrCommitter>
|
||||
<clean>false</clean>
|
||||
<wipeOutWorkspace>true</wipeOutWorkspace>
|
||||
<pruneBranches>false</pruneBranches>
|
||||
<remotePoll>false</remotePoll>
|
||||
<gitTool>Default</gitTool>
|
||||
<submoduleCfg class="list"/>
|
||||
<relativeTargetDir/>
|
||||
<reference/>
|
||||
<gitConfigName/>
|
||||
<gitConfigEmail/>
|
||||
<skipTag>false</skipTag>
|
||||
<scmName/>
|
||||
<useShallowClone>false</useShallowClone>
|
||||
</scm>
|
||||
</scms>
|
||||
</scm>
|
||||
<builders/>
|
||||
<publishers/>
|
||||
<buildWrappers/>
|
||||
</project>
|
26
tests/macros/scm/multi-scms001.yaml
Normal file
26
tests/macros/scm/multi-scms001.yaml
Normal file
@ -0,0 +1,26 @@
|
||||
- scm:
|
||||
name: first-scm
|
||||
scm:
|
||||
- git:
|
||||
url: ssh://jenkins@review.openstack.org:29418/first.git
|
||||
branches:
|
||||
- origin/master
|
||||
|
||||
- scm:
|
||||
name: second-scm
|
||||
scm:
|
||||
- git:
|
||||
url: ssh://jenkins@review.openstack.org:29418/second.git
|
||||
branches:
|
||||
- origin/master
|
||||
|
||||
- scm:
|
||||
name: first-and-second
|
||||
scm:
|
||||
- first-scm
|
||||
- second-scm
|
||||
|
||||
- job:
|
||||
name: my-job
|
||||
scm:
|
||||
- first-and-second
|
64
tests/macros/scm/multi-scms002.xml
Normal file
64
tests/macros/scm/multi-scms002.xml
Normal file
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project>
|
||||
<actions/>
|
||||
<description><!-- Managed by Jenkins Job Builder --></description>
|
||||
<keepDependencies>false</keepDependencies>
|
||||
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
|
||||
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
|
||||
<concurrentBuild>false</concurrentBuild>
|
||||
<canRoam>true</canRoam>
|
||||
<properties/>
|
||||
<scm class="org.jenkinsci.plugins.multiplescms.MultiSCM">
|
||||
<scms>
|
||||
<scm class="hudson.plugins.repo.RepoScm">
|
||||
<manifestRepositoryUrl>https://example.com/project/</manifestRepositoryUrl>
|
||||
<manifestBranch>stable</manifestBranch>
|
||||
<manifestFile>repo.xml</manifestFile>
|
||||
<manifestGroup>drivers</manifestGroup>
|
||||
<destinationDir>build</destinationDir>
|
||||
<repoUrl>https://internal.net/projects/repo</repoUrl>
|
||||
<mirrorDir>~/git/project/</mirrorDir>
|
||||
<jobs>3</jobs>
|
||||
<currentBranch>false</currentBranch>
|
||||
<quiet>false</quiet>
|
||||
</scm>
|
||||
<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/second.git</url>
|
||||
</hudson.plugins.git.UserRemoteConfig>
|
||||
</userRemoteConfigs>
|
||||
<branches>
|
||||
<hudson.plugins.git.BranchSpec>
|
||||
<name>origin/master</name>
|
||||
</hudson.plugins.git.BranchSpec>
|
||||
</branches>
|
||||
<excludedUsers/>
|
||||
<buildChooser class="hudson.plugins.git.util.DefaultBuildChooser"/>
|
||||
<disableSubmodules>false</disableSubmodules>
|
||||
<recursiveSubmodules>false</recursiveSubmodules>
|
||||
<doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
|
||||
<authorOrCommitter>false</authorOrCommitter>
|
||||
<clean>false</clean>
|
||||
<wipeOutWorkspace>true</wipeOutWorkspace>
|
||||
<pruneBranches>false</pruneBranches>
|
||||
<remotePoll>false</remotePoll>
|
||||
<gitTool>Default</gitTool>
|
||||
<submoduleCfg class="list"/>
|
||||
<relativeTargetDir/>
|
||||
<reference/>
|
||||
<gitConfigName/>
|
||||
<gitConfigEmail/>
|
||||
<skipTag>false</skipTag>
|
||||
<scmName/>
|
||||
<useShallowClone>false</useShallowClone>
|
||||
</scm>
|
||||
</scms>
|
||||
</scm>
|
||||
<builders/>
|
||||
<publishers/>
|
||||
<buildWrappers/>
|
||||
</project>
|
33
tests/macros/scm/multi-scms002.yaml
Normal file
33
tests/macros/scm/multi-scms002.yaml
Normal file
@ -0,0 +1,33 @@
|
||||
- scm:
|
||||
name: first-scm
|
||||
scm:
|
||||
- repo:
|
||||
manifest-url: https://example.com/project/
|
||||
manifest-branch: stable
|
||||
manifest-file: repo.xml
|
||||
manifest-group: drivers
|
||||
destination-dir: build
|
||||
repo-url: https://internal.net/projects/repo
|
||||
mirror-dir: ~/git/project/
|
||||
jobs: 3
|
||||
current-branch: false
|
||||
quiet: false
|
||||
|
||||
- scm:
|
||||
name: second-scm
|
||||
scm:
|
||||
- git:
|
||||
url: ssh://jenkins@review.openstack.org:29418/second.git
|
||||
branches:
|
||||
- origin/master
|
||||
|
||||
- scm:
|
||||
name: first-and-second
|
||||
scm:
|
||||
- first-scm
|
||||
- second-scm
|
||||
|
||||
- job:
|
||||
name: my-job
|
||||
scm:
|
||||
- first-and-second
|
15
tests/macros/scm/scm001.xml
Normal file
15
tests/macros/scm/scm001.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project>
|
||||
<actions/>
|
||||
<description><!-- Managed by Jenkins Job Builder --></description>
|
||||
<keepDependencies>false</keepDependencies>
|
||||
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
|
||||
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
|
||||
<concurrentBuild>false</concurrentBuild>
|
||||
<canRoam>true</canRoam>
|
||||
<properties/>
|
||||
<scm class="hudson.scm.NullSCM"/>
|
||||
<builders/>
|
||||
<publishers/>
|
||||
<buildWrappers/>
|
||||
</project>
|
3
tests/macros/scm/scm001.yaml
Normal file
3
tests/macros/scm/scm001.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
- job:
|
||||
name: my-job
|
||||
scm: !!seq []
|
48
tests/macros/scm/scm002.xml
Normal file
48
tests/macros/scm/scm002.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project>
|
||||
<actions/>
|
||||
<description><!-- Managed by Jenkins Job Builder --></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/repository.git</url>
|
||||
</hudson.plugins.git.UserRemoteConfig>
|
||||
</userRemoteConfigs>
|
||||
<branches>
|
||||
<hudson.plugins.git.BranchSpec>
|
||||
<name>origin/master</name>
|
||||
</hudson.plugins.git.BranchSpec>
|
||||
</branches>
|
||||
<excludedUsers/>
|
||||
<buildChooser class="hudson.plugins.git.util.DefaultBuildChooser"/>
|
||||
<disableSubmodules>false</disableSubmodules>
|
||||
<recursiveSubmodules>false</recursiveSubmodules>
|
||||
<doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
|
||||
<authorOrCommitter>false</authorOrCommitter>
|
||||
<clean>false</clean>
|
||||
<wipeOutWorkspace>true</wipeOutWorkspace>
|
||||
<pruneBranches>false</pruneBranches>
|
||||
<remotePoll>false</remotePoll>
|
||||
<gitTool>Default</gitTool>
|
||||
<submoduleCfg class="list"/>
|
||||
<relativeTargetDir/>
|
||||
<reference/>
|
||||
<gitConfigName/>
|
||||
<gitConfigEmail/>
|
||||
<skipTag>false</skipTag>
|
||||
<scmName/>
|
||||
<useShallowClone>false</useShallowClone>
|
||||
</scm>
|
||||
<builders/>
|
||||
<publishers/>
|
||||
<buildWrappers/>
|
||||
</project>
|
12
tests/macros/scm/scm002.yaml
Normal file
12
tests/macros/scm/scm002.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
- scm:
|
||||
name: repository
|
||||
scm:
|
||||
- git:
|
||||
url: ssh://jenkins@review.openstack.org:29418/repository.git
|
||||
branches:
|
||||
- origin/master
|
||||
|
||||
- job:
|
||||
name: my-job
|
||||
scm:
|
||||
- repository
|
26
tests/macros/test_macros.py
Normal file
26
tests/macros/test_macros.py
Normal file
@ -0,0 +1,26 @@
|
||||
# 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 TestCaseModuleSCMMacro(TestWithScenarios, TestCase, SingleJobTestCase):
|
||||
fixtures_path = os.path.join(os.path.dirname(__file__), 'scm')
|
||||
scenarios = get_scenarios(fixtures_path)
|
@ -15,52 +15,13 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import operator
|
||||
import os
|
||||
from ConfigParser import ConfigParser
|
||||
from testtools import TestCase
|
||||
from testscenarios.testcase import TestWithScenarios
|
||||
from tests.base import get_scenarios, BaseTestCase
|
||||
import doctest
|
||||
import testtools
|
||||
from jenkins_jobs.builder import YamlParser
|
||||
from tests.base import get_scenarios, SingleJobTestCase
|
||||
|
||||
|
||||
class TestCaseModuleYamlInclude(TestWithScenarios, TestCase, BaseTestCase):
|
||||
class TestCaseModuleYamlInclude(TestWithScenarios, TestCase,
|
||||
SingleJobTestCase):
|
||||
fixtures_path = os.path.join(os.path.dirname(__file__), 'fixtures')
|
||||
scenarios = get_scenarios(fixtures_path)
|
||||
|
||||
def test_yaml_snippet(self):
|
||||
if not self.xml_filename or not self.yaml_filename:
|
||||
return
|
||||
|
||||
xml_filepath = os.path.join(self.fixtures_path, self.xml_filename)
|
||||
expected_xml = u"%s" % open(xml_filepath, 'r').read()
|
||||
|
||||
yaml_filepath = os.path.join(self.fixtures_path, self.yaml_filename)
|
||||
|
||||
if self.conf_filename:
|
||||
config = ConfigParser()
|
||||
conf_filepath = os.path.join(self.fixtures_path,
|
||||
self.conf_filename)
|
||||
config.readfp(open(conf_filepath))
|
||||
else:
|
||||
config = None
|
||||
parser = YamlParser(config)
|
||||
parser.parse(yaml_filepath)
|
||||
|
||||
# Generate the XML tree
|
||||
parser.generateXML()
|
||||
|
||||
parser.jobs.sort(key=operator.attrgetter('name'))
|
||||
|
||||
# Prettify generated XML
|
||||
pretty_xml = "\n".join(job.output() for job in parser.jobs)
|
||||
|
||||
self.assertThat(
|
||||
pretty_xml,
|
||||
testtools.matchers.DocTestMatches(expected_xml,
|
||||
doctest.ELLIPSIS |
|
||||
doctest.NORMALIZE_WHITESPACE |
|
||||
doctest.REPORT_NDIFF)
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user