|
21 | 21 | from lxml import etree |
22 | 22 | from markdown2 import markdown |
23 | 23 | from pymysql.err import IntegrityError |
24 | | -from sqlalchemy import and_, func, or_ |
25 | | -from sqlalchemy.orm.query import Query |
| 24 | +from sqlalchemy import and_, func |
26 | 25 | from sqlalchemy.sql import label |
27 | 26 | from sqlalchemy.sql.functions import count |
28 | 27 | from werkzeug.utils import secure_filename |
|
32 | 31 | from mod_auth.controllers import check_access_rights, login_required |
33 | 32 | from mod_auth.models import Role |
34 | 33 | from mod_ci.forms import AddUsersToBlacklist, DeleteUserForm |
35 | | -from mod_ci.models import (BlockedUsers, GcpInstance, MaintenanceMode, |
36 | | - PrCommentInfo, Status) |
| 34 | +from mod_ci.models import (BlockedUsers, CategoryTestInfo, GcpInstance, |
| 35 | + MaintenanceMode, PrCommentInfo, Status) |
37 | 36 | from mod_customized.models import CustomizedTest |
38 | 37 | from mod_home.models import CCExtractorVersion, GeneralData |
39 | 38 | from mod_regression.models import (Category, RegressionTest, |
40 | | - RegressionTestOutput, |
41 | | - RegressionTestOutputFiles, |
42 | | - regressionTestLinkTable) |
| 39 | + RegressionTestOutput) |
43 | 40 | from mod_sample.models import Issue |
| 41 | +from mod_test.controllers import get_test_results |
44 | 42 | from mod_test.models import (Fork, Test, TestPlatform, TestProgress, |
45 | 43 | TestResult, TestResultFile, TestStatus, TestType) |
46 | 44 | from utility import is_valid_signature, request_from_github |
@@ -1138,8 +1136,11 @@ def update_build_badge(status, test) -> None: |
1138 | 1136 | shutil.copyfile(original_location, build_status_location) |
1139 | 1137 | g.log.info('Build badge updated successfully!') |
1140 | 1138 |
|
1141 | | - regression_testid_passed = get_query_regression_testid_passed(test.id) |
1142 | | - test_ids_to_update = [result[0] for result in regression_testid_passed] |
| 1139 | + test_results = get_test_results(test) |
| 1140 | + test_ids_to_update = [] |
| 1141 | + for category_results in test_results: |
| 1142 | + test_ids_to_update.extend([test['test'].id for test in category_results['tests'] if not test['error']]) |
| 1143 | + |
1143 | 1144 | g.db.query(RegressionTest).filter(RegressionTest.id.in_(test_ids_to_update) |
1144 | 1145 | ).update({"last_passed_on": test.id}, synchronize_session=False) |
1145 | 1146 | g.db.commit() |
@@ -1292,7 +1293,7 @@ def progress_type_request(log, test, test_id, request) -> bool: |
1292 | 1293 | state = Status.SUCCESS |
1293 | 1294 | message = 'Tests completed' |
1294 | 1295 | if test.test_type == TestType.pull_request: |
1295 | | - state = comment_pr(test.id, test.pr_nr, test.platform.name) |
| 1296 | + state = comment_pr(test) |
1296 | 1297 | update_build_badge(state, test) |
1297 | 1298 |
|
1298 | 1299 | else: |
@@ -1552,99 +1553,64 @@ def set_avg_time(platform, process_type: str, time_taken: int) -> None: |
1552 | 1553 | g.db.commit() |
1553 | 1554 |
|
1554 | 1555 |
|
1555 | | -def get_query_regression_testid_passed(test_id: int) -> Query: |
1556 | | - """Get sqlalchemy query to fetch all regression tests which passed on given test id. |
| 1556 | +def get_info_for_pr_comment(test: Test) -> PrCommentInfo: |
| 1557 | + """ |
| 1558 | + Return info about the given test for use in a PR comment. |
1557 | 1559 |
|
1558 | | - :param test_id: test id of the test whose query is required |
1559 | | - :type test_id: int |
1560 | | - :return: Query object for passed regression tests |
1561 | | - :rtype: sqlalchemy.orm.query.Query |
1562 | | - """ |
1563 | | - regression_testid_passed = g.db.query(TestResult.regression_test_id).outerjoin( |
1564 | | - TestResultFile, TestResult.test_id == TestResultFile.test_id).filter( |
1565 | | - TestResult.test_id == test_id, |
1566 | | - TestResult.expected_rc == TestResult.exit_code, |
1567 | | - and_( |
1568 | | - RegressionTestOutput.regression_id == TestResult.regression_test_id, |
1569 | | - RegressionTestOutput.ignore.is_(True) |
1570 | | - )).distinct().subquery() |
1571 | | - |
1572 | | - regression_testid_passed = g.db.query(TestResult.regression_test_id).outerjoin( |
1573 | | - TestResultFile, TestResult.test_id == TestResultFile.test_id).filter( |
1574 | | - TestResult.test_id == test_id, |
1575 | | - TestResult.expected_rc == TestResult.exit_code, |
1576 | | - or_( |
1577 | | - TestResult.exit_code != 0, |
1578 | | - and_(TestResult.exit_code == 0, |
1579 | | - TestResult.regression_test_id == TestResultFile.regression_test_id, |
1580 | | - or_(TestResultFile.got.is_(None), |
1581 | | - and_( |
1582 | | - RegressionTestOutputFiles.regression_test_output_id == TestResultFile.regression_test_output_id, |
1583 | | - TestResultFile.got == RegressionTestOutputFiles.file_hashes |
1584 | | - ))) |
1585 | | - )).distinct().union(g.db.query(regression_testid_passed.c.regression_test_id)) |
1586 | | - |
1587 | | - return regression_testid_passed |
1588 | | - |
1589 | | - |
1590 | | -def get_info_for_pr_comment(test_id: int, platform) -> PrCommentInfo: |
1591 | | - """ |
1592 | | - Return info about the given test id for use in a PR comment. |
1593 | | -
|
1594 | | - :param test_id: The identity of Test whose report will be uploaded |
1595 | | - :type test_id: str |
1596 | | - :param platform |
1597 | | - :type: str |
1598 | | - """ |
1599 | | - platform = TestPlatform.from_string(platform) |
| 1560 | + :param test: The test whose report will be returned |
| 1561 | + :type test: Test |
| 1562 | + """ |
1600 | 1563 | last_test_master = g.db.query(Test).filter(Test.branch == "master", Test.test_type == TestType.commit, |
1601 | | - Test.platform == platform).join( |
| 1564 | + Test.platform == test.platform).join( |
1602 | 1565 | TestProgress, Test.id == TestProgress.test_id).filter( |
1603 | 1566 | TestProgress.status == TestStatus.completed).order_by(TestProgress.id.desc()).first() |
1604 | | - regression_test_passed = get_query_regression_testid_passed(test_id) |
1605 | | - |
1606 | | - passed = g.db.query(label('category_id', Category.id), label( |
1607 | | - 'success', count(regressionTestLinkTable.c.regression_id))).filter( |
1608 | | - regressionTestLinkTable.c.regression_id.in_(regression_test_passed), |
1609 | | - Category.id == regressionTestLinkTable.c.category_id).group_by( |
1610 | | - regressionTestLinkTable.c.category_id).subquery() |
1611 | | - tot = g.db.query(label('category', Category.name), label('total', count(regressionTestLinkTable.c.regression_id)), |
1612 | | - label('success', passed.c.success)).outerjoin( |
1613 | | - passed, passed.c.category_id == Category.id).filter( |
1614 | | - Category.id == regressionTestLinkTable.c.category_id).group_by( |
1615 | | - regressionTestLinkTable.c.category_id).all() |
1616 | | - regression_test_failed = RegressionTest.query.filter(RegressionTest.id.notin_(regression_test_passed)).all() |
1617 | | - |
1618 | | - last_test_master_id = last_test_master.id if last_test_master else 0 |
1619 | | - extra_failed_tests = [test for test in regression_test_failed if test.last_passed_on == last_test_master] |
1620 | | - fixed_tests = RegressionTest.query.filter(RegressionTest.id.in_(regression_test_passed), |
1621 | | - RegressionTest.last_passed_on != last_test_master_id).all() |
1622 | | - common_failed_tests = [test for test in regression_test_failed if test.last_passed_on != last_test_master] |
1623 | | - return PrCommentInfo(tot, extra_failed_tests, fixed_tests, common_failed_tests, last_test_master) |
1624 | | - |
1625 | | - |
1626 | | -def comment_pr(test_id, pr_nr, platform) -> str: |
| 1567 | + |
| 1568 | + extra_failed_tests = [] |
| 1569 | + common_failed_tests = [] |
| 1570 | + fixed_tests = [] |
| 1571 | + category_stats = [] |
| 1572 | + |
| 1573 | + test_results = get_test_results(test) |
| 1574 | + for category_results in test_results: |
| 1575 | + category_name = category_results['category'].name |
| 1576 | + |
| 1577 | + category_test_pass_count = 0 |
| 1578 | + for test in category_results['tests']: |
| 1579 | + if not test['error']: |
| 1580 | + category_test_pass_count += 1 |
| 1581 | + if test['test'].last_passed_on != last_test_master: |
| 1582 | + fixed_tests.append(test['test']) |
| 1583 | + else: |
| 1584 | + if test['test'].last_passed_on != last_test_master: |
| 1585 | + common_failed_tests.append(test['test']) |
| 1586 | + else: |
| 1587 | + extra_failed_tests.append(test['test']) |
| 1588 | + |
| 1589 | + category_stats.append(CategoryTestInfo(category_name, len(category_results['tests']), category_test_pass_count)) |
| 1590 | + |
| 1591 | + return PrCommentInfo(category_stats, extra_failed_tests, fixed_tests, common_failed_tests, last_test_master) |
| 1592 | + |
| 1593 | + |
| 1594 | +def comment_pr(test: Test) -> str: |
1627 | 1595 | """ |
1628 | 1596 | Upload the test report to the GitHub PR as comment. |
1629 | 1597 |
|
1630 | | - :param test_id: The identity of Test whose report will be uploaded |
1631 | | - :type test_id: str |
1632 | | - :param pr_nr: PR number to which test commit is related and comment will be uploaded |
1633 | | - :type: str |
1634 | | - :param platform |
1635 | | - :type: str |
| 1598 | + :param test: The test whose report will be uploaded |
| 1599 | + :type test: Test |
1636 | 1600 | """ |
1637 | 1601 | from run import app, log |
1638 | 1602 |
|
1639 | | - comment_info = get_info_for_pr_comment(test_id, platform) |
| 1603 | + test_id = test.id |
| 1604 | + platform = test.platform.name |
| 1605 | + comment_info = get_info_for_pr_comment(test) |
1640 | 1606 | template = app.jinja_env.get_or_select_template('ci/pr_comment.txt') |
1641 | 1607 | message = template.render(comment_info=comment_info, test_id=test_id, platform=platform) |
1642 | 1608 | log.debug(f"GitHub PR Comment Message Created for Test_id: {test_id}") |
1643 | 1609 | try: |
1644 | 1610 | gh = Github(g.github['bot_token']) |
1645 | 1611 | repository = gh.get_repo(f"{g.github['repository_owner']}/{g.github['repository']}") |
1646 | 1612 | # Pull requests are just issues with code, so GitHub considers PR comments in issues |
1647 | | - pull_request = repository.get_pull(number=pr_nr) |
| 1613 | + pull_request = repository.get_pull(number=test.pr_nr) |
1648 | 1614 | comments = pull_request.get_issue_comments() |
1649 | 1615 | bot_name = gh.get_user().login |
1650 | 1616 | for comment in comments: |
|
0 commit comments