123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- 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"]
- # don't want this to be accidentally run from getsentry
- assert repo == "sentry", repo
- 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",
- (
- "bash",
- "-euo",
- "pipefail",
- "-c",
- """
- NODE_ENV=development ./.devenv/bin/yarn install --frozen-lockfile
- yarn check --verify-tree || yarn install --check-files
- """,
- ),
- ),
- (
- "python dependencies",
- (
- "bash",
- "-euo",
- "pipefail",
- "-c",
- """
- # install pinned pip
- pip install --constraint requirements-dev-frozen.txt pip
- # pip doesn't do well with swapping drop-ins
- pip uninstall -qqy djangorestframework-stubs django-stubs
- pip install -r requirements-dev-frozen.txt
- python3 -m tools.fast_editable --path .
- """,
- ),
- ),
- ),
- ):
- return 1
- if not run_procs(
- repo,
- reporoot,
- venv_dir,
- (
- (
- "git and precommit",
- # this can't be done in paralell 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", "--no-clobber"))
- # TODO: check healthchecks for redis and postgres to short circuit this
- proc.run(
- (
- f"{venv_dir}/bin/sentry",
- "devservices",
- "up",
- "redis",
- "postgres",
- ),
- pathprepend=f"{reporoot}/.devenv/bin",
- exit=True,
- )
- if not run_procs(
- repo,
- reporoot,
- venv_dir,
- (
- (
- "python migrations",
- (
- "bash",
- "-euo",
- "pipefail",
- "-c",
- """
- make create-db
- sentry upgrade --noinput
- """,
- ),
- ),
- ),
- ):
- return 1
- # Starting sentry is slow.
- stdout = proc.run(
- (
- "docker",
- "exec",
- "sentry_postgres",
- "psql",
- "sentry",
- "postgres",
- "-t",
- "-c",
- "select exists (select from auth_user where email = 'admin@sentry.io')",
- ),
- stdout=True,
- )
- if stdout != "t":
- proc.run(
- (
- f"{venv_dir}/bin/sentry",
- "createuser",
- "--superuser",
- "--email",
- "admin@sentry.io",
- "--password",
- "admin",
- "--no-input",
- )
- )
- return 0
|