The Gatekeeper, or a project gating system
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

655 lines
27 KiB

  1. # Copyright 2014 Rackspace Australia
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  4. # not use this file except in compliance with the License. You may obtain
  5. # a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. # License for the specific language governing permissions and limitations
  13. # under the License.
  14. import textwrap
  15. import sqlalchemy as sa
  16. from tests.base import ZuulTestCase, ZuulDBTestCase
  17. def _get_reporter_from_connection_name(reporters, connection_name):
  18. # Reporters are placed into lists for each action they may exist in.
  19. # Search through the given list for the correct reporter by its conncetion
  20. # name
  21. for r in reporters:
  22. if r.connection.connection_name == connection_name:
  23. return r
  24. class TestConnections(ZuulTestCase):
  25. config_file = 'zuul-connections-same-gerrit.conf'
  26. tenant_config_file = 'config/zuul-connections-same-gerrit/main.yaml'
  27. def test_multiple_gerrit_connections(self):
  28. "Test multiple connections to the one gerrit"
  29. A = self.fake_review_gerrit.addFakeChange('org/project', 'master', 'A')
  30. self.addEvent('review_gerrit', A.getPatchsetCreatedEvent(1))
  31. self.waitUntilSettled()
  32. self.assertEqual(len(A.patchsets[-1]['approvals']), 1)
  33. self.assertEqual(A.patchsets[-1]['approvals'][0]['type'], 'Verified')
  34. self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
  35. self.assertEqual(A.patchsets[-1]['approvals'][0]['by']['username'],
  36. 'jenkins')
  37. B = self.fake_review_gerrit.addFakeChange('org/project', 'master', 'B')
  38. self.executor_server.failJob('project-test2', B)
  39. self.addEvent('review_gerrit', B.getPatchsetCreatedEvent(1))
  40. self.waitUntilSettled()
  41. self.assertEqual(len(B.patchsets[-1]['approvals']), 1)
  42. self.assertEqual(B.patchsets[-1]['approvals'][0]['type'], 'Verified')
  43. self.assertEqual(B.patchsets[-1]['approvals'][0]['value'], '-1')
  44. self.assertEqual(B.patchsets[-1]['approvals'][0]['by']['username'],
  45. 'civoter')
  46. class TestSQLConnection(ZuulDBTestCase):
  47. config_file = 'zuul-sql-driver.conf'
  48. tenant_config_file = 'config/sql-driver/main.yaml'
  49. expected_table_prefix = ''
  50. def _sql_tables_created(self, connection_name):
  51. connection = self.scheds.first.connections.connections[connection_name]
  52. insp = sa.engine.reflection.Inspector(connection.engine)
  53. table_prefix = connection.table_prefix
  54. self.assertEqual(self.expected_table_prefix, table_prefix)
  55. buildset_table = table_prefix + 'zuul_buildset'
  56. build_table = table_prefix + 'zuul_build'
  57. self.assertEqual(16, len(insp.get_columns(buildset_table)))
  58. self.assertEqual(13, len(insp.get_columns(build_table)))
  59. def test_sql_tables_created(self):
  60. "Test the tables for storing results are created properly"
  61. self._sql_tables_created('resultsdb_mysql')
  62. self._sql_tables_created('resultsdb_postgresql')
  63. def _sql_indexes_created(self, connection_name):
  64. connection = self.scheds.first.connections.connections[connection_name]
  65. insp = sa.engine.reflection.Inspector(connection.engine)
  66. table_prefix = connection.table_prefix
  67. self.assertEqual(self.expected_table_prefix, table_prefix)
  68. buildset_table = table_prefix + 'zuul_buildset'
  69. build_table = table_prefix + 'zuul_build'
  70. indexes_buildset = insp.get_indexes(buildset_table)
  71. indexes_build = insp.get_indexes(build_table)
  72. # Remove implicitly generated indexes by the foreign key.
  73. # MySQL creates an implicit index with the name if the column (which
  74. # is not a problem as in MySQL the index names are scoped within the
  75. # table). This is an implementation detail of the db engine so don't
  76. # check this.
  77. indexes_build = [x for x in indexes_build
  78. if x['name'] != 'buildset_id']
  79. self.assertEqual(4, len(indexes_buildset))
  80. self.assertEqual(2, len(indexes_build))
  81. # check if all indexes are prefixed
  82. if table_prefix:
  83. indexes = indexes_buildset + indexes_build
  84. for index in indexes:
  85. self.assertTrue(index['name'].startswith(table_prefix))
  86. def test_sql_indexes_created(self):
  87. "Test the indexes are created properly"
  88. self._sql_indexes_created('resultsdb_mysql')
  89. self._sql_indexes_created('resultsdb_postgresql')
  90. def test_sql_results(self):
  91. "Test results are entered into an sql table"
  92. def check_results(connection_name):
  93. # Grab the sa tables
  94. tenant = self.scheds.first.sched.abide.tenants.get('tenant-one')
  95. reporter = _get_reporter_from_connection_name(
  96. tenant.layout.pipelines['check'].success_actions,
  97. connection_name
  98. )
  99. conn = self.scheds.first.connections.connections[connection_name].\
  100. engine.connect()
  101. result = conn.execute(
  102. sa.sql.select([reporter.connection.zuul_buildset_table]))
  103. buildsets = result.fetchall()
  104. self.assertEqual(3, len(buildsets))
  105. buildset0 = buildsets[0]
  106. buildset1 = buildsets[1]
  107. buildset2 = buildsets[2]
  108. self.assertEqual('check', buildset0['pipeline'])
  109. self.assertEqual('org/project', buildset0['project'])
  110. self.assertEqual(1, buildset0['change'])
  111. self.assertEqual('1', buildset0['patchset'])
  112. self.assertEqual('SUCCESS', buildset0['result'])
  113. self.assertEqual('Build succeeded.', buildset0['message'])
  114. self.assertEqual('tenant-one', buildset0['tenant'])
  115. self.assertEqual(
  116. 'https://review.example.com/%d' % buildset0['change'],
  117. buildset0['ref_url'])
  118. self.assertNotEqual(None, buildset0['event_id'])
  119. buildset0_builds = conn.execute(
  120. sa.sql.select([reporter.connection.zuul_build_table]).where(
  121. reporter.connection.zuul_build_table.c.buildset_id ==
  122. buildset0['id']
  123. )
  124. ).fetchall()
  125. # Check the first result, which should be the project-merge job
  126. self.assertEqual('project-merge', buildset0_builds[0]['job_name'])
  127. self.assertEqual("SUCCESS", buildset0_builds[0]['result'])
  128. self.assertEqual(None, buildset0_builds[0]['log_url'])
  129. self.assertEqual('check', buildset1['pipeline'])
  130. self.assertEqual('master', buildset1['branch'])
  131. self.assertEqual('org/project', buildset1['project'])
  132. self.assertEqual(2, buildset1['change'])
  133. self.assertEqual('1', buildset1['patchset'])
  134. self.assertEqual('FAILURE', buildset1['result'])
  135. self.assertEqual('Build failed.', buildset1['message'])
  136. buildset1_builds = conn.execute(
  137. sa.sql.select([reporter.connection.zuul_build_table]).where(
  138. reporter.connection.zuul_build_table.c.buildset_id ==
  139. buildset1['id']
  140. )
  141. ).fetchall()
  142. # Check the second result, which should be the project-test1 job
  143. # which failed
  144. self.assertEqual('project-test1', buildset1_builds[1]['job_name'])
  145. self.assertEqual("FAILURE", buildset1_builds[1]['result'])
  146. self.assertEqual(None, buildset1_builds[1]['log_url'])
  147. buildset2_builds = conn.execute(
  148. sa.sql.select([reporter.connection.zuul_build_table]).where(
  149. reporter.connection.zuul_build_table.c.buildset_id ==
  150. buildset2['id']
  151. )
  152. ).fetchall()
  153. # Check the first result, which should be the project-publish job
  154. self.assertEqual('project-publish',
  155. buildset2_builds[0]['job_name'])
  156. self.assertEqual("SUCCESS", buildset2_builds[0]['result'])
  157. self.executor_server.hold_jobs_in_build = True
  158. # Add a success result
  159. self.log.debug("Adding success FakeChange")
  160. A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
  161. self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
  162. self.waitUntilSettled()
  163. self.orderedRelease()
  164. self.waitUntilSettled()
  165. # Add a failed result
  166. self.log.debug("Adding failed FakeChange")
  167. B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
  168. self.executor_server.failJob('project-test1', B)
  169. self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
  170. self.waitUntilSettled()
  171. self.orderedRelease()
  172. self.waitUntilSettled()
  173. # Add a tag result
  174. self.log.debug("Adding FakeTag event")
  175. C = self.fake_gerrit.addFakeTag('org/project', 'master', 'foo')
  176. self.fake_gerrit.addEvent(C)
  177. self.waitUntilSettled()
  178. self.orderedRelease()
  179. self.waitUntilSettled()
  180. check_results('resultsdb_mysql')
  181. check_results('resultsdb_postgresql')
  182. def test_sql_results_retry_builds(self):
  183. "Test that retry results are entered into an sql table correctly"
  184. # Check the results
  185. def check_results(connection_name):
  186. # Grab the sa tables
  187. tenant = self.scheds.first.sched.abide.tenants.get("tenant-one")
  188. reporter = _get_reporter_from_connection_name(
  189. tenant.layout.pipelines["check"].success_actions,
  190. connection_name
  191. )
  192. with self.scheds.first.connections.connections[connection_name]\
  193. .engine.connect() as conn:
  194. result = conn.execute(
  195. sa.sql.select([reporter.connection.zuul_buildset_table])
  196. )
  197. buildsets = result.fetchall()
  198. self.assertEqual(1, len(buildsets))
  199. buildset0 = buildsets[0]
  200. self.assertEqual('check', buildset0['pipeline'])
  201. self.assertEqual('org/project', buildset0['project'])
  202. self.assertEqual(1, buildset0['change'])
  203. self.assertEqual('1', buildset0['patchset'])
  204. self.assertEqual('SUCCESS', buildset0['result'])
  205. self.assertEqual('Build succeeded.', buildset0['message'])
  206. self.assertEqual('tenant-one', buildset0['tenant'])
  207. self.assertEqual(
  208. 'https://review.example.com/%d' % buildset0['change'],
  209. buildset0['ref_url'])
  210. buildset0_builds = conn.execute(
  211. sa.sql.select(
  212. [reporter.connection.zuul_build_table]
  213. ).where(
  214. reporter.connection.zuul_build_table.c.buildset_id ==
  215. buildset0['id']
  216. )
  217. ).fetchall()
  218. # Check the retry results
  219. self.assertEqual('project-merge', buildset0_builds[0]['job_name'])
  220. self.assertEqual('SUCCESS', buildset0_builds[0]['result'])
  221. self.assertTrue(buildset0_builds[0]['final'])
  222. self.assertEqual('project-test1', buildset0_builds[1]['job_name'])
  223. self.assertEqual('RETRY', buildset0_builds[1]['result'])
  224. self.assertFalse(buildset0_builds[1]['final'])
  225. self.assertEqual('project-test1', buildset0_builds[2]['job_name'])
  226. self.assertEqual('SUCCESS', buildset0_builds[2]['result'])
  227. self.assertTrue(buildset0_builds[2]['final'])
  228. self.assertEqual('project-test2', buildset0_builds[3]['job_name'])
  229. self.assertEqual('RETRY', buildset0_builds[3]['result'])
  230. self.assertFalse(buildset0_builds[3]['final'])
  231. self.assertEqual('project-test2', buildset0_builds[4]['job_name'])
  232. self.assertEqual('SUCCESS', buildset0_builds[4]['result'])
  233. self.assertTrue(buildset0_builds[4]['final'])
  234. self.executor_server.hold_jobs_in_build = True
  235. # Add a retry result
  236. self.log.debug("Adding retry FakeChange")
  237. A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
  238. self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
  239. self.waitUntilSettled()
  240. # Release the merge job (which is the dependency for the other jobs)
  241. self.executor_server.release('.*-merge')
  242. self.waitUntilSettled()
  243. # Let both test jobs fail on the first run, so they are both run again.
  244. self.builds[0].requeue = True
  245. self.builds[1].requeue = True
  246. self.orderedRelease()
  247. self.waitUntilSettled()
  248. check_results('resultsdb_mysql')
  249. check_results('resultsdb_postgresql')
  250. def test_multiple_sql_connections(self):
  251. "Test putting results in different databases"
  252. # Add a successful result
  253. A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
  254. self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
  255. self.waitUntilSettled()
  256. # Add a failed result
  257. B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
  258. self.executor_server.failJob('project-test1', B)
  259. self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
  260. self.waitUntilSettled()
  261. def check_results(connection_name_1, connection_name_2):
  262. # Grab the sa tables for resultsdb
  263. tenant = self.scheds.first.sched.abide.tenants.get('tenant-one')
  264. reporter1 = _get_reporter_from_connection_name(
  265. tenant.layout.pipelines['check'].success_actions,
  266. connection_name_1
  267. )
  268. conn = self.scheds.first.connections.\
  269. connections[connection_name_1].engine.connect()
  270. buildsets_resultsdb = conn.execute(sa.sql.select(
  271. [reporter1.connection.zuul_buildset_table])).fetchall()
  272. # Should have been 2 buildset reported to the resultsdb (both
  273. # success and failure report)
  274. self.assertEqual(2, len(buildsets_resultsdb))
  275. # The first one should have passed
  276. self.assertEqual('check', buildsets_resultsdb[0]['pipeline'])
  277. self.assertEqual(
  278. 'org/project', buildsets_resultsdb[0]['project'])
  279. self.assertEqual(1, buildsets_resultsdb[0]['change'])
  280. self.assertEqual('1', buildsets_resultsdb[0]['patchset'])
  281. self.assertEqual('SUCCESS', buildsets_resultsdb[0]['result'])
  282. self.assertEqual(
  283. 'Build succeeded.', buildsets_resultsdb[0]['message'])
  284. # Grab the sa tables for resultsdb_mysql_failures
  285. reporter2 = _get_reporter_from_connection_name(
  286. tenant.layout.pipelines['check'].failure_actions,
  287. connection_name_2
  288. )
  289. conn = self.scheds.first.connections.\
  290. connections[connection_name_2].engine.connect()
  291. buildsets_resultsdb_failures = conn.execute(sa.sql.select(
  292. [reporter2.connection.zuul_buildset_table])).fetchall()
  293. # The failure db should only have 1 buildset failed
  294. self.assertEqual(1, len(buildsets_resultsdb_failures))
  295. self.assertEqual(
  296. 'check', buildsets_resultsdb_failures[0]['pipeline'])
  297. self.assertEqual('org/project',
  298. buildsets_resultsdb_failures[0]['project'])
  299. self.assertEqual(2,
  300. buildsets_resultsdb_failures[0]['change'])
  301. self.assertEqual(
  302. '1', buildsets_resultsdb_failures[0]['patchset'])
  303. self.assertEqual(
  304. 'FAILURE', buildsets_resultsdb_failures[0]['result'])
  305. self.assertEqual('Build failed.',
  306. buildsets_resultsdb_failures[0]['message'])
  307. check_results('resultsdb_mysql', 'resultsdb_mysql_failures')
  308. check_results('resultsdb_postgresql', 'resultsdb_postgresql_failures')
  309. class TestSQLConnectionPrefix(TestSQLConnection):
  310. config_file = 'zuul-sql-driver-prefix.conf'
  311. expected_table_prefix = 'prefix_'
  312. class TestConnectionsBadSQL(ZuulDBTestCase):
  313. config_file = 'zuul-sql-driver-bad.conf'
  314. tenant_config_file = 'config/sql-driver/main.yaml'
  315. def test_unable_to_connect(self):
  316. "Test the SQL reporter fails gracefully when unable to connect"
  317. self.config.set('zuul', 'layout_config',
  318. 'tests/fixtures/layout-sql-reporter.yaml')
  319. self.scheds.execute(lambda app: app.sched.reconfigure(app.config))
  320. # Trigger a reporter. If no errors are raised, the reporter has been
  321. # disabled correctly
  322. A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
  323. self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
  324. self.waitUntilSettled()
  325. class TestMultipleGerrits(ZuulTestCase):
  326. config_file = 'zuul-connections-multiple-gerrits.conf'
  327. tenant_config_file = 'config/zuul-connections-multiple-gerrits/main.yaml'
  328. def test_multiple_project_separate_gerrits(self):
  329. self.executor_server.hold_jobs_in_build = True
  330. A = self.fake_another_gerrit.addFakeChange(
  331. 'org/project1', 'master', 'A')
  332. self.fake_another_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
  333. self.waitUntilSettled()
  334. self.assertBuilds([dict(name='project-test2',
  335. changes='1,1',
  336. project='org/project1',
  337. pipeline='another_check')])
  338. # NOTE(jamielennox): the tests back the git repo for both connections
  339. # onto the same git repo on the file system. If we just create another
  340. # fake change the fake_review_gerrit will try to create another 1,1
  341. # change and git will fail to create the ref. Arbitrarily set it to get
  342. # around the problem.
  343. self.fake_review_gerrit.change_number = 50
  344. B = self.fake_review_gerrit.addFakeChange(
  345. 'org/project1', 'master', 'B')
  346. self.fake_review_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
  347. self.waitUntilSettled()
  348. self.assertBuilds([
  349. dict(name='project-test2',
  350. changes='1,1',
  351. project='org/project1',
  352. pipeline='another_check'),
  353. dict(name='project-test1',
  354. changes='51,1',
  355. project='org/project1',
  356. pipeline='review_check'),
  357. ])
  358. self.executor_server.hold_jobs_in_build = False
  359. self.executor_server.release()
  360. self.waitUntilSettled()
  361. def test_multiple_project_separate_gerrits_common_pipeline(self):
  362. self.executor_server.hold_jobs_in_build = True
  363. A = self.fake_another_gerrit.addFakeChange(
  364. 'org/project2', 'master', 'A')
  365. self.fake_another_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
  366. self.waitUntilSettled()
  367. self.assertBuilds([dict(name='project-test2',
  368. changes='1,1',
  369. project='org/project2',
  370. pipeline='common_check')])
  371. # NOTE(jamielennox): the tests back the git repo for both connections
  372. # onto the same git repo on the file system. If we just create another
  373. # fake change the fake_review_gerrit will try to create another 1,1
  374. # change and git will fail to create the ref. Arbitrarily set it to get
  375. # around the problem.
  376. self.fake_review_gerrit.change_number = 50
  377. B = self.fake_review_gerrit.addFakeChange(
  378. 'org/project2', 'master', 'B')
  379. self.fake_review_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
  380. self.waitUntilSettled()
  381. self.assertBuilds([
  382. dict(name='project-test2',
  383. changes='1,1',
  384. project='org/project2',
  385. pipeline='common_check'),
  386. dict(name='project-test1',
  387. changes='51,1',
  388. project='org/project2',
  389. pipeline='common_check'),
  390. ])
  391. self.executor_server.hold_jobs_in_build = False
  392. self.executor_server.release()
  393. self.waitUntilSettled()
  394. class TestConnectionsMerger(ZuulTestCase):
  395. config_file = 'zuul-connections-merger.conf'
  396. tenant_config_file = 'config/single-tenant/main.yaml'
  397. source_only = True
  398. def test_connections_merger(self):
  399. "Test merger only configures source connections"
  400. self.assertIn("gerrit", self.scheds.first.connections.connections)
  401. self.assertIn("github", self.scheds.first.connections.connections)
  402. self.assertNotIn("smtp", self.scheds.first.connections.connections)
  403. self.assertNotIn("sql", self.scheds.first.connections.connections)
  404. self.assertNotIn("timer", self.scheds.first.connections.connections)
  405. self.assertNotIn("zuul", self.scheds.first.connections.connections)
  406. class TestConnectionsCgit(ZuulTestCase):
  407. config_file = 'zuul-connections-cgit.conf'
  408. tenant_config_file = 'config/single-tenant/main.yaml'
  409. def test_cgit_web_url(self):
  410. self.assertIn("gerrit", self.scheds.first.connections.connections)
  411. conn = self.scheds.first.connections.connections['gerrit']
  412. source = conn.source
  413. proj = source.getProject('foo/bar')
  414. url = conn._getWebUrl(proj, '1')
  415. self.assertEqual(url,
  416. 'https://cgit.example.com/cgit/foo/bar/commit/?id=1')
  417. class TestConnectionsGitweb(ZuulTestCase):
  418. config_file = 'zuul-connections-gitweb.conf'
  419. tenant_config_file = 'config/single-tenant/main.yaml'
  420. def test_gitweb_url(self):
  421. self.assertIn("gerrit", self.scheds.first.connections.connections)
  422. conn = self.scheds.first.connections.connections['gerrit']
  423. source = conn.source
  424. proj = source.getProject('foo/bar')
  425. url = conn._getWebUrl(proj, '1')
  426. url_should_be = 'https://review.example.com/' \
  427. 'gitweb?p=foo/bar.git;a=commitdiff;h=1'
  428. self.assertEqual(url, url_should_be)
  429. class TestMQTTConnection(ZuulTestCase):
  430. config_file = 'zuul-mqtt-driver.conf'
  431. tenant_config_file = 'config/mqtt-driver/main.yaml'
  432. def test_mqtt_reporter(self):
  433. "Test the MQTT reporter"
  434. # Add a success result
  435. A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
  436. self.executor_server.returnData(
  437. "test", A, {"zuul": {"log_url": "some-log-url"}}
  438. )
  439. self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
  440. self.waitUntilSettled()
  441. success_event = self.mqtt_messages.pop()
  442. start_event = self.mqtt_messages.pop()
  443. self.assertEquals(start_event.get('topic'),
  444. 'tenant-one/zuul_start/check/org/project/master')
  445. mqtt_payload = start_event['msg']
  446. self.assertEquals(mqtt_payload['project'], 'org/project')
  447. self.assertEqual(len(mqtt_payload['commit_id']), 40)
  448. self.assertEquals(mqtt_payload['owner'], 'username')
  449. self.assertEquals(mqtt_payload['branch'], 'master')
  450. self.assertEquals(mqtt_payload['buildset']['result'], None)
  451. self.assertEquals(mqtt_payload['buildset']['builds'][0]['job_name'],
  452. 'test')
  453. self.assertNotIn('result', mqtt_payload['buildset']['builds'][0])
  454. self.assertEquals(success_event.get('topic'),
  455. 'tenant-one/zuul_buildset/check/org/project/master')
  456. mqtt_payload = success_event['msg']
  457. self.assertEquals(mqtt_payload['project'], 'org/project')
  458. self.assertEquals(mqtt_payload['branch'], 'master')
  459. self.assertEquals(mqtt_payload['buildset']['result'], 'SUCCESS')
  460. builds = mqtt_payload['buildset']['builds']
  461. test_job = [b for b in builds if b['job_name'] == 'test'][0]
  462. dependent_test_job = [
  463. b for b in builds if b['job_name'] == 'dependent-test'
  464. ][0]
  465. self.assertEquals(test_job['job_name'], 'test')
  466. self.assertEquals(test_job['result'], 'SUCCESS')
  467. self.assertEquals(test_job['dependencies'], [])
  468. # Both log- and web-url should point to the same URL which is specified
  469. # in the build result data under zuul.log_url.
  470. self.assertEquals(test_job['log_url'], 'some-log-url/')
  471. self.assertEquals(test_job['web_url'], 'some-log-url')
  472. self.assertIn('execute_time', test_job)
  473. self.assertIn('timestamp', mqtt_payload)
  474. self.assertIn('enqueue_time', mqtt_payload)
  475. self.assertIn('trigger_time', mqtt_payload)
  476. self.assertIn('zuul_event_id', mqtt_payload)
  477. self.assertEquals(dependent_test_job['dependencies'], ['test'])
  478. def test_mqtt_invalid_topic(self):
  479. in_repo_conf = textwrap.dedent(
  480. """
  481. - pipeline:
  482. name: test-pipeline
  483. manager: independent
  484. trigger:
  485. gerrit:
  486. - event: comment-added
  487. start:
  488. mqtt:
  489. topic: "{bad}/{topic}"
  490. """)
  491. file_dict = {'zuul.d/test.yaml': in_repo_conf}
  492. A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
  493. files=file_dict)
  494. self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
  495. self.waitUntilSettled()
  496. self.assertIn("topic component 'bad' is invalid", A.messages[0],
  497. "A should report a syntax error")
  498. class TestMQTTConnectionBuildPage(ZuulTestCase):
  499. config_file = "zuul-mqtt-driver.conf"
  500. tenant_config_file = "config/mqtt-driver-report-build-page/main.yaml"
  501. def test_mqtt_reporter(self):
  502. "Test the MQTT reporter with 'report-build-page' enabled"
  503. # Add a sucess result
  504. A = self.fake_gerrit.addFakeChange("org/project", "master", "A")
  505. self.executor_server.returnData(
  506. "test", A, {"zuul": {"log_url": "some-log-url"}}
  507. )
  508. self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
  509. self.waitUntilSettled()
  510. success_event = self.mqtt_messages.pop()
  511. self.assertEquals(
  512. success_event.get("topic"),
  513. "tenant-one/zuul_buildset/check/org/project/master",
  514. )
  515. mqtt_payload = success_event["msg"]
  516. self.assertEquals(mqtt_payload["project"], "org/project")
  517. self.assertEquals(mqtt_payload["branch"], "master")
  518. self.assertEquals(mqtt_payload["buildset"]["result"], "SUCCESS")
  519. builds = mqtt_payload["buildset"]["builds"]
  520. test_job = [b for b in builds if b["job_name"] == "test"][0]
  521. self.assertEquals(test_job["job_name"], "test")
  522. self.assertEquals(test_job["result"], "SUCCESS")
  523. build_id = test_job["uuid"]
  524. # When report-build-page is enabled, the log_url should still point to
  525. # the URL that is specified in the build result data under
  526. # zuul.log_url. The web_url will instead point to the builds page.
  527. self.assertEquals(test_job["log_url"], "some-log-url/")
  528. self.assertEquals(
  529. test_job["web_url"],
  530. "https://tenant.example.com/t/tenant-one/build/{}".format(
  531. build_id
  532. ),
  533. )