diff --git a/doc/source/definition.rst b/doc/source/definition.rst
index a45692f70..828a4950d 100644
--- a/doc/source/definition.rst
+++ b/doc/source/definition.rst
@@ -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:
diff --git a/jenkins_jobs/defaults.py b/jenkins_jobs/defaults.py
index d771a5ba2..33ba1a482 100644
--- a/jenkins_jobs/defaults.py
+++ b/jenkins_jobs/defaults.py
@@ -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
diff --git a/jenkins_jobs/job.py b/jenkins_jobs/job.py
index 7e5bfb3fd..56dd0f434 100644
--- a/jenkins_jobs/job.py
+++ b/jenkins_jobs/job.py
@@ -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):
diff --git a/jenkins_jobs/root_base.py b/jenkins_jobs/root_base.py
index b6e6c58f9..4ae8593b9 100644
--- a/jenkins_jobs/root_base.py
+++ b/jenkins_jobs/root_base.py
@@ -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)
diff --git a/jenkins_jobs/view.py b/jenkins_jobs/view.py
index 12a138cdf..4ba9303aa 100644
--- a/jenkins_jobs/view.py
+++ b/jenkins_jobs/view.py
@@ -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,
)
diff --git a/tests/conftest.py b/tests/conftest.py
index b765afd3b..a2b14370d 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -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
diff --git a/tests/general/fixtures/folders001.yaml b/tests/general/fixtures/folders001.yaml
deleted file mode 100644
index 948ccc6d0..000000000
--- a/tests/general/fixtures/folders001.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-name: test-folder
-project-type: freestyle
-folder: folders
diff --git a/tests/general/fixtures/folders002.yaml b/tests/general/fixtures/folders002.yaml
deleted file mode 100644
index b5626607b..000000000
--- a/tests/general/fixtures/folders002.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-name: test-folder
-project-type: freestyle
-folder: folders/test-nested-folder
diff --git a/tests/yamlparser/job_fixtures/folders-defaults-for-job-template.yaml b/tests/yamlparser/job_fixtures/folders-defaults-for-job-template.yaml
new file mode 100644
index 000000000..9c53bb2e6
--- /dev/null
+++ b/tests/yamlparser/job_fixtures/folders-defaults-for-job-template.yaml
@@ -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
diff --git a/tests/yamlparser/job_fixtures/folders-attribute.yaml b/tests/yamlparser/job_fixtures/folders-defaults-for-job.yaml
similarity index 72%
rename from tests/yamlparser/job_fixtures/folders-attribute.yaml
rename to tests/yamlparser/job_fixtures/folders-defaults-for-job.yaml
index 7346fa2f9..dd8d0f3a6 100644
--- a/tests/yamlparser/job_fixtures/folders-attribute.yaml
+++ b/tests/yamlparser/job_fixtures/folders-defaults-for-job.yaml
@@ -1,3 +1,5 @@
+# 'folders' attribute from defaults should be used (combined with job name) for jobs.
+
- defaults:
name: team1
folder: team1-jobs
diff --git a/tests/yamlparser/job_fixtures/folders-nested-job-template.yaml b/tests/yamlparser/job_fixtures/folders-nested-job-template.yaml
new file mode 100644
index 000000000..b17c744b2
--- /dev/null
+++ b/tests/yamlparser/job_fixtures/folders-nested-job-template.yaml
@@ -0,0 +1,9 @@
+- job-template:
+ name: sample-job
+ project-type: freestyle
+ folder: folders/test-nested-folder
+
+- project:
+ name: sample-project
+ jobs:
+ - sample-job
diff --git a/tests/yamlparser/job_fixtures/folders-nested-job.yaml b/tests/yamlparser/job_fixtures/folders-nested-job.yaml
new file mode 100644
index 000000000..3e7da5739
--- /dev/null
+++ b/tests/yamlparser/job_fixtures/folders-nested-job.yaml
@@ -0,0 +1,4 @@
+- job:
+ name: sample-job
+ project-type: freestyle
+ folder: folders/test-nested-folder
diff --git a/tests/general/fixtures/folders/folders001.xml b/tests/yamlparser/job_fixtures/folders/test-nested-folder/folders-nested-job-template.xml
similarity index 65%
rename from tests/general/fixtures/folders/folders001.xml
rename to tests/yamlparser/job_fixtures/folders/test-nested-folder/folders-nested-job-template.xml
index 1505db519..0570e10a5 100644
--- a/tests/general/fixtures/folders/folders001.xml
+++ b/tests/yamlparser/job_fixtures/folders/test-nested-folder/folders-nested-job-template.xml
@@ -1,9 +1,15 @@
+ <!-- Managed by Jenkins Job Builder -->
false
false
false
false
true
+
+
+
+
+
diff --git a/tests/general/fixtures/folders/test-nested-folder/folders002.xml b/tests/yamlparser/job_fixtures/folders/test-nested-folder/folders-nested-job.xml
similarity index 65%
rename from tests/general/fixtures/folders/test-nested-folder/folders002.xml
rename to tests/yamlparser/job_fixtures/folders/test-nested-folder/folders-nested-job.xml
index 1505db519..0570e10a5 100644
--- a/tests/general/fixtures/folders/test-nested-folder/folders002.xml
+++ b/tests/yamlparser/job_fixtures/folders/test-nested-folder/folders-nested-job.xml
@@ -1,9 +1,15 @@
+ <!-- Managed by Jenkins Job Builder -->
false
false
false
false
true
+
+
+
+
+
diff --git a/tests/yamlparser/job_fixtures/team1-jobs/ruby-jobs/folders-attribute.xml b/tests/yamlparser/job_fixtures/team1-jobs/ruby-jobs/folders-defaults-for-job-template.xml
similarity index 100%
rename from tests/yamlparser/job_fixtures/team1-jobs/ruby-jobs/folders-attribute.xml
rename to tests/yamlparser/job_fixtures/team1-jobs/ruby-jobs/folders-defaults-for-job-template.xml
diff --git a/tests/yamlparser/job_fixtures/team1-jobs/ruby-jobs/folders-defaults-for-job.xml b/tests/yamlparser/job_fixtures/team1-jobs/ruby-jobs/folders-defaults-for-job.xml
new file mode 100644
index 000000000..2c57eb750
--- /dev/null
+++ b/tests/yamlparser/job_fixtures/team1-jobs/ruby-jobs/folders-defaults-for-job.xml
@@ -0,0 +1,22 @@
+
+
+
+ <!-- Managed by Jenkins Job Builder -->
+ false
+ false
+ false
+ false
+ true
+
+
+
+
+ rvm use --create ruby-2.3.0@rspec
+bundle install
+bundle exec rspec
+
+
+
+
+
+