diff --git a/npm_install.py b/npm_install.py index ecf8893..7e80d02 100644 --- a/npm_install.py +++ b/npm_install.py @@ -573,7 +573,6 @@ def adjust_nginx_like_paths_in_tree(root: Path): cand.write_text(txt, encoding="utf-8") def install_node_and_yarn(node_pkg: str): - # Node apt_install([node_pkg]) if shutil.which("yarn") or shutil.which("yarnpkg"): return @@ -584,24 +583,44 @@ def install_node_and_yarn(node_pkg: str): os.symlink("/usr/bin/yarnpkg","/usr/bin/yarn") def _build_frontend(src_frontend: Path, dest_frontend: Path): - def _semver(s: str) -> bool: return bool(re.match(r"^\d+(?:\.\d+){1,3}$", (s or "").strip())) - def _good_yarn(cmd: str) -> bool: - v = (run_out([cmd, "--version"], check=False) or "").strip() + def _good_yarn(argv: list[str]) -> bool: + v = (run_out(argv + ["--version"], check=False) or "").strip() return _semver(v) - yarn_cmd = None - if shutil.which("yarn") and _good_yarn("yarn"): - yarn_cmd = ["yarn"] - elif shutil.which("yarnpkg") and _good_yarn("yarnpkg"): - yarn_cmd = ["yarnpkg"] - elif shutil.which("npm"): - if (run_out(["npm", "--version"], check=False) or "").strip(): - yarn_cmd = ["npm", "exec", "--yes", "yarn@stable"] + def _pick_yarn_cmd() -> list[str] | None: + for c in (["yarn"], ["yarnpkg"]): + if shutil.which(c[0]) and _good_yarn(c): + return c + if shutil.which("npm") and (run_out(["npm", "--version"], check=False) or "").strip(): + if _good_yarn(["npm", "exec", "--yes", "yarn@stable"]): + return ["npm", "exec", "--yes", "yarn@stable"] + if shutil.which("npx") and (run_out(["npx", "--version"], check=False) or "").strip(): + if _good_yarn(["npx", "-y", "yarn@stable"]): + return ["npx", "-y", "yarn@stable"] + return None + + def _ensure_yarn_installed(): + if not shutil.which("npm"): + try: + apt_try_install(["npm"]) + except Exception: + run(["apt-get", "update"], check=False) + run(["apt-get", "install", "-y", "npm"]) + run(["npm", "install", "-g", "yarn"], check=False) + + yarn_cmd = _pick_yarn_cmd() if not yarn_cmd: - raise RuntimeError("No yarn in system") + _ensure_yarn_installed() + yarn_cmd = _pick_yarn_cmd() + + if not yarn_cmd: + raise RuntimeError( + "Unable to detect or install a valid Yarn. " + "Try: apt-get install -y npm && npm i -g yarn." + ) with step("Installing frontend dependencies (yarn)"): os.environ["NODE_ENV"] = "development" @@ -612,7 +631,6 @@ def _build_frontend(src_frontend: Path, dest_frontend: Path): Path(cache_dir).mkdir(parents=True, exist_ok=True) run(yarn_cmd + ["cache", "clean"], check=False) - run(yarn_cmd + ["install"]) with step("Building frontend (yarn build)"): @@ -625,6 +643,7 @@ def _build_frontend(src_frontend: Path, dest_frontend: Path): if (src_frontend / "app-images").exists(): shutil.copytree(src_frontend / "app-images", dest_frontend / "images", dirs_exist_ok=True) + def patch_npm_backend_commands(): candidates = [ Path("/opt/npm/lib/utils.js"),