Skip to content

Instantly share code, notes, and snippets.

@koiralakiran1
Last active April 26, 2024 07:29
Show Gist options
  • Save koiralakiran1/2d9a28c7cf42c64cd744b17371630e7e to your computer and use it in GitHub Desktop.
Save koiralakiran1/2d9a28c7cf42c64cd744b17371630e7e to your computer and use it in GitHub Desktop.
How I used to setup my device.
#!/usr/bin/env python
# pylint: disable=line-too-long,missing-module-docstring
import os
import sys
import logging
import platform
import subprocess
class SetupDevice():
"""Executes my new device setup flows"""
logger: logging.Logger
ssh_setup_script = 'https://gist.githubusercontent.com/koiralakiran1/fd33f2b6162f827a0a90a7c45011df53/raw/8dca96fcf5ea49b3c353fa6f437da28bb1c7baef/setup_github_ssh_keys.sh'
default_browser_preference = 'brave-bin' # Pacman's "brave-browser" doesn't work for some reason
# Dotfiles specific config
clone_directory = os.path.expanduser('~/dotfiles')
link_files_script_path_in_dotfiles = 'v2/home/.scripts/link_files.py'
def __init__(self) -> None:
self.logger = self._get_logger()
def _get_logger(self):
handler = logging.StreamHandler()
handler.setLevel(logging.NOTSET)
handler.setFormatter(self._CustomFormatter())
logger = logging.getLogger('SetupDevice')
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)
return logger
def _ask_yes_no(self, question: str, defaultValue = 'no'):
answer = input(f'{question} (y/n/yes/no, default = {defaultValue}): ') or defaultValue
return answer.lower() == 'yes' or answer.lower() == 'y'
def _exec_full(self, filepath):
global_namespace = {
"__file__": filepath,
"__name__": "__main__",
}
with open(filepath, 'rb') as file:
exec(compile(file.read(), filepath, 'exec'), global_namespace)
def _sync_packages(self):
if self._ask_yes_no('Sync packages?', 'y'):
self.logger.info('Syncing pacman package list. (sudo pacman -Sy)')
subprocess.run(['sudo', 'pacman', '-Sy'], check=True)
def _instal_necessary_utilities(self):
self.logger.info('Installing yay and necessary utilities using pacman..')
subprocess.run(['sudo', 'pacman', '-S', '--needed', 'curl', 'wget', 'bash', 'git', 'base-devel', 'yay'], check=True)
def _install_preferred_browser(self):
preferred_browser = input(f'Enter preferred browser (default = {self.default_browser_preference}): ') or self.default_browser_preference
self.logger.info('Installing %s...', preferred_browser)
subprocess.run(['yay', '-S', '--needed', preferred_browser], check=True)
self.logger.info('Now open %s and sync it; Setup password manager, accounts etc.', preferred_browser)
input('Press any key to continue...')
def _setup_github_ssh_access(self):
"""
Setup ssh access to github. Using existing shell file from gist
TODO: Make python version of the shell file
"""
if not self._ask_yes_no('Do you have git ssh setup already?'):
self.logger.info('Setting up new github ssh access')
self.logger.info('Running "%s"', self.ssh_setup_script)
os.system(f'bash <(curl -s {self.ssh_setup_script})')
self.logger.info('Github ssh access setup complete!')
else:
self.logger.info('Skipping ssh setup...')
def _clone_dotfiles(self):
dotfiles_profile = input('Enter github profile to clone "dotfiles" repo from: ')
dotfiles_link = f'git@github.com:{dotfiles_profile}/dotfiles.git'
# Backup existing dotfiles if any
self.logger.info('Backing up existing dotfiles if exists')
subprocess.run(['mv', '-f', self.clone_directory, f'{self.clone_directory}.bkp'], check=False)
# Clone dotfiles
self.logger.info('Cloning dotfiles from %s to %s', dotfiles_link, self.clone_directory)
subprocess.run(['git', 'clone', dotfiles_link, self.clone_directory], check=True)
self.logger.info('Dotfiles cloned!')
def _execute_link_files(self):
if self._ask_yes_no('Link files?'):
self.logger.info('Executing link-files')
self._exec_full(os.path.expanduser(f'{self.clone_directory}/{self.link_files_script_path_in_dotfiles}'))
self.logger.info('Linked files!')
def _install_package_list(self):
if self._ask_yes_no('Install ~/.packagelist?', 'yes'):
subprocess.run(['install-packagelist'], check=True) # alias install-packagelist="yay -S --needed --noconfirm - < ~/.packagelist"
self.logger.info('All packages from packagelist are installed!')
class _CustomFormatter(logging.Formatter):
"""Custom log formatter"""
grey = "\x1b[38m"
green = "\x1B[32m"
yellow = "\x1b[33m"
red = "\x1b[31m"
bold_red = "\x1b[31;1m"
reset = "\x1b[0m"
message_format = "%(asctime)s - %(name)s - %(levelname)s -> %(message)s (%(filename)s:%(lineno)d)"
FORMATS = {
logging.DEBUG: grey + message_format + reset,
logging.INFO: green + message_format + reset,
logging.WARNING: yellow + message_format + reset,
logging.ERROR: red + message_format + reset,
logging.CRITICAL: bold_red + message_format + reset
}
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
def main(self):
"""Main function to run setup device flow"""
self.logger.info('Setting up new system: %s', platform.node())
self._sync_packages()
self._instal_necessary_utilities()
self._install_preferred_browser()
self._setup_github_ssh_access()
self._clone_dotfiles()
self._execute_link_files()
self.logger.info('Now install packagelist. Run `install-packagelist`')
self._install_package_list()
self.logger.info('Setup Complete!')
if __name__ == "__main__":
obj = SetupDevice()
sys.exit(obj.main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment