test_analytics_search_source.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. # Copyright Materialize, Inc. and contributors. All rights reserved.
  2. #
  3. # Use of this software is governed by the Business Source License
  4. # included in the LICENSE file at the root of this repository.
  5. #
  6. # As of the Change Date specified in that file, in accordance with
  7. # the Business Source License, use of this software will be governed
  8. # by the Apache License, Version 2.0.
  9. from textwrap import dedent
  10. from materialize.buildkite_insights.data.build_annotation import BuildAnnotation
  11. from materialize.buildkite_insights.data.build_info import Build
  12. from materialize.test_analytics.config.test_analytics_db_config import (
  13. create_test_analytics_config_with_credentials,
  14. )
  15. from materialize.test_analytics.test_analytics_db import TestAnalyticsDb
  16. from materialize.test_analytics.util.mz_sql_util import as_sanitized_literal
  17. ANY_PIPELINE_VALUE = "*"
  18. ANY_BRANCH_VALUE = "*"
  19. class TestAnalyticsDataSource:
  20. __test__ = False
  21. def __init__(
  22. self,
  23. test_analytics_hostname: str,
  24. test_analytics_username: str,
  25. test_analytics_app_password: str,
  26. ):
  27. test_analytics_db_config = create_test_analytics_config_with_credentials(
  28. test_analytics_hostname,
  29. test_analytics_username,
  30. test_analytics_app_password,
  31. )
  32. self.test_analytics_db = TestAnalyticsDb(test_analytics_db_config)
  33. def search_annotations(
  34. self,
  35. pipeline: str,
  36. branch: str | None,
  37. build_step_keys: list[str],
  38. not_newer_than_build_number: int | None,
  39. like_pattern: str,
  40. max_entries: int,
  41. only_failed_builds: bool,
  42. ) -> list[tuple[Build, BuildAnnotation]]:
  43. pipeline_clause = (
  44. f" AND bae.pipeline = {as_sanitized_literal(pipeline)}"
  45. if pipeline != ANY_PIPELINE_VALUE
  46. else ""
  47. )
  48. branch_clause = (
  49. f" AND bae.branch = {as_sanitized_literal(branch)}"
  50. if branch is not None
  51. else ""
  52. )
  53. failed_builds_clause = " AND bsu.has_failed_steps" if only_failed_builds else ""
  54. if len(build_step_keys) > 0:
  55. in_build_step_keys = ",".join(
  56. as_sanitized_literal(key) for key in build_step_keys
  57. )
  58. build_steps_keys_clause = (
  59. f" AND bae.build_step_key IN ({in_build_step_keys})"
  60. )
  61. else:
  62. build_steps_keys_clause = ""
  63. build_number_offset_clause = (
  64. f"AND bae.build_number <= {not_newer_than_build_number}"
  65. if not_newer_than_build_number is not None
  66. else ""
  67. )
  68. order_clause = (
  69. "bae.build_number DESC"
  70. if pipeline != ANY_PIPELINE_VALUE
  71. else "bae.build_date DESC"
  72. )
  73. result_rows = self.test_analytics_db.build_annotations.query_data(
  74. dedent(
  75. f"""
  76. SELECT
  77. bae.build_number,
  78. bae.pipeline,
  79. CASE WHEN bsu.has_failed_steps THEN 'FAILED' else 'PASSED' END AS state,
  80. bae.branch,
  81. bsu.build_url,
  82. bae.build_date,
  83. bae.test_suite,
  84. bae.content
  85. FROM v_build_annotation_error bae
  86. INNER JOIN v_build_success bsu
  87. ON bae.build_id = bsu.build_id
  88. WHERE bae.content ILIKE {as_sanitized_literal(like_pattern)}
  89. {pipeline_clause}
  90. {branch_clause}
  91. {failed_builds_clause}
  92. {build_steps_keys_clause}
  93. {build_number_offset_clause}
  94. ORDER BY
  95. {order_clause}
  96. LIMIT {max_entries}
  97. """
  98. ),
  99. verbose=False,
  100. statement_timeout="5s",
  101. )
  102. result = []
  103. for row in result_rows:
  104. build = Build(
  105. number=row[0],
  106. pipeline=row[1],
  107. state=row[2],
  108. branch=row[3],
  109. web_url=row[4],
  110. created_at=row[5],
  111. )
  112. annotation = BuildAnnotation(title=row[6], content=row[7])
  113. result.append((build, annotation))
  114. return result