send_build_stats.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #!/usr/bin/env python3
  2. import datetime
  3. import os
  4. import ydb
  5. import uuid
  6. import subprocess
  7. YDBD_PATH = "ydb/apps/ydbd/ydbd"
  8. DATABASE_PATH = "/ru-central1/b1ggceeul2pkher8vhb6/etnvsjbk7kh1jc6bbfi8"
  9. DATABASE_ENDPOINT = "grpcs://lb.etnvsjbk7kh1jc6bbfi8.ydb.mdb.yandexcloud.net:2135"
  10. FROM_ENV_COLUMNS = [
  11. "github_head_ref",
  12. "github_workflow",
  13. "github_workflow_ref",
  14. "github_sha",
  15. "github_repository",
  16. "github_event_name",
  17. "github_ref_type",
  18. "github_ref_name",
  19. "github_ref",
  20. ]
  21. STRING_COLUMNS = FROM_ENV_COLUMNS + [
  22. "id",
  23. "git_commit_message",
  24. "binary_path",
  25. "build_preset",
  26. ]
  27. DATETIME_COLUMNS = [
  28. "git_commit_time",
  29. ]
  30. UINT64_COLUMNS = [
  31. "size_bytes",
  32. "size_stripped_bytes",
  33. ]
  34. ALL_COLUMNS = STRING_COLUMNS + DATETIME_COLUMNS + UINT64_COLUMNS
  35. def sanitize_str(s):
  36. # YDB SDK expects bytes for 'String' columns
  37. if s is None:
  38. s = "N\A"
  39. return s.encode("utf-8")
  40. def main():
  41. if "CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS" not in os.environ:
  42. print("Env variable CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS is missing, skipping")
  43. return 1
  44. # Do not set up 'real' variable from gh workflows because it interfere with ydb tests
  45. # So, set up it locally
  46. os.environ["YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS"] = os.environ["CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS"]
  47. if not os.path.exists(YDBD_PATH):
  48. # can be possible due to incremental builds and ydbd itself is not affected by changes
  49. print("{} not exists, skipping".format(YDBD_PATH))
  50. return 0
  51. with ydb.Driver(
  52. endpoint=DATABASE_ENDPOINT,
  53. database=DATABASE_PATH,
  54. credentials=ydb.credentials_from_env_variables()
  55. ) as driver:
  56. driver.wait(timeout=10, fail_fast=True)
  57. session = ydb.retry_operation_sync(
  58. lambda: driver.table_client.session().create()
  59. )
  60. with session.transaction() as tx:
  61. text_query_builder = []
  62. for type_ in STRING_COLUMNS:
  63. text_query_builder.append("DECLARE ${} as String;".format(type_))
  64. for type_ in UINT64_COLUMNS:
  65. text_query_builder.append("DECLARE ${} as Uint64;".format(type_))
  66. for type_ in DATETIME_COLUMNS:
  67. text_query_builder.append("DECLARE ${} as Datetime;".format(type_))
  68. text_query_builder.append(
  69. """INSERT INTO binary_size
  70. (
  71. {}
  72. )
  73. VALUES
  74. (
  75. {}
  76. );
  77. """.format(
  78. ", \n ".join(ALL_COLUMNS),
  79. ", \n ".join(["$" + column for column in ALL_COLUMNS]),
  80. )
  81. )
  82. text_query = "\n".join(text_query_builder)
  83. prepared_query = session.prepare(text_query)
  84. binary_size_bytes = subprocess.check_output(
  85. ["bash", "-c", "cat {} | wc -c".format(YDBD_PATH)]
  86. )
  87. binary_size_stripped_bytes = subprocess.check_output(
  88. ["bash", "-c", "./ya tool strip {} -o - | wc -c".format(YDBD_PATH)]
  89. )
  90. build_preset = os.environ.get("build_preset", None)
  91. github_sha = os.environ.get("GITHUB_SHA", None)
  92. if github_sha is not None:
  93. git_commit_time_bytes = subprocess.check_output(
  94. ["git", "show", "--no-patch", "--format=%cI", github_sha]
  95. )
  96. git_commit_message_bytes = subprocess.check_output(
  97. ["git", "log", "--format=%s", "-n", "1", github_sha]
  98. )
  99. git_commit_time = datetime.datetime.fromisoformat(
  100. git_commit_time_bytes.decode("utf-8").strip()
  101. )
  102. git_commit_message = git_commit_message_bytes.decode("utf-8").strip()
  103. git_commit_time_unix = int(git_commit_time.timestamp())
  104. else:
  105. git_commit_time = None
  106. git_commit_message = None
  107. git_commit_time_unix = 0
  108. parameters = {
  109. "$id": sanitize_str(str(uuid.uuid4())),
  110. "$build_preset": sanitize_str(build_preset),
  111. "$binary_path": sanitize_str(YDBD_PATH),
  112. "$size_stripped_bytes": int(binary_size_stripped_bytes.decode("utf-8")),
  113. "$size_bytes": int(binary_size_bytes.decode("utf-8")),
  114. "$git_commit_time": git_commit_time_unix,
  115. "$git_commit_message": sanitize_str(git_commit_message),
  116. }
  117. for column in FROM_ENV_COLUMNS:
  118. value = os.environ.get(column.upper(), None)
  119. parameters["$" + column] = sanitize_str(value)
  120. print("Executing query:\n{}".format(text_query))
  121. print("With parameters:")
  122. for k, v in parameters.items():
  123. print("{}: {}".format(k, v))
  124. tx.execute(prepared_query, parameters, commit_tx=True)
  125. if __name__ == "__main__":
  126. exit(main())