Browse Source

Add option to report build page

This adds a tenant option to use the Zuul web build page as the
URL reported to the code review system when a build completes.

The setting is per-tenant (because it requires that the tenant
have a working SQL reporter configured in all pipelines) and
defaults to false, since we can't guarantee that.  In the future,
we expect to make SQL reporting implicit, then this can default
to true and eventually be deprecated.

A new zuul.conf option is added and marked required to supply
the root web URL.  As we perform further integration with the web
app, we may be able to deprecate other similar settings, such
as "status_url".

Change-Id: Iaa3be10525994722d020d2aa5a7dcf141f2404d9
tags/3.10.0
James E. Blair 1 week ago
parent
commit
f13cc924df

+ 9
- 0
doc/source/admin/components.rst View File

@@ -250,6 +250,15 @@ The following sections of ``zuul.conf`` are used by the scheduler:
250 250
 
251 251
 .. attr:: web
252 252
 
253
+   .. attr:: root
254
+      :required:
255
+
256
+      The root URL of the web service (e.g.,
257
+      ``https://zuul.example.com/``).
258
+
259
+      See :attr:`tenant.web-root` for additional options for
260
+      whitelabeled tenant configuration.
261
+
253 262
    .. attr:: status_url
254 263
 
255 264
       URL that will be posted in Zuul comments made to changes when

+ 2
- 0
doc/source/admin/drivers/sql.rst View File

@@ -51,6 +51,8 @@ The connection options for the SQL driver are:
51 51
       if you rely on external databases which you don't have under control.
52 52
       The default is to have no prefix.
53 53
 
54
+.. _sql_reporter:
55
+
54 56
 Reporter Configuration
55 57
 ----------------------
56 58
 

+ 23
- 0
doc/source/admin/tenants.rst View File

@@ -42,6 +42,7 @@ configuration. Some examples of tenant definitions are:
42 42
        name: my-tenant
43 43
        max-nodes-per-job: 5
44 44
        exclude-unprotected-branches: false
45
+       report-build-page: true
45 46
        source:
46 47
          gerrit:
47 48
            config-projects:
@@ -307,6 +308,28 @@ configuration. Some examples of tenant definitions are:
307 308
       this setting can be used to restrict what labels a tenant can use.
308 309
       Without this setting, the tenant can use any labels.
309 310
 
311
+   .. attr:: report-build-page
312
+      :default: false
313
+
314
+      If this is set to ``true``, then Zuul will use the URL of the
315
+      build page in Zuul's web interface when reporting to the code
316
+      review system.  In this case, :attr:`job.success-url` and
317
+      :attr:`job.failure-url` are ignored for the report (though they
318
+      are still used on the status page before the buildset is
319
+      complete and reported).
320
+
321
+      This requires that all the pipelines in the tenant have a
322
+      :ref:`SQL reporter<sql_reporter>` configured, and at least one of
323
+      :attr:`tenant.web-root` or :attr:`web.root` must be defined.
324
+
325
+   .. attr:: web-root
326
+
327
+      If this tenant has a whitelabeled installation of zuul-web, set
328
+      its externally visible URL here (e.g.,
329
+      ``https://tenant.example.com/``).  This will override the
330
+      :attr:`web.root` setting when constructing URLs for this tenant.
331
+
332
+
310 333
 .. _admin_rule_definition:
311 334
 
312 335
 Access Rule

+ 17
- 0
releasenotes/notes/report-build-page-49088c2b0a36e1b5.yaml View File

@@ -0,0 +1,17 @@
1
+---
2
+features:
3
+  - |
4
+    An option to use the URL of the Zuul build page when reporting has
5
+    been added.  This fetaure requires that all the pipelines in the
6
+    tenant have a :ref:`SQL reporter<sql_reporter>` configured, and at
7
+    least one of :attr:`tenant.web-root` or :attr:`web.root` must be
8
+    defined.
9
+
10
+    See :attr:`tenant.report-build-page`.
11
+upgrade:
12
+  - |
13
+    As further integration with the web interface is planned, the
14
+    :attr:`web.root` setting in ``zuul.conf`` is marked required and
15
+    future releases may error if it is missing.  Please add it to your
16
+    configuration now.  See :attr:`tenant.web-root` for additional
17
+    information about whitelabel tenants.

+ 2
- 0
tests/fixtures/config/build-page/git/common-config/playbooks/python27.yaml View File

@@ -0,0 +1,2 @@
1
+- hosts: all
2
+  tasks: []

+ 24
- 0
tests/fixtures/config/build-page/git/common-config/zuul.yaml View File

@@ -0,0 +1,24 @@
1
+- pipeline:
2
+    name: check
3
+    manager: independent
4
+    trigger:
5
+      gerrit:
6
+        - event: patchset-created
7
+    success:
8
+      gerrit:
9
+        Verified: 1
10
+    failure:
11
+      gerrit:
12
+        Verified: -1
13
+
14
+- job:
15
+    name: base
16
+    parent: null
17
+
18
+- job:
19
+    name: python27
20
+    nodeset:
21
+      nodes:
22
+        - name: controller
23
+          label: ubuntu-trusty
24
+    run: playbooks/python27.yaml

+ 1
- 0
tests/fixtures/config/build-page/git/org_project1/README View File

@@ -0,0 +1 @@
1
+test

+ 4
- 0
tests/fixtures/config/build-page/git/org_project1/zuul.yaml View File

@@ -0,0 +1,4 @@
1
+- project:
2
+    check:
3
+      jobs:
4
+        - python27

+ 1
- 0
tests/fixtures/config/build-page/git/org_project2/README View File

@@ -0,0 +1 @@
1
+test

+ 4
- 0
tests/fixtures/config/build-page/git/org_project2/zuul.yaml View File

@@ -0,0 +1,4 @@
1
+- project:
2
+    check:
3
+      jobs:
4
+        - python27

+ 1
- 0
tests/fixtures/config/build-page/git/org_project3/README View File

@@ -0,0 +1 @@
1
+test

+ 4
- 0
tests/fixtures/config/build-page/git/org_project3/zuul.yaml View File

@@ -0,0 +1,4 @@
1
+- project:
2
+    check:
3
+      jobs:
4
+        - python27

+ 29
- 0
tests/fixtures/config/build-page/main.yaml View File

@@ -0,0 +1,29 @@
1
+- tenant:
2
+    name: tenant-one
3
+    web-root: https://one.example.com/
4
+    report-build-page: true
5
+    source:
6
+      gerrit:
7
+        config-projects:
8
+          - common-config
9
+        untrusted-projects:
10
+          - org/project1
11
+
12
+- tenant:
13
+    name: tenant-two
14
+    report-build-page: true
15
+    source:
16
+      gerrit:
17
+        config-projects:
18
+          - common-config
19
+        untrusted-projects:
20
+          - org/project2
21
+
22
+- tenant:
23
+    name: tenant-three
24
+    source:
25
+      gerrit:
26
+        config-projects:
27
+          - common-config
28
+        untrusted-projects:
29
+          - org/project3

+ 1
- 0
tests/fixtures/zuul.conf View File

@@ -33,3 +33,4 @@ default_to=you@example.com
33 33
 
34 34
 [web]
35 35
 static_cache_expiry=1200
36
+root=https://zuul.example.com/

+ 43
- 0
tests/unit/test_scheduler.py View File

@@ -7597,3 +7597,46 @@ class TestPipelineSupersedes(ZuulTestCase):
7597 7597
             dict(name='test-job', result='ABORTED', changes='1,1'),
7598 7598
             dict(name='test-job', result='SUCCESS', changes='1,1'),
7599 7599
         ], ordered=False)
7600
+
7601
+
7602
+class TestReportBuildPage(ZuulTestCase):
7603
+    tenant_config_file = 'config/build-page/main.yaml'
7604
+
7605
+    def test_tenant_url(self):
7606
+        """
7607
+        Test that the tenant url is used in reporting the build page.
7608
+        """
7609
+        A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
7610
+        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
7611
+        self.waitUntilSettled()
7612
+        self.assertHistory([
7613
+            dict(name='python27', result='SUCCESS', changes='1,1'),
7614
+        ])
7615
+        self.assertIn('python27 https://one.example.com/build/',
7616
+                      A.messages[0])
7617
+
7618
+    def test_base_url(self):
7619
+        """
7620
+        Test that the web base url is used in reporting the build page.
7621
+        """
7622
+        A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
7623
+        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
7624
+        self.waitUntilSettled()
7625
+        self.assertHistory([
7626
+            dict(name='python27', result='SUCCESS', changes='1,1'),
7627
+        ])
7628
+        self.assertIn('python27 https://zuul.example.com/t/tenant-two/build/',
7629
+                      A.messages[0])
7630
+
7631
+    def test_no_build_page(self):
7632
+        """
7633
+        Test that we fall back to the old behavior if the tenant is
7634
+        not configured to report the build page
7635
+        """
7636
+        A = self.fake_gerrit.addFakeChange('org/project3', 'master', 'A')
7637
+        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
7638
+        self.waitUntilSettled()
7639
+        self.assertHistory([
7640
+            dict(name='python27', result='SUCCESS', changes='1,1'),
7641
+        ])
7642
+        self.assertIn('python27 finger://', A.messages[0])

+ 5
- 0
zuul/configloader.py View File

@@ -1454,6 +1454,8 @@ class TenantParser(object):
1454 1454
                   'default-parent': str,
1455 1455
                   'default-ansible-version': vs.Any(str, float),
1456 1456
                   'admin-rules': to_list(str),
1457
+                  'report-build-page': bool,
1458
+                  'web-root': str,
1457 1459
                   }
1458 1460
         return vs.Schema(tenant)
1459 1461
 
@@ -1469,6 +1471,9 @@ class TenantParser(object):
1469 1471
                 conf['exclude-unprotected-branches']
1470 1472
         if conf.get('admin-rules') is not None:
1471 1473
             tenant.authorization_rules = conf['admin-rules']
1474
+        if conf.get('report-build-page') is not None:
1475
+            tenant.report_build_page = conf['report-build-page']
1476
+        tenant.web_root = conf.get('web-root', self.scheduler.web_root)
1472 1477
         tenant.allowed_triggers = conf.get('allowed-triggers')
1473 1478
         tenant.allowed_reporters = conf.get('allowed-reporters')
1474 1479
         tenant.allowed_labels = conf.get('allowed-labels')

+ 13
- 1
zuul/model.py View File

@@ -2670,6 +2670,17 @@ class QueueItem(object):
2670 2670
         return url
2671 2671
 
2672 2672
     def formatJobResult(self, job):
2673
+        if (self.pipeline.tenant.report_build_page and
2674
+            self.pipeline.tenant.web_root):
2675
+            build = self.current_build_set.getBuild(job.name)
2676
+            pattern = urllib.parse.urljoin(self.pipeline.tenant.web_root,
2677
+                                           'build/{build.uuid}')
2678
+            url = self.formatUrlPattern(pattern, job, build)
2679
+            return (build.result, url)
2680
+        else:
2681
+            return self.formatProvisionalJobResult(job)
2682
+
2683
+    def formatProvisionalJobResult(self, job):
2673 2684
         build = self.current_build_set.getBuild(job.name)
2674 2685
         result = build.result
2675 2686
         pattern = None
@@ -2764,7 +2775,7 @@ class QueueItem(object):
2764 2775
                     urlformat += '&websocket_url={websocket_url}'
2765 2776
                 build_url = urlformat.format(
2766 2777
                     build=build, websocket_url=websocket_url)
2767
-                (unused, report_url) = self.formatJobResult(job)
2778
+                (unused, report_url) = self.formatProvisionalJobResult(job)
2768 2779
                 if build.start_time:
2769 2780
                     if build.end_time:
2770 2781
                         elapsed = int((build.end_time -
@@ -4217,6 +4228,7 @@ class Tenant(object):
4217 4228
         self.max_job_timeout = 10800
4218 4229
         self.exclude_unprotected_branches = False
4219 4230
         self.default_base_job = None
4231
+        self.report_build_page = False
4220 4232
         self.layout = None
4221 4233
         # The unparsed configuration from the main zuul config for
4222 4234
         # this tenant.

+ 5
- 0
zuul/scheduler.py View File

@@ -25,6 +25,7 @@ import socket
25 25
 import sys
26 26
 import threading
27 27
 import time
28
+import urllib
28 29
 
29 30
 from zuul import configloader
30 31
 from zuul import model
@@ -330,6 +331,10 @@ class Scheduler(threading.Thread):
330 331
         if self.config.has_option('scheduler', 'relative_priority'):
331 332
             if self.config.getboolean('scheduler', 'relative_priority'):
332 333
                 self.use_relative_priority = True
334
+        web_root = get_default(self.config, 'web', 'root', None)
335
+        if web_root:
336
+            web_root = urllib.parse.urljoin(web_root, 't/{tenant.name}/')
337
+        self.web_root = web_root
333 338
 
334 339
         default_ansible_version = get_default(
335 340
             self.config, 'scheduler', 'default_ansible_version', None)

Loading…
Cancel
Save