Story: 2010984 Fix folder tests and defaults for folders
Folders was not actually tested by tests. Fix tests and add more tests. Fix bug in code unearthed by now-working tests: defaults were not checked for job folders. Task: 49188 Change-Id: I922af7a28b0ec0c99ef3f8a17b3d5a9c10f2dce0
This commit is contained in:
parent
36ea222763
commit
c1ac0e03d6
@ -454,7 +454,7 @@ Job Name Example:
|
||||
|
||||
Folder Attribute Example:
|
||||
|
||||
.. literalinclude:: /../../tests/yamlparser/job_fixtures/folders-attribute.yaml
|
||||
.. literalinclude:: /../../tests/yamlparser/job_fixtures/folders-defaults-for-job.yaml
|
||||
|
||||
|
||||
.. _ids:
|
||||
|
@ -28,6 +28,7 @@ job_contents_keys = {
|
||||
"pipeline-scm",
|
||||
"reporters",
|
||||
# General.
|
||||
"description",
|
||||
"project-type",
|
||||
"folder",
|
||||
"node",
|
||||
@ -89,6 +90,7 @@ job_contents_keys = {
|
||||
|
||||
view_contents_keys = {
|
||||
# Common.
|
||||
"description",
|
||||
"filter-executors",
|
||||
"filter-queue",
|
||||
# All
|
||||
|
@ -13,7 +13,6 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from .errors import JenkinsJobsException
|
||||
from .loc_loader import LocDict
|
||||
from .root_base import RootBase, NonTemplateRootMixin, TemplateRootMixin, Group
|
||||
from .defaults import split_contents_params, job_contents_keys
|
||||
|
||||
@ -49,21 +48,26 @@ class JobBase(RootBase):
|
||||
folder,
|
||||
)
|
||||
|
||||
def _as_dict(self):
|
||||
data = LocDict.merge(
|
||||
{"name": self._full_name},
|
||||
self.contents,
|
||||
)
|
||||
if self.project_type:
|
||||
data["project-type"] = self.project_type
|
||||
return data
|
||||
|
||||
@property
|
||||
def _full_name(self):
|
||||
def contents(self):
|
||||
contents = super().contents
|
||||
contents["name"] = self.name
|
||||
if self.project_type:
|
||||
contents["project-type"] = self.project_type
|
||||
if self.folder:
|
||||
return f"{self.folder}/{self.name}"
|
||||
contents["folder"] = self.folder
|
||||
return contents
|
||||
|
||||
def _expand_contents(self, contents, params):
|
||||
expanded_contents = super()._expand_contents(contents, params)
|
||||
try:
|
||||
folder = expanded_contents["folder"]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
return self.name
|
||||
name = expanded_contents["name"]
|
||||
expanded_contents["name"] = f"{folder}/{name}"
|
||||
return expanded_contents
|
||||
|
||||
|
||||
class Job(JobBase, NonTemplateRootMixin):
|
||||
|
@ -52,7 +52,7 @@ class RootBase:
|
||||
description: str
|
||||
defaults_name: str
|
||||
params: dict
|
||||
contents: dict
|
||||
_contents: dict
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
@ -65,19 +65,20 @@ class RootBase:
|
||||
def title(self):
|
||||
return str(self).capitalize()
|
||||
|
||||
def _format_description(self, params):
|
||||
if self.description is None:
|
||||
defaults = self._pick_defaults(self.defaults_name)
|
||||
description = defaults.params.get("description")
|
||||
else:
|
||||
if type(self.description) is LocString:
|
||||
description = str(self.description)
|
||||
else:
|
||||
description = self.description
|
||||
if description is None and self._keep_descriptions:
|
||||
return {}
|
||||
expanded_desc = self._expander.expand(description, params)
|
||||
return {"description": (expanded_desc or "") + MAGIC_MANAGE_STRING}
|
||||
@property
|
||||
def contents(self):
|
||||
contents = self._contents.copy()
|
||||
if self.description is not None:
|
||||
contents["description"] = self.description
|
||||
return contents
|
||||
|
||||
def _expand_contents(self, contents, params):
|
||||
expanded_contents = self._expander.expand(contents, params)
|
||||
description = expanded_contents.get("description")
|
||||
if description is not None or not self._keep_descriptions:
|
||||
amended_description = (description or "") + MAGIC_MANAGE_STRING
|
||||
expanded_contents["description"] = amended_description
|
||||
return expanded_contents
|
||||
|
||||
def _pick_defaults(self, name, merge_global=True):
|
||||
try:
|
||||
@ -102,17 +103,14 @@ class NonTemplateRootMixin:
|
||||
def top_level_generate_items(self):
|
||||
try:
|
||||
defaults = self._pick_defaults(self.defaults_name, merge_global=False)
|
||||
description = self._format_description(params={})
|
||||
raw_data = self._as_dict()
|
||||
contents = self._expander.expand(raw_data, self.params)
|
||||
data = LocDict.merge(
|
||||
contents = LocDict.merge(
|
||||
defaults.contents,
|
||||
contents,
|
||||
description,
|
||||
self.contents,
|
||||
pos=self.pos,
|
||||
)
|
||||
expanded_contents = self._expand_contents(contents, self.params)
|
||||
context = [Context(f"In {self}", self.pos)]
|
||||
yield JobViewData(data, context)
|
||||
yield JobViewData(expanded_contents, context)
|
||||
except JenkinsJobsException as x:
|
||||
raise x.with_context(f"In {self}", pos=self.pos)
|
||||
|
||||
@ -136,7 +134,8 @@ class TemplateRootMixin:
|
||||
item_params["id"] = self._id
|
||||
contents = LocDict.merge(
|
||||
defaults.contents,
|
||||
self._as_dict(),
|
||||
self.contents,
|
||||
pos=self.pos,
|
||||
)
|
||||
axes = list(enum_str_format_required_params(self.name, self.name.pos))
|
||||
axes_defaults = dict(enum_str_format_param_defaults(self.name))
|
||||
@ -152,15 +151,9 @@ class TemplateRootMixin:
|
||||
key_pos=expanded_params.key_pos.get("exclude"),
|
||||
):
|
||||
continue
|
||||
description = self._format_description(expanded_params)
|
||||
expanded_contents = self._expander.expand(contents, expanded_params)
|
||||
data = LocDict.merge(
|
||||
expanded_contents,
|
||||
description,
|
||||
pos=self.pos,
|
||||
)
|
||||
expanded_contents = self._expand_contents(contents, expanded_params)
|
||||
context = [Context(f"In {self}", self.pos)]
|
||||
yield JobViewData(data, context)
|
||||
yield JobViewData(expanded_contents, context)
|
||||
except JenkinsJobsException as x:
|
||||
raise x.with_context(f"In {self}", pos=self.pos)
|
||||
|
||||
|
@ -46,13 +46,14 @@ class ViewBase(RootBase):
|
||||
view_type,
|
||||
)
|
||||
|
||||
def _as_dict(self):
|
||||
@property
|
||||
def contents(self):
|
||||
return LocDict.merge(
|
||||
{
|
||||
"name": self.name,
|
||||
"view-type": self.view_type,
|
||||
},
|
||||
self.contents,
|
||||
super().contents,
|
||||
)
|
||||
|
||||
|
||||
|
@ -118,18 +118,24 @@ def expected_error(scenario):
|
||||
return None
|
||||
|
||||
|
||||
def check_folder(scenario, jjb_config, input):
|
||||
if "name" not in input:
|
||||
return
|
||||
if "folder" in input:
|
||||
full_name = input["folder"] + "/" + input["name"]
|
||||
else:
|
||||
full_name = input["name"]
|
||||
*dirs, name = full_name.split("/")
|
||||
input_dir = scenario.in_path.parent
|
||||
expected_out_dirs = [input_dir.joinpath(*dirs)]
|
||||
actual_out_dirs = [path.parent for path in scenario.out_paths]
|
||||
assert expected_out_dirs == actual_out_dirs
|
||||
# Tests use output files directories as expected folder name.
|
||||
def check_folders(scenario, job_xml_list):
|
||||
root_dir = scenario.in_path.parent
|
||||
|
||||
def name_parent(name):
|
||||
*dirs, name = name.split("/")
|
||||
return "/".join(dirs)
|
||||
|
||||
def path_parent(path):
|
||||
dir = str(path.relative_to(root_dir).parent)
|
||||
if dir == ".":
|
||||
return ""
|
||||
else:
|
||||
return dir
|
||||
|
||||
actual_dirs = list(sorted(set(name_parent(jx.name) for jx in job_xml_list)))
|
||||
expected_dirs = list(sorted(path_parent(path) for path in scenario.out_paths))
|
||||
assert expected_dirs == actual_dirs
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -142,7 +148,6 @@ def check_generator(scenario, input, expected_output, jjb_config, registry, proj
|
||||
|
||||
generator = Generator(registry)
|
||||
generator.gen_xml(xml, input)
|
||||
check_folder(scenario, jjb_config, input)
|
||||
pretty_xml = XmlJob(xml, "fixturejob").output().decode()
|
||||
assert expected_output == pretty_xml
|
||||
|
||||
@ -188,6 +193,8 @@ def check_job(scenario, expected_output, jjb_config, registry):
|
||||
)
|
||||
assert stripped_expected_output == pretty_xml
|
||||
|
||||
check_folders(scenario, job_xml_list)
|
||||
|
||||
return check
|
||||
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
name: test-folder
|
||||
project-type: freestyle
|
||||
folder: folders
|
@ -1,3 +0,0 @@
|
||||
name: test-folder
|
||||
project-type: freestyle
|
||||
folder: folders/test-nested-folder
|
@ -0,0 +1,19 @@
|
||||
# 'folders' attribute from defaults should be used (combined with job name) for job templates.
|
||||
|
||||
- defaults:
|
||||
name: team1
|
||||
folder: team1-jobs
|
||||
|
||||
- job:
|
||||
name: ruby-jobs/sample-job
|
||||
defaults: team1
|
||||
builders:
|
||||
- shell: |
|
||||
rvm use --create ruby-2.3.0@rspec
|
||||
bundle install
|
||||
bundle exec rspec
|
||||
|
||||
- project:
|
||||
name: sample-project
|
||||
jobs:
|
||||
- ruby-jobs/sample-job
|
@ -1,3 +1,5 @@
|
||||
# 'folders' attribute from defaults should be used (combined with job name) for jobs.
|
||||
|
||||
- defaults:
|
||||
name: team1
|
||||
folder: team1-jobs
|
@ -0,0 +1,9 @@
|
||||
- job-template:
|
||||
name: sample-job
|
||||
project-type: freestyle
|
||||
folder: folders/test-nested-folder
|
||||
|
||||
- project:
|
||||
name: sample-project
|
||||
jobs:
|
||||
- sample-job
|
4
tests/yamlparser/job_fixtures/folders-nested-job.yaml
Normal file
4
tests/yamlparser/job_fixtures/folders-nested-job.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
- job:
|
||||
name: sample-job
|
||||
project-type: freestyle
|
||||
folder: folders/test-nested-folder
|
@ -1,9 +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>
|
@ -1,9 +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>
|
@ -0,0 +1,22 @@
|
||||
<?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>
|
||||
<hudson.tasks.Shell>
|
||||
<command>rvm use --create ruby-2.3.0@rspec
|
||||
bundle install
|
||||
bundle exec rspec
|
||||
</command>
|
||||
</hudson.tasks.Shell>
|
||||
</builders>
|
||||
<publishers/>
|
||||
<buildWrappers/>
|
||||
</project>
|
Loading…
Reference in New Issue
Block a user