diff --git a/.gitignore b/.gitignore index 253f82c..f99a9ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /**/packer_cache/ /**/builds/ .vscode +.idea* +*.iml \ No newline at end of file diff --git a/bin/install-mac-homebrew.py b/bin/install-mac-homebrew.py index a17c1ab..4b28100 100755 --- a/bin/install-mac-homebrew.py +++ b/bin/install-mac-homebrew.py @@ -4,48 +4,139 @@ # This script will prompt for user's password if sudo access is needed # TODO(ericbrown): Can we check, install & upgrade apps we know we need/want? +import os +import platform import subprocess -HOMEBREW_INSTALLER = \ - 'https://raw.githubusercontent.com/Homebrew/install/master/install.sh' - -print('Checking for mac homebrew') - -install_brew = False -which = subprocess.run(['which', 'brew'], capture_output=True) -if which.returncode != 0: - print('Brew not found, Installing!') - install_brew = True -else: - result = subprocess.run(['brew', '--help'], capture_output=True) - if result.returncode != 0: - print('Brew broken, Re-installing') - install_brew = True - -if install_brew: - # Download installer - installer = subprocess.run(['curl', '-fsSL', HOMEBREW_INSTALLER], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - check=True) - - # Validate that we have sudo access (as installer script checks) - print("This setup script needs your password to install things as root.") - subprocess.run(['sudo', 'sh', '-c', 'echo You have sudo'], check=True) - - # Run downloaded installer - result = subprocess.run(['bash'], input=installer.stdout, check=True) - -print('Updating (but not upgrading) Homebrew') -subprocess.run(['brew', 'update'], capture_output=True, check=True) - -# Install homebrew-cask, so we can use it manage installing binary/GUI apps -# brew tap caskroom/cask - -# Likely need an alternate versions of Casks in order to install chrome-canary -# Required to install chrome-canary -# (Moved to mac-install-apps.sh, but might be needed elsewhere unbeknownst!) -# subprocess.run(['brew', 'tap', 'brew/cask-versions'], check=True) - -# This is where we store our own formula, including a python@2 backport -subprocess.run(['brew', 'tap', 'khan/repo'], check=True) + +class HomebrewInstaller: + HOMEBREW_INSTALLER = ( + "https://raw.githubusercontent.com/Homebrew/install/master/install.sh" + ) + HOMEBREW_UNINSTALLER = ( + "https://raw.githubusercontent.com/Homebrew/install/master/install.sh" + ) + ARM64_BREW_DIR = "/opt/homebrew/bin" + X86_BREW_DIR = "/usr/local/bin" + + def __init__(self): + self.__install_script = None + self.__uninstall_script = None + + @property + def _install_script(self): + if not self.__install_script: + self.__install_script = self._pull_script(self.HOMEBREW_INSTALLER) + return self.__install_script + + @property + def _uninstall_script(self): + if not self.__install_script: + self.__install_script = self._pull_script(self.HOMEBREW_INSTALLER) + return self.__install_script + + @staticmethod + def _pull_script(script_url): + return subprocess.run( + ["curl", "-fsSL", script_url], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=True, + ).stdout + + @staticmethod + def _install_or_uninstall_homebrew(brew_script, force_x86=False): + # Validate that we have sudo access (as installer script checks) + print( + "This setup script needs your password to install things as root." + ) + subprocess.run(["sudo", "sh", "-c", "echo You have sudo"], check=True) + + # Run installer + installer_runner = ( + ["arch", "-x86_64", "/bin/bash"] if force_x86 else ["/bin/bash"] + ) + subprocess.run(installer_runner, input=brew_script, check=True) + + def install_homebrew(self, force_x86=False): + self._install_or_uninstall_homebrew( + brew_script=self._install_script, force_x86=force_x86 + ) + + def uninstall_homebrew(self, force_x86=False): + if force_x86: + os.environ["PATH"] = self.X86_BREW_DIR + os.environ["PATH"] + self._install_or_uninstall_homebrew(brew_script=self._uninstall_script) + if force_x86: + os.environ["PATH"] = self.ARM64_BREW_DIR + os.environ["PATH"] + + def _validate_and_install_homebrew(self, force_x86=False): + brew_runner = ( + ["arch", "-x86_64", "/usr/local/bin/brew"] + if force_x86 + else ["brew"] + ) + if force_x86: + brew_bin_exists = os.path.exists("/usr/local/bin/brew") + else: + brew_bin_exists = ( + subprocess.run( + ["which", "brew"], capture_output=True + ).returncode + == 0 + ) + if not brew_bin_exists: + print("Brew not found, Installing!") + self.install_homebrew(force_x86=force_x86) + else: + result = subprocess.run( + brew_runner + ["--help"], capture_output=True + ) + if result.returncode != 0: + print("Brew broken, Re-installing") + self.uninstall_homebrew(force_x86=force_x86) + self.install_homebrew(force_x86=force_x86) + update_msg = "Updating (but not upgrading) Homebrew" + if force_x86: + update_msg += " x86" + print(update_msg) + subprocess.run( + brew_runner + ["update"], capture_output=True, check=True + ) + + # Install homebrew-cask, so we can use it manage installing binary/GUI + # apps brew tap caskroom/cask + + # Likely need an alternate versions of Casks in order to install + # chrome-canary + # Required to install chrome-canary + # (Moved to mac-install-apps.sh, but might be needed elsewhere + # unbeknownst!) + # subprocess.run(['brew', 'tap', 'brew/cask-versions'], check=True) + + # This is where we store our own formula, including a python@2 backport + subprocess.run(brew_runner + ["tap", "khan/repo"], check=True) + + def validate_and_install_homebrew(self): + self._validate_and_install_homebrew() + + if platform.uname().machine == "arm64": + # Ensure arm64 brew bin is used by default over x86 + path_msg = ( + self.ARM64_BREW_DIR + + "must come before " + + self.X86_BREW_DIR + + " in PATH" + ) + env_path = os.environ["PATH"] + assert self.ARM64_BREW_DIR in env_path, path_msg + opt_homebrew_idx = env_path.index(self.ARM64_BREW_DIR) + usr_local_bin_idx = env_path.index(self.X86_BREW_DIR) + assert opt_homebrew_idx < usr_local_bin_idx, path_msg + # Install x86 brew for M1 architecture to be run with rosetta + self._validate_and_install_homebrew(force_x86=True) + + +if __name__ == "__main__": + print("Checking for mac homebrew") + HomebrewInstaller().validate_and_install_homebrew() diff --git a/bin/install-mac-python2.py b/bin/install-mac-python2.py index 627b63e..747e5a7 100755 --- a/bin/install-mac-python2.py +++ b/bin/install-mac-python2.py @@ -2,38 +2,46 @@ """Install Khan's python2.""" import argparse +import platform import re import subprocess parser = argparse.ArgumentParser() -parser.add_argument("--force", help="Force install of Khan's python2", - action="store_true") +parser.add_argument( + "--force", help="Force install of Khan's python2", action="store_true" +) args = parser.parse_args() -which = subprocess.run(['which', 'python2'], capture_output=True, text=True) -is_installed = (which.returncode == 0 - and which.stdout.strip() != "/usr/bin/python2") +which = subprocess.run(["which", "python2"], capture_output=True, text=True) +is_installed = ( + which.returncode == 0 and which.stdout.strip() != "/usr/bin/python2" +) if is_installed: print("Already running a non-system python2.") if args.force or not is_installed: action = "reinstall" if is_installed else "install" print("Installing python2 from khan/repo. This may take a few minutes.") - subprocess.run(['brew', action, 'khan/repo/python@2'], check=True) + if platform.uname().machine == "arm64": + brew_runner = ["arch", "-x86_64", "/usr/local/bin/brew"] + else: + brew_runner = ["brew"] + subprocess.run(brew_runner + [action, "khan/repo/python@2"], check=True) # Get version of pip2 pip2_version = "" -pip2_version_str = subprocess.run(['pip2', '--version'], - capture_output=True, text=True) +pip2_version_str = subprocess.run( + ["pip2", "--version"], capture_output=True, text=True +) if pip2_version_str: - match = re.match(r'\w+ (\d+)', pip2_version_str.stdout) + match = re.match(r"\w+ (\d+)", pip2_version_str.stdout) if match: pip2_version = match.group(1) if pip2_version and pip2_version > "19": print("Reverting pip2 from version: " + pip2_version_str.stdout.strip()) - subprocess.run(['pip2', 'install', 'pip<20', '-U'], check=True) + subprocess.run(["pip2", "install", "pip<20", "-U"], check=True) # Simple diagnostics -subprocess.run(['pip2', '--version']) +subprocess.run(["pip2", "--version"]) print("which python2: " + which.stdout.strip()) diff --git a/mac-setup-normal.sh b/mac-setup-normal.sh index af3b330..7122dee 100755 --- a/mac-setup-normal.sh +++ b/mac-setup-normal.sh @@ -209,7 +209,7 @@ install_python2() { fi info "Installing python2 from khan/repo. This may take a few minutes." - brew install khan/repo/python@2 + brew86 install khan/repo/python@2 } install_node() { diff --git a/setup.sh b/setup.sh index e91a96d..c31c7f8 100755 --- a/setup.sh +++ b/setup.sh @@ -310,6 +310,11 @@ install_hooks() { fi } +install_our_lovely_cli() { + cd "$DEVTOOLS_DIR/our-lovely-cli" + npm install +} + install_dotfiles check_dependencies @@ -317,8 +322,9 @@ check_dependencies update_userinfo # the order for these is (mostly!) important, beware -clone_repos setup_python +clone_repos +install_our_lovely_cli # pre-req: clone_repos install_and_setup_gcloud # pre-req: setup_python install_deps # pre-reqs: clone_repos, install_and_setup_gcloud install_hooks # pre-req: clone_repos