Browse Source

Merge "Adds named branches to property strategy support"

tags/2.10.0
Zuul 4 months ago
parent
commit
51e2a99d58

+ 1
- 1
doc/source/conf.py View File

@@ -30,7 +30,7 @@ sys.path.insert(0, os.path.abspath('../../jenkins_jobs/modules'))
30 30
 #  extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
31 31
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage',
32 32
               'jenkins_jobs.sphinx.yaml', 'sphinxcontrib.programoutput',
33
-              'sphinx.ext.extlinks']
33
+              'sphinx.ext.extlinks', 'sphinx.ext.doctest']
34 34
 
35 35
 # Add any paths that contain templates here, relative to this directory.
36 36
 templates_path = ['_templates']

+ 153
- 32
jenkins_jobs/modules/project_multibranch.py View File

@@ -76,6 +76,7 @@ import six
76 76
 
77 77
 from jenkins_jobs.modules.scm import git_extensions
78 78
 from jenkins_jobs.errors import InvalidAttributeError
79
+from jenkins_jobs.errors import JenkinsJobsException
79 80
 
80 81
 logger = logging.getLogger(str(__name__))
81 82
 
@@ -1146,7 +1147,8 @@ def property_strategies(xml_parent, data):
1146 1147
 
1147 1148
     Requires the :jenkins-wiki:`Branch API Plugin <Branch+API+Plugin>`.
1148 1149
 
1149
-    :arg dict property-strategies: Definition of property strategies.
1150
+    :arg dict property-strategies: Definition of property strategies.  Either
1151
+        `named-branches` or `all-branches` may be specified, but not both.
1150 1152
 
1151 1153
         * **all-branches** (list): A list of property strategy definitions
1152 1154
             for use with all branches.
@@ -1158,43 +1160,162 @@ def property_strategies(xml_parent, data):
1158 1160
                 performance-optimized, survivable-nonatomic, or
1159 1161
                 max-survivability (optional) Requires the :jenkins-wiki:
1160 1162
                 `Pipeline Multibranch Plugin <Pipeline+Multibranch+Plugin>`
1163
+
1164
+        * **named-branches** (dict): Named branches get different properties.
1165
+            Comprised of a list of defaults and a list of property strategy
1166
+            exceptions for use with specific branches.
1167
+
1168
+            * **defaults** (list): A list of property strategy definitions
1169
+                to be applied by default to all branches, unless overridden
1170
+                by an entry in `exceptions`
1171
+
1172
+                * **suppress-scm-triggering** (bool): Suppresses automatic SCM
1173
+                    triggering (optional)
1174
+                * **pipeline-branch-durability-override** (str): Set a custom
1175
+                    branch speed/durability level. Valid values:
1176
+                    performance-optimized, survivable-nonatomic, or
1177
+                    max-survivability (optional) Requires the :jenkins-wiki:
1178
+                    `Pipeline Multibranch Plugin <Pipeline+Multibranch+Plugin>`
1179
+
1180
+            * **exceptions** (list): A list of branch names and the property
1181
+                strategies to be used on that branch, instead of any listed
1182
+                in `defaults`.
1183
+
1184
+                * **exception** (dict): Defines exception
1185
+                    * **branch-name** (str): Name of the branch to which these
1186
+                        properties will be applied.
1187
+                    * **properties** (list): A list of properties to apply to
1188
+                        this branch.
1189
+
1190
+                        * **suppress-scm-triggering** (bool): Suppresses
1191
+                            automatic SCM triggering (optional)
1192
+                        * **pipeline-branch-durability-override** (str): Set a
1193
+                            custom branch speed/durability level. Valid values:
1194
+                            performance-optimized, survivable-nonatomic, or
1195
+                            max-survivability (optional) Requires the
1196
+                            :jenkins-wiki:`Pipeline Multibranch Plugin
1197
+                            <Pipeline+Multibranch+Plugin>`
1161 1198
     """
1162 1199
 
1200
+    valid_prop_strats = [
1201
+        'all-branches',
1202
+        'named-branches'
1203
+    ]
1204
+
1205
+    basic_property_strategies = 'jenkins.branch'
1206
+
1207
+    prop_strats = data.get('property-strategies', None)
1208
+
1209
+    if prop_strats:
1210
+
1211
+        for prop_strat in prop_strats:
1212
+            if prop_strat not in valid_prop_strats:
1213
+                raise InvalidAttributeError('property-strategies',
1214
+                                            prop_strat,
1215
+                                            valid_prop_strats)
1216
+        if len(prop_strats) > 1:
1217
+            raise JenkinsJobsException(
1218
+                'Only one property strategy may be specified')
1219
+
1220
+        all_branches = prop_strats.get('all-branches', None)
1221
+        named_branches = prop_strats.get('named-branches', None)
1222
+
1223
+        if all_branches:
1224
+
1225
+            strat_elem = XML.SubElement(xml_parent, 'strategy', {
1226
+                'class': ''.join([basic_property_strategies,
1227
+                                  '.DefaultBranchPropertyStrategy'])})
1228
+            props_elem = XML.SubElement(strat_elem, 'properties', {
1229
+                'class': 'java.util.Arrays$ArrayList'})
1230
+            props_elem = XML.SubElement(props_elem, 'a', {
1231
+                'class': ''.join([
1232
+                    basic_property_strategies, '.BranchProperty-array'])})
1233
+
1234
+            apply_property_strategies(props_elem, all_branches)
1235
+
1236
+        elif named_branches:
1237
+
1238
+            strat_elem = XML.SubElement(xml_parent, 'strategy', {
1239
+                'class': ''.join([basic_property_strategies,
1240
+                                  '.NamedExceptionsBranchPropertyStrategy'])})
1241
+
1242
+            nbs_defaults = named_branches.get('defaults', None)
1243
+            if nbs_defaults:
1244
+
1245
+                props_elem = XML.SubElement(strat_elem, 'defaultProperties', {
1246
+                    'class': 'java.util.Arrays$ArrayList'})
1247
+                props_elem = XML.SubElement(props_elem, 'a', {
1248
+                    'class': ''.join([
1249
+                        basic_property_strategies, '.BranchProperty-array'])})
1250
+
1251
+                apply_property_strategies(props_elem, nbs_defaults)
1252
+
1253
+            nbs_exceptions = named_branches.get('exceptions', None)
1254
+            if nbs_exceptions:
1255
+
1256
+                props_elem = XML.SubElement(strat_elem, 'namedExceptions', {
1257
+                    'class': 'java.util.Arrays$ArrayList'})
1258
+                props_elem = XML.SubElement(props_elem, 'a', {
1259
+                    'class': ''.join([
1260
+                        basic_property_strategies,
1261
+                        '.NamedExceptionsBranchPropertyStrategy$Named-array'
1262
+                    ])})
1263
+
1264
+                for named_exception in nbs_exceptions:
1265
+                    named_exception = named_exception.get('exception', None)
1266
+                    if not named_exception:
1267
+                        continue
1268
+
1269
+                    exc_elem = XML.SubElement(props_elem, ''.join([
1270
+                        basic_property_strategies,
1271
+                        '.NamedExceptionsBranchPropertyStrategy_-Named']))
1272
+
1273
+                    ne_branch_name = named_exception.get('branch-name', None)
1274
+                    if ne_branch_name is not None:
1275
+                        XML.SubElement(exc_elem, 'name').text = ne_branch_name
1276
+
1277
+                    ne_properties = named_exception.get('properties', None)
1278
+                    if ne_properties:
1279
+                        exc_elem = XML.SubElement(exc_elem, 'props', {
1280
+                            'class': 'java.util.Arrays$ArrayList'})
1281
+                        exc_elem = XML.SubElement(exc_elem, 'a', {
1282
+                            'class': ''.join([
1283
+                                basic_property_strategies,
1284
+                                '.BranchProperty-array'])})
1285
+                        apply_property_strategies(exc_elem, ne_properties)
1286
+
1287
+
1288
+def apply_property_strategies(props_elem, props_list):
1289
+    # there are 3 locations at which property strategies can be defined:
1290
+    # globally (all-branches), defaults (named-branches), exceptions
1291
+    # (also named-branches)
1292
+
1293
+    basic_property_strategies = 'jenkins.branch'
1294
+    workflow_multibranch = 'org.jenkinsci.plugins.workflow.multibranch'
1163 1295
     # Valid options for the pipeline branch durability override.
1164 1296
     pbdo_map = collections.OrderedDict([
1165 1297
         ("max-survivability", "MAX_SURVIVABILITY"),
1166 1298
         ("performance-optimized", "PERFORMANCE_OPTIMIZED"),
1167 1299
         ("survivable-nonatomic", "SURVIVABLE_NONATOMIC"),
1168 1300
     ])
1169
-    basic_property_strategies = 'jenkins.branch'
1170
-    workflow_multibranch = 'org.jenkinsci.plugins.workflow.multibranch'
1171
-    dbps = XML.SubElement(xml_parent, 'strategy', {
1172
-        'class': ''.join([basic_property_strategies,
1173
-                          '.DefaultBranchPropertyStrategy'])})
1174
-    prop_strats = data.get('property-strategies', None)
1175 1301
 
1176
-    if prop_strats:
1177
-        props_elem = XML.SubElement(dbps, 'properties', {
1178
-            'class': 'java.util.Arrays$ArrayList'})
1179
-        props_elem = XML.SubElement(props_elem, 'a', {
1180
-            'class': ''.join([
1181
-                basic_property_strategies, '.BranchProperty-array'])})
1182
-
1183
-        for dbs_list in prop_strats.get('all-branches', None):
1184
-
1185
-            if dbs_list.get('suppress-scm-triggering', False):
1186
-                XML.SubElement(props_elem, ''.join([
1187
-                    basic_property_strategies, '.NoTriggerBranchProperty']))
1188
-
1189
-            pbdo_val = dbs_list.get(
1190
-                'pipeline-branch-durability-override', None)
1191
-            if pbdo_val:
1192
-                if not pbdo_map.get(pbdo_val):
1193
-                    raise InvalidAttributeError(
1194
-                        'pipeline-branch-durability-override',
1195
-                        pbdo_val,
1196
-                        pbdo_map.keys())
1197
-                pbdo_elem = XML.SubElement(props_elem, ''.join([
1198
-                    workflow_multibranch, '.DurabilityHintBranchProperty']), {
1199
-                        'plugin': 'workflow-multibranch'})
1200
-                XML.SubElement(pbdo_elem, 'hint').text = pbdo_map.get(pbdo_val)
1302
+    for dbs_list in props_list:
1303
+
1304
+        if dbs_list.get('suppress-scm-triggering', False):
1305
+            XML.SubElement(props_elem, ''.join([
1306
+                basic_property_strategies, '.NoTriggerBranchProperty']))
1307
+
1308
+        pbdo_val = dbs_list.get(
1309
+            'pipeline-branch-durability-override', None)
1310
+        if pbdo_val:
1311
+            if not pbdo_map.get(pbdo_val):
1312
+                raise InvalidAttributeError(
1313
+                    'pipeline-branch-durability-override',
1314
+                    pbdo_val,
1315
+                    pbdo_map.keys())
1316
+            pbdo_elem = XML.SubElement(props_elem, ''.join([
1317
+                workflow_multibranch,
1318
+                '.DurabilityHintBranchProperty']), {
1319
+                    'plugin': 'workflow-multibranch'})
1320
+            XML.SubElement(pbdo_elem, 'hint').text = pbdo_map.get(
1321
+                pbdo_val)

+ 94
- 0
tests/multibranch/fixtures/scm_github_named_branch_props.xml View File

@@ -0,0 +1,94 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject plugin="workflow-multibranch">
3
+  <properties/>
4
+  <views>
5
+    <hudson.model.AllView>
6
+      <name>All</name>
7
+      <filterExecutors>false</filterExecutors>
8
+      <filterQueue>false</filterQueue>
9
+      <properties class="hudson.model.View$PropertyList"/>
10
+      <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../../.."/>
11
+    </hudson.model.AllView>
12
+  </views>
13
+  <viewsTabBar class="hudson.views.DefaultViewsTabBar"/>
14
+  <folderViews class="jenkins.branch.MultiBranchProjectViewHolder" plugin="branch-api">
15
+    <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
16
+  </folderViews>
17
+  <healthMetrics>
18
+    <com.cloudbees.hudson.plugins.folder.health.WorstChildHealthMetric plugin="cloudbees-folder">
19
+      <nonRecursive>false</nonRecursive>
20
+    </com.cloudbees.hudson.plugins.folder.health.WorstChildHealthMetric>
21
+  </healthMetrics>
22
+  <icon class="jenkins.branch.MetadataActionFolderIcon" plugin="branch-api">
23
+    <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
24
+  </icon>
25
+  <orphanedItemStrategy class="com.cloudbees.hudson.plugins.folder.computed.DefaultOrphanedItemStrategy" plugin="cloudbees-folder">
26
+    <pruneDeadBranches>true</pruneDeadBranches>
27
+    <daysToKeep>-1</daysToKeep>
28
+    <numToKeep>-1</numToKeep>
29
+  </orphanedItemStrategy>
30
+  <triggers/>
31
+  <sources class="jenkins.branch.MultiBranchProject$BranchSourceList" plugin="branch-api">
32
+    <data>
33
+      <jenkins.branch.BranchSource>
34
+        <source class="org.jenkinsci.plugins.github_branch_source.GitHubSCMSource" plugin="github-branch-source">
35
+          <id>gh-johndoe-foo</id>
36
+          <repoOwner>johndoe</repoOwner>
37
+          <repository>foo</repository>
38
+          <traits>
39
+            <org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait>
40
+              <strategyId>1</strategyId>
41
+            </org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait>
42
+            <org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait>
43
+              <strategyId>1</strategyId>
44
+              <trust class="org.jenkinsci.plugins.github_branch_source.ForkPullRequestDiscoveryTrait$TrustContributors"/>
45
+            </org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait>
46
+            <org.jenkinsci.plugins.github__branch__source.OriginPullRequestDiscoveryTrait>
47
+              <strategyId>1</strategyId>
48
+            </org.jenkinsci.plugins.github__branch__source.OriginPullRequestDiscoveryTrait>
49
+            <jenkins.plugins.git.traits.WipeWorkspaceTrait>
50
+              <extension class="hudson.plugins.git.extensions.impl.WipeWorkspace"/>
51
+            </jenkins.plugins.git.traits.WipeWorkspaceTrait>
52
+          </traits>
53
+        </source>
54
+        <strategy class="jenkins.branch.NamedExceptionsBranchPropertyStrategy">
55
+          <defaultProperties class="java.util.Arrays$ArrayList">
56
+            <a class="jenkins.branch.BranchProperty-array">
57
+              <org.jenkinsci.plugins.workflow.multibranch.DurabilityHintBranchProperty plugin="workflow-multibranch">
58
+                <hint>MAX_SURVIVABILITY</hint>
59
+              </org.jenkinsci.plugins.workflow.multibranch.DurabilityHintBranchProperty>
60
+            </a>
61
+          </defaultProperties>
62
+          <namedExceptions class="java.util.Arrays$ArrayList">
63
+            <a class="jenkins.branch.NamedExceptionsBranchPropertyStrategy$Named-array">
64
+              <jenkins.branch.NamedExceptionsBranchPropertyStrategy_-Named>
65
+                <name>master</name>
66
+                <props class="java.util.Arrays$ArrayList">
67
+                  <a class="jenkins.branch.BranchProperty-array">
68
+                    <jenkins.branch.NoTriggerBranchProperty/>
69
+                    <org.jenkinsci.plugins.workflow.multibranch.DurabilityHintBranchProperty plugin="workflow-multibranch">
70
+                      <hint>SURVIVABLE_NONATOMIC</hint>
71
+                    </org.jenkinsci.plugins.workflow.multibranch.DurabilityHintBranchProperty>
72
+                  </a>
73
+                </props>
74
+              </jenkins.branch.NamedExceptionsBranchPropertyStrategy_-Named>
75
+              <jenkins.branch.NamedExceptionsBranchPropertyStrategy_-Named>
76
+                <name>staging</name>
77
+                <props class="java.util.Arrays$ArrayList">
78
+                  <a class="jenkins.branch.BranchProperty-array">
79
+                    <jenkins.branch.NoTriggerBranchProperty/>
80
+                  </a>
81
+                </props>
82
+              </jenkins.branch.NamedExceptionsBranchPropertyStrategy_-Named>
83
+            </a>
84
+          </namedExceptions>
85
+        </strategy>
86
+      </jenkins.branch.BranchSource>
87
+    </data>
88
+    <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
89
+  </sources>
90
+  <factory class="org.jenkinsci.plugins.workflow.multibranch.WorkflowBranchProjectFactory">
91
+    <owner class="org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject" reference="../.."/>
92
+    <scriptPath>Jenkinsfile</scriptPath>
93
+  </factory>
94
+</org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject>

+ 21
- 0
tests/multibranch/fixtures/scm_github_named_branch_props.yaml View File

@@ -0,0 +1,21 @@
1
+name: 'demo-multibranch-github-min'
2
+project-type: multibranch
3
+scm:
4
+    - github:
5
+        repo: 'foo'
6
+        repo-owner: 'johndoe'
7
+
8
+        property-strategies:
9
+            named-branches:
10
+                defaults:
11
+                  - pipeline-branch-durability-override: max-survivability
12
+                exceptions:
13
+                  - exception:
14
+                      branch-name: master
15
+                      properties:
16
+                        - suppress-scm-triggering: true
17
+                        - pipeline-branch-durability-override: survivable-nonatomic
18
+                  - exception:
19
+                      branch-name: staging
20
+                      properties:
21
+                        - suppress-scm-triggering: true

Loading…
Cancel
Save