123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- from __future__ import annotations
- import configparser
- import os
- import shlex
- import subprocess
- from devenv import constants
- from devenv.lib import colima, config, limactl, proc, venv, volta
- # TODO: need to replace this with a nicer process executor in devenv.lib
- def run_procs(
- repo: str,
- reporoot: str,
- venv_path: str,
- _procs: tuple[tuple[str, tuple[str, ...]], ...],
- ) -> bool:
- procs: list[tuple[str, tuple[str, ...], subprocess.Popen[bytes]]] = []
- for name, cmd in _procs:
- print(f"⏳ {name}")
- if constants.DEBUG:
- proc.xtrace(cmd)
- procs.append(
- (
- name,
- cmd,
- subprocess.Popen(
- cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
- env={
- **constants.user_environ,
- **proc.base_env,
- "VIRTUAL_ENV": venv_path,
- "VOLTA_HOME": f"{reporoot}/.devenv/bin/volta-home",
- "PATH": f"{venv_path}/bin:{reporoot}/.devenv/bin:{proc.base_path}",
- },
- cwd=reporoot,
- ),
- )
- )
- all_good = True
- for name, final_cmd, p in procs:
- out, _ = p.communicate()
- if p.returncode != 0:
- all_good = False
- print(
- f"""
- ❌ {name}
- failed command (code p.returncode):
- {shlex.join(final_cmd)}
- Output:
- {out.decode()}
- """
- )
- else:
- print(f"✅ {name}")
- return all_good
- def main(context: dict[str, str]) -> int:
- repo = context["repo"]
- reporoot = context["reporoot"]
- FRONTEND_ONLY = os.environ.get("SENTRY_DEVENV_FRONTEND_ONLY") is not None
- # venv's still needed for frontend because repo-local devenv and pre-commit
- # exist inside it
- venv_dir, python_version, requirements, editable_paths, bins = venv.get(reporoot, repo)
- url, sha256 = config.get_python(reporoot, python_version)
- print(f"ensuring {repo} venv at {venv_dir}...")
- venv.ensure(venv_dir, python_version, url, sha256)
- # TODO: move volta version into per-repo config
- try:
- volta.install(reporoot)
- except TypeError:
- # this is needed for devenv <=1.4.0,>1.2.3 to finish syncing and therefore update itself
- volta.install()
- if constants.DARWIN:
- repo_config = configparser.ConfigParser()
- repo_config.read(f"{reporoot}/devenv/config.ini")
- try:
- colima.install(
- repo_config["colima"]["version"],
- repo_config["colima"][constants.SYSTEM_MACHINE],
- repo_config["colima"][f"{constants.SYSTEM_MACHINE}_sha256"],
- reporoot,
- )
- except TypeError:
- # this is needed for devenv <=1.4.0,>1.2.3 to finish syncing and therefore update itself
- colima.install(
- repo_config["colima"]["version"],
- repo_config["colima"][constants.SYSTEM_MACHINE],
- repo_config["colima"][f"{constants.SYSTEM_MACHINE}_sha256"],
- )
- # TODO: move limactl version into per-repo config
- try:
- limactl.install(reporoot)
- except TypeError:
- # this is needed for devenv <=1.4.0,>1.2.3 to finish syncing and therefore update itself
- limactl.install()
- if not run_procs(
- repo,
- reporoot,
- venv_dir,
- (
- ("javascript dependencies", ("make", "install-js-dev")),
- # could opt out of syncing python if FRONTEND_ONLY but only if repo-local devenv
- # and pre-commit were moved to inside devenv and not the sentry venv
- ("python dependencies", ("make", "install-py-dev")),
- ),
- ):
- return 1
- if not run_procs(
- repo,
- reporoot,
- venv_dir,
- (
- (
- "git and precommit",
- # this can't be done in parallel with python dependencies
- # as multiple pips cannot act on the same venv
- ("make", "setup-git"),
- ),
- ),
- ):
- return 1
- if not os.path.exists(f"{constants.home}/.sentry/config.yml") or not os.path.exists(
- f"{constants.home}/.sentry/sentry.conf.py"
- ):
- proc.run((f"{venv_dir}/bin/sentry", "init", "--dev"))
- # Frontend engineers don't necessarily always have devservices running and
- # can configure to skip them to save on local resources
- if FRONTEND_ONLY:
- print("Skipping python migrations since SENTRY_DEVENV_FRONTEND_ONLY is set.")
- return 0
- # TODO: check healthchecks for redis and postgres to short circuit this
- proc.run(
- (
- f"{venv_dir}/bin/{repo}",
- "devservices",
- "up",
- "redis",
- "postgres",
- ),
- pathprepend=f"{reporoot}/.devenv/bin",
- exit=True,
- )
- if run_procs(
- repo,
- reporoot,
- venv_dir,
- (
- (
- "python migrations",
- ("make", "apply-migrations"),
- ),
- ),
- ):
- return 0
- return 1
|