sync.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. from __future__ import annotations
  2. import configparser
  3. import os
  4. import subprocess
  5. from devenv import constants
  6. from devenv.lib import colima, config, limactl, proc, venv, volta
  7. # TODO: need to replace this with a nicer process executor in devenv.lib
  8. def run_procs(
  9. repo: str,
  10. reporoot: str,
  11. venv_path: str,
  12. _procs: tuple[tuple[str, tuple[str, ...]], ...],
  13. ) -> bool:
  14. procs: list[tuple[str, tuple[str, ...], subprocess.Popen[bytes]]] = []
  15. for name, cmd in _procs:
  16. print(f"⏳ {name}")
  17. if constants.DEBUG:
  18. proc.xtrace(cmd)
  19. procs.append(
  20. (
  21. name,
  22. cmd,
  23. subprocess.Popen(
  24. cmd,
  25. stdout=subprocess.PIPE,
  26. stderr=subprocess.STDOUT,
  27. env={
  28. **constants.user_environ,
  29. **proc.base_env,
  30. "VIRTUAL_ENV": venv_path,
  31. "VOLTA_HOME": f"{reporoot}/.devenv/bin/volta-home",
  32. "PATH": f"{venv_path}/bin:{reporoot}/.devenv/bin:{proc.base_path}",
  33. },
  34. cwd=reporoot,
  35. ),
  36. )
  37. )
  38. all_good = True
  39. for name, final_cmd, p in procs:
  40. out, _ = p.communicate()
  41. if p.returncode != 0:
  42. all_good = False
  43. out_str = "" if out is None else out.decode()
  44. print(
  45. f"""
  46. ❌ {name}
  47. failed command (code p.returncode):
  48. {proc.quote(final_cmd)}
  49. Output:
  50. {out_str}
  51. """
  52. )
  53. else:
  54. print(f"✅ {name}")
  55. return all_good
  56. def main(context: dict[str, str]) -> int:
  57. repo = context["repo"]
  58. reporoot = context["reporoot"]
  59. venv_dir, python_version, requirements, editable_paths, bins = venv.get(reporoot, repo)
  60. url, sha256 = config.get_python(reporoot, python_version)
  61. print(f"ensuring {repo} venv at {venv_dir}...")
  62. venv.ensure(venv_dir, python_version, url, sha256)
  63. # TODO: move volta version into per-repo config
  64. try:
  65. volta.install(reporoot)
  66. except TypeError:
  67. # this is needed for devenv <=1.4.0,>1.2.3 to finish syncing and therefore update itself
  68. volta.install()
  69. if constants.DARWIN:
  70. repo_config = configparser.ConfigParser()
  71. repo_config.read(f"{reporoot}/devenv/config.ini")
  72. try:
  73. colima.install(
  74. repo_config["colima"]["version"],
  75. repo_config["colima"][constants.SYSTEM_MACHINE],
  76. repo_config["colima"][f"{constants.SYSTEM_MACHINE}_sha256"],
  77. reporoot,
  78. )
  79. except TypeError:
  80. # this is needed for devenv <=1.4.0,>1.2.3 to finish syncing and therefore update itself
  81. colima.install(
  82. repo_config["colima"]["version"],
  83. repo_config["colima"][constants.SYSTEM_MACHINE],
  84. repo_config["colima"][f"{constants.SYSTEM_MACHINE}_sha256"],
  85. )
  86. # TODO: move limactl version into per-repo config
  87. try:
  88. limactl.install(reporoot)
  89. except TypeError:
  90. # this is needed for devenv <=1.4.0,>1.2.3 to finish syncing and therefore update itself
  91. limactl.install()
  92. if not run_procs(
  93. repo,
  94. reporoot,
  95. venv_dir,
  96. (
  97. ("javascript dependencies", ("make", "install-js-dev")),
  98. ("python dependencies", ("make", "install-py-dev")),
  99. ),
  100. ):
  101. return 1
  102. if not run_procs(
  103. repo,
  104. reporoot,
  105. venv_dir,
  106. (
  107. (
  108. "git and precommit",
  109. # this can't be done in paralell with python dependencies
  110. # as multiple pips cannot act on the same venv
  111. ("make", "setup-git"),
  112. ),
  113. ),
  114. ):
  115. return 1
  116. if not os.path.exists(f"{constants.home}/.sentry/config.yml") or not os.path.exists(
  117. f"{constants.home}/.sentry/sentry.conf.py"
  118. ):
  119. proc.run((f"{venv_dir}/bin/sentry", "init", "--dev"))
  120. # TODO: check healthchecks for redis and postgres to short circuit this
  121. proc.run(
  122. (
  123. f"{venv_dir}/bin/{repo}",
  124. "devservices",
  125. "up",
  126. "redis",
  127. "postgres",
  128. ),
  129. pathprepend=f"{reporoot}/.devenv/bin",
  130. exit=True,
  131. )
  132. if run_procs(
  133. repo,
  134. reporoot,
  135. venv_dir,
  136. (
  137. (
  138. "python migrations",
  139. ("make", "apply-migrations"),
  140. ),
  141. ),
  142. ):
  143. return 0
  144. return 1