diff --git a/tests/fixtures/layouts/sql-build-error.yaml b/tests/fixtures/layouts/sql-build-error.yaml new file mode 100644 index 0000000000..d3a7f2f49b --- /dev/null +++ b/tests/fixtures/layouts/sql-build-error.yaml @@ -0,0 +1,24 @@ +- pipeline: + name: check + manager: independent + trigger: + gerrit: + - event: patchset-created + success: + resultsdb_mysql: null + gerrit: + Verified: 1 + failure: + resultsdb_mysql: null + gerrit: + Verified: -1 + +- job: + name: base + parent: null + run: playbooks/base.yaml + +- project: + name: org/project + check: + jobs: [] diff --git a/tests/unit/test_connection.py b/tests/unit/test_connection.py index cb80a032a2..98048eacfb 100644 --- a/tests/unit/test_connection.py +++ b/tests/unit/test_connection.py @@ -75,7 +75,7 @@ class TestSQLConnection(ZuulDBTestCase): build_table = table_prefix + 'zuul_build' self.assertEqual(16, len(insp.get_columns(buildset_table))) - self.assertEqual(10, len(insp.get_columns(build_table))) + self.assertEqual(11, len(insp.get_columns(build_table))) def test_sql_tables_created(self): "Test the tables for storing results are created properly" diff --git a/tests/unit/test_web.py b/tests/unit/test_web.py index d32857f74c..200a50e399 100644 --- a/tests/unit/test_web.py +++ b/tests/unit/test_web.py @@ -17,6 +17,7 @@ import json import os import urllib.parse import socket +import textwrap import time import jwt @@ -27,6 +28,7 @@ import zuul.rpcclient from tests.base import ZuulTestCase, ZuulDBTestCase, AnsibleZuulTestCase from tests.base import ZuulWebFixture, FIXTURE_DIR, iterate_timeout +from tests.base import simple_layout class FakeConfig(object): @@ -1119,6 +1121,30 @@ class TestBuildInfo(ZuulDBTestCase, BaseTestWeb): if x["job_name"] == "project-merge"][0] self.assertEqual('SUCCESS', project_merge_build['result']) + @simple_layout('layouts/sql-build-error.yaml') + def test_build_error(self): + conf = textwrap.dedent( + """ + - job: + name: test-job + run: playbooks/dne.yaml + + - project: + name: org/project + check: + jobs: + - test-job + """) + + file_dict = {'.zuul.yaml': conf} + A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A', + files=file_dict) + self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1)) + self.waitUntilSettled() + builds = self.get_url("api/tenant/tenant-one/builds").json() + self.assertIn('Unable to find playbook', + builds[0]['error_detail']) + class TestArtifacts(ZuulDBTestCase, BaseTestWeb, AnsibleZuulTestCase): config_file = 'zuul-sql-driver.conf' diff --git a/zuul/driver/sql/alembic/versions/16c1dc9054d0_add_error_detail.py b/zuul/driver/sql/alembic/versions/16c1dc9054d0_add_error_detail.py new file mode 100644 index 0000000000..2e5083ab5a --- /dev/null +++ b/zuul/driver/sql/alembic/versions/16c1dc9054d0_add_error_detail.py @@ -0,0 +1,37 @@ +# 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. + +"""add error_detail + +Revision ID: 16c1dc9054d0 +Revises: 5f183546b39c +Create Date: 2020-02-25 14:04:56.947095 + +""" + +# revision identifiers, used by Alembic. +revision = '16c1dc9054d0' +down_revision = '5f183546b39c' +branch_labels = None +depends_on = None + +from alembic import op +import sqlalchemy as sa + + +def upgrade(table_prefix=''): + op.add_column( + table_prefix + 'zuul_build', sa.Column('error_detail', sa.TEXT())) + + +def downgrade(): + raise Exception("Downgrades not supported") diff --git a/zuul/driver/sql/sqlconnection.py b/zuul/driver/sql/sqlconnection.py index b60ea19327..985fd5329e 100644 --- a/zuul/driver/sql/sqlconnection.py +++ b/zuul/driver/sql/sqlconnection.py @@ -300,6 +300,7 @@ class SQLConnection(BaseConnection): voting = sa.Column(sa.Boolean) log_url = sa.Column(sa.String(255)) node_name = sa.Column(sa.String(255)) + error_detail = sa.Column(sa.TEXT()) buildset = orm.relationship(BuildSetModel, backref="builds") def createArtifact(self, *args, **kw): diff --git a/zuul/driver/sql/sqlreporter.py b/zuul/driver/sql/sqlreporter.py index c6ff1b3ad7..951861cdc0 100644 --- a/zuul/driver/sql/sqlreporter.py +++ b/zuul/driver/sql/sqlreporter.py @@ -93,6 +93,7 @@ class SQLReporter(BaseReporter): voting=build.job.voting, log_url=log_url, node_name=build.node_name, + error_detail=build.error_detail, ) for provides in job.provides: diff --git a/zuul/web/__init__.py b/zuul/web/__init__.py index de2d3a0670..6c3b6a9339 100755 --- a/zuul/web/__init__.py +++ b/zuul/web/__init__.py @@ -824,6 +824,7 @@ class ZuulWebAPI(object): 'voting': build.voting, 'log_url': build.log_url, 'node_name': build.node_name, + 'error_detail': build.error_detail, 'artifacts': [], 'provides': [], }