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:
Vsevolod Fedorov 2023-11-24 12:33:48 +03:00
parent 36ea222763
commit c1ac0e03d6
16 changed files with 134 additions and 65 deletions

View File

@ -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:

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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,
)

View File

@ -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

View File

@ -1,3 +0,0 @@
name: test-folder
project-type: freestyle
folder: folders

View File

@ -1,3 +0,0 @@
name: test-folder
project-type: freestyle
folder: folders/test-nested-folder

View File

@ -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

View File

@ -1,3 +1,5 @@
# 'folders' attribute from defaults should be used (combined with job name) for jobs.
- defaults:
name: team1
folder: team1-jobs

View File

@ -0,0 +1,9 @@
- job-template:
name: sample-job
project-type: freestyle
folder: folders/test-nested-folder
- project:
name: sample-project
jobs:
- sample-job

View File

@ -0,0 +1,4 @@
- job:
name: sample-job
project-type: freestyle
folder: folders/test-nested-folder

View File

@ -1,9 +1,15 @@
<?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.scm.NullSCM"/>
<builders/>
<publishers/>
<buildWrappers/>
</project>

View File

@ -1,9 +1,15 @@
<?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.scm.NullSCM"/>
<builders/>
<publishers/>
<buildWrappers/>
</project>

View File

@ -0,0 +1,22 @@
<?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.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>