From 0f9dd4e8052753c472770ae5354032f36112d74d Mon Sep 17 00:00:00 2001 From: Jiri Tyr Date: Mon, 27 Jan 2020 17:31:10 +0000 Subject: Adding view for the Delivery Pipeline Plugin Change-Id: I8a9a71267562734b078b7260c79d299db7fb4e2b Signed-off-by: Jiri Tyr --- doc/source/view_delivery_pipeline.rst | 7 + jenkins_jobs/modules/view_delivery_pipeline.py | 217 +++++++++++++++++++++ setup.cfg | 1 + tests/base.py | 3 + .../views/fixtures/view_delivery_pipeline-full.xml | 44 +++++ .../fixtures/view_delivery_pipeline-full.yaml | 16 ++ .../fixtures/view_delivery_pipeline-minimal.xml | 38 ++++ .../fixtures/view_delivery_pipeline-minimal.yaml | 6 + tests/views/test_views.py | 7 + 9 files changed, 339 insertions(+) create mode 100644 doc/source/view_delivery_pipeline.rst create mode 100644 jenkins_jobs/modules/view_delivery_pipeline.py create mode 100644 tests/views/fixtures/view_delivery_pipeline-full.xml create mode 100644 tests/views/fixtures/view_delivery_pipeline-full.yaml create mode 100644 tests/views/fixtures/view_delivery_pipeline-minimal.xml create mode 100644 tests/views/fixtures/view_delivery_pipeline-minimal.yaml diff --git a/doc/source/view_delivery_pipeline.rst b/doc/source/view_delivery_pipeline.rst new file mode 100644 index 00000000..76648fb4 --- /dev/null +++ b/doc/source/view_delivery_pipeline.rst @@ -0,0 +1,7 @@ +.. _view_delivery_pipeline: + +Delivery Pipeline View +====================== + +.. automodule:: view_delivery_pipeline + :members: diff --git a/jenkins_jobs/modules/view_delivery_pipeline.py b/jenkins_jobs/modules/view_delivery_pipeline.py new file mode 100644 index 00000000..fbabe598 --- /dev/null +++ b/jenkins_jobs/modules/view_delivery_pipeline.py @@ -0,0 +1,217 @@ +# Copyright 2020 Openstack Foundation + +# 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. + +""" +The view delivery pipeline module handles creation of Delivery Pipeline views. +To create a delivery pipeline view specify ``delivery_pipeline`` in the +``view-type`` attribute to the :ref:`view_delivery_pipeline` definition. +Requires the Jenkins :jenkins-plugins:`Delivery Pipeline Plugin +`. + +:View Parameters: + * **name** (`str`): The name of the view. + * **view-type** (`str`): The type of view. + * **description** (`str`): A description of the view. (optional) + * **filter-executors** (`bool`): Show only executors that can + execute the included views. (default false) + * **filter-queue** (`bool`): Show only included jobs in builder + queue. (default false) + * **components** (`list`): + * **name** (`str`): Name of the pipeline, usually the name of the + component or product. + * **initial-job** (`str`): First job in the pipeline. + * **final-job** (`str`): Final job to display in the pipeline view + regardless of its downstream jobs. (default '') + * **show-upstream** (`bool`): Whether to show upstream. (default false) + * **regexps** (`list`): + * **regexp** (`str`): Regular expression to find initial jobs. + * **show-upstream** (`bool`): Whether to show upstream. (default false) + * **aggregated-changes-grouping-pattern** (`str`): Group changelog by regex + pattern. (default '') + * **allow-abort** (`bool`): Allow cancelling a running job from the + delivery pipeline view. (default false) + * **allow-manual-triggers** (`bool`): Displays a button in the pipeline + view if a task is manual (Build other projects (manual step)) from Build + Pipeline Plugin. (default false) + * **allow-pipeline-start** (`bool`): Allow starting a new pipeline run from + the delivery pipeline view. (default false) + * **allow-rebuild** (`bool`): Allow rerunning a task from the delivery + pipeline view. (default false) + * **link-relative** (`bool`): Use relative links for jobs in this pipeline + view to allow for easier navigation. (default false) + * **link-to-console-log** (`bool`): Changes behaviour of task link in + delivery pipeline view to go directly to the console log. (default false) + * **max-number-of-visible-pipelines** (`int`): Limits the number of + pipelines shown in the view, regardless of how many pipelines are + configured. A negative value will not enforce a limit. + * **no-of-columns** (`int`): Number of columns used for showing pipelines. + Possible values are 1 (default), 2 and 3. + * **no-of-pipelines** (`int`): Number of pipelines instances shown for each + pipeline. Possible values are numbers from 1 to 50 (default 3). + * **paging-enabled** (`bool`): Enable pagination in normal view, to allow + navigation to older pipeline runs which are not displayed on the first + page. Not available in full screen view. (default false) + * **show-absolute-date-time** (`bool`): Show dates and times as absolute + values instead of as relative to the current time. (default false) + * **show-aggregated-changes** (`bool`): Show an aggregated changelog + between different stages. (default false) + * **show-aggregated-pipeline** (`bool`): Show an aggregated view where each + stage shows the latest version being executed. (default false) + * **show-avatars** (`bool`): Show avatars pictures instead of names of the + people involved in a pipeline instance. (default false) + * **show-changes** (`bool`): Show SCM change log for the first job in the + pipeline. (default false) + * **show-description** (`bool`): Show a build description connected to a + specific pipeline task. (default false) + * **show-promotions** (`bool`): Show promotions from Promoted Builds + Plugin. (default false) + * **show-static-analysis-results** (`bool`): Show different analysis + results from Analysis Collector Plugin. (default false) + * **show-test-results** (`bool`): Show test results as pass/failed/skipped. + (default false) + * **show-total-build-time** (`bool`): Show total build time for a pipeline + run. (default false) + * **sorting** (`str`): How to sort the pipelines in the current view. Only + applicable when multiple pipelines are configured in the same view. + Possible values are 'none' (default), 'title' (sort by title), + 'failed_last_activity' (sort by failed pipelines, then by last activity), + 'last_activity' (sort by last activity). + * **update-interval** (`int`): How often the pipeline view will be updated. + To be specified in seconds. (default 2) + +Minimal Example: + + .. literalinclude:: + /../../tests/views/fixtures/view_delivery_pipeline-minimal.yaml + +Full Example: + + .. literalinclude:: + /../../tests/views/fixtures/view_delivery_pipeline-full.yaml +""" + +import xml.etree.ElementTree as XML +import jenkins_jobs.modules.base +import jenkins_jobs.modules.helpers as helpers + + +class DeliveryPipeline(jenkins_jobs.modules.base.Base): + def root_xml(self, data): + root = XML.Element( + "se.diabol.jenkins.pipeline.DeliveryPipelineView", + {"plugin": "delivery-pipeline-plugin"}, + ) + + # Optional + mapping_optional = [ + ("description", "description", None), + ("filter-executors", "filterExecutors", False), + ("filter-queue", "filterQueue", False), + ] + helpers.convert_mapping_to_xml( + root, data, mapping_optional, fail_required=False + ) + + # Required - simple + mapping = [ + ( + "aggregated-changes-grouping-pattern", + "aggregatedChangesGroupingPattern", + "", + ), + ("allow-abort", "allowAbort", False), + ("allow-manual-triggers", "allowManualTriggers", False), + ("allow-pipeline-start", "allowPipelineStart", False), + ("allow-rebuild", "allowRebuild", False), + ("link-relative", "linkRelative", False), + ("link-to-console-log", "linkToConsoleLog", False), + ("max-number-of-visible-pipelines", "maxNumberOfVisiblePipelines", -1), + ("name", "name", None), + ("no-of-columns", "noOfColumns", 1, [1, 2, 3]), + ("no-of-pipelines", "noOfPipelines", 3, list(range(51))), + ("paging-enabled", "pagingEnabled", False), + ("show-absolute-date-time", "showAbsoluteDateTime", False), + ("show-aggregated-changes", "showAggregatedChanges", False), + ("show-aggregated-pipeline", "showAggregatedPipeline", False), + ("show-avatars", "showAvatars", False), + ("show-changes", "showChanges", False), + ("show-description", "showDescription", False), + ("show-promotions", "showPromotions", False), + ("show-static-analysis-results", "showStaticAnalysisResults", False), + ("show-test-results", "showTestResults", False), + ("show-total-build-time", "showTotalBuildTime", False), + ("update-interval", "updateInterval", 2), + ] + helpers.convert_mapping_to_xml(root, data, mapping, fail_required=True) + + # Required - complex + sorting_val = data.get("sorting", "none") + sorting_map = { + "none": "None", + "title": ("se.diabol.jenkins.pipeline.sort.NameComparator"), + "failed_last_activity": ( + "se.diabol.jenkins.pipeline.sort.FailedJobComparator" + ), + "last_activity": ( + "se.diabol.jenkins.pipeline.sort.LatestActivityComparator" + ), + } + sorting = XML.SubElement(root, "sorting") + + if sorting_val in sorting_map: + sorting.text = sorting_map[sorting_val] + else: + sorting.text = sorting_map["none"] + + components = data.get("components", []) + + if len(components): + component_specs = XML.SubElement(root, "componentSpecs") + + for c in components: + component_spec = XML.SubElement( + component_specs, + "se.diabol.jenkins.pipeline.DeliveryPipelineView_-ComponentSpec", + ) + + name = XML.SubElement(component_spec, "name") + name.text = c.get("name", "") + + first_job = XML.SubElement(component_spec, "firstJob") + first_job.text = c.get("initial-job", "") + + last_job = XML.SubElement(component_spec, "lastJob") + last_job.text = c.get("final-job", "") + + show_upstream = XML.SubElement(component_spec, "showUpstream") + show_upstream.text = c.get("show-upstream", "false") + + regexps = data.get("regexps", []) + + if len(regexps): + regexp_first_jobs = XML.SubElement(root, "regexpFirstJobs") + + for r in regexps: + regexp_first_job = XML.SubElement( + regexp_first_jobs, + "se.diabol.jenkins.pipeline.DeliveryPipelineView_-RegExpSpec", + ) + + regexp = XML.SubElement(regexp_first_job, "regexp") + regexp.text = r.get("regexp", "") + + show_upstream = XML.SubElement(regexp_first_job, "showUpstream") + show_upstream.text = r.get("show-upstream", "false") + + return root diff --git a/setup.cfg b/setup.cfg index 5a27c846..3e6a8f21 100644 --- a/setup.cfg +++ b/setup.cfg @@ -63,6 +63,7 @@ jenkins_jobs.projects = workflow=jenkins_jobs.modules.project_workflow:Workflow jenkins_jobs.views = all=jenkins_jobs.modules.view_all:All + delivery_pipeline=jenkins_jobs.modules.view_delivery_pipeline:DeliveryPipeline list=jenkins_jobs.modules.view_list:List nested=jenkins_jobs.modules.view_nested:Nested pipeline=jenkins_jobs.modules.view_pipeline:Pipeline diff --git a/tests/base.py b/tests/base.py index 910133f4..262e183f 100644 --- a/tests/base.py +++ b/tests/base.py @@ -46,6 +46,7 @@ from jenkins_jobs.modules import project_maven from jenkins_jobs.modules import project_multibranch from jenkins_jobs.modules import project_multijob from jenkins_jobs.modules import view_all +from jenkins_jobs.modules import view_delivery_pipeline from jenkins_jobs.modules import view_list from jenkins_jobs.modules import view_nested from jenkins_jobs.modules import view_pipeline @@ -237,6 +238,8 @@ class BaseScenariosTestCase(testscenarios.TestWithScenarios, BaseTestCase): if "view-type" in yaml_content: if yaml_content["view-type"] == "all": project = view_all.All(registry) + elif yaml_content["view-type"] == "delivery_pipeline": + project = view_delivery_pipeline.DeliveryPipeline(registry) elif yaml_content["view-type"] == "list": project = view_list.List(registry) elif yaml_content["view-type"] == "nested": diff --git a/tests/views/fixtures/view_delivery_pipeline-full.xml b/tests/views/fixtures/view_delivery_pipeline-full.xml new file mode 100644 index 00000000..031d1e61 --- /dev/null +++ b/tests/views/fixtures/view_delivery_pipeline-full.xml @@ -0,0 +1,44 @@ + + + Test jobs created by JJB. + false + false + + true + true + true + true + false + true + -1 + Test pipeline + 1 + 1 + true + false + false + false + false + false + false + false + false + false + true + 2 + None + + + Test + Test-A + + false + + + + + ^Test-A + false + + + diff --git a/tests/views/fixtures/view_delivery_pipeline-full.yaml b/tests/views/fixtures/view_delivery_pipeline-full.yaml new file mode 100644 index 00000000..1e404681 --- /dev/null +++ b/tests/views/fixtures/view_delivery_pipeline-full.yaml @@ -0,0 +1,16 @@ +name: Test pipeline +description: Test jobs created by JJB. +view-type: delivery_pipeline +components: + - name: Test + initial-job: Test-A +regexps: + - regexp: ^Test-A +no-of-pipelines: 1 +allow-manual-triggers: yes +show-total-build-time: yes +allow-rebuild: yes +allow-pipeline-start: yes +allow-abort: yes +paging-enabled: yes +link-to-console-log: yes diff --git a/tests/views/fixtures/view_delivery_pipeline-minimal.xml b/tests/views/fixtures/view_delivery_pipeline-minimal.xml new file mode 100644 index 00000000..be342680 --- /dev/null +++ b/tests/views/fixtures/view_delivery_pipeline-minimal.xml @@ -0,0 +1,38 @@ + + + Test jobs created by JJB. + false + false + + false + false + false + false + false + false + -1 + Test pipeline + 1 + 3 + false + false + false + false + false + false + false + false + false + false + false + 2 + None + + + Test + Test-A + + false + + + diff --git a/tests/views/fixtures/view_delivery_pipeline-minimal.yaml b/tests/views/fixtures/view_delivery_pipeline-minimal.yaml new file mode 100644 index 00000000..3fd01318 --- /dev/null +++ b/tests/views/fixtures/view_delivery_pipeline-minimal.yaml @@ -0,0 +1,6 @@ +name: Test pipeline +description: Test jobs created by JJB. +view-type: delivery_pipeline +components: + - name: Test + initial-job: Test-A diff --git a/tests/views/test_views.py b/tests/views/test_views.py index fb506310..06d153c5 100644 --- a/tests/views/test_views.py +++ b/tests/views/test_views.py @@ -14,6 +14,7 @@ import os from jenkins_jobs.modules import view_all +from jenkins_jobs.modules import view_delivery_pipeline from jenkins_jobs.modules import view_list from jenkins_jobs.modules import view_nested from jenkins_jobs.modules import view_pipeline @@ -27,6 +28,12 @@ class TestCaseModuleViewAll(base.BaseScenariosTestCase): klass = view_all.All +class TestCaseModuleViewDeliveryPipeline(base.BaseScenariosTestCase): + fixtures_path = os.path.join(os.path.dirname(__file__), "fixtures") + scenarios = base.get_scenarios(fixtures_path) + klass = view_delivery_pipeline.DeliveryPipeline + + class TestCaseModuleViewList(base.BaseScenariosTestCase): fixtures_path = os.path.join(os.path.dirname(__file__), "fixtures") scenarios = base.get_scenarios(fixtures_path) -- cgit