send_build_stats.py 4.8 KB

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