diff --git a/README.md b/README.md index 3d1b64a..dbc5f2d 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,12 @@ The package is structured as such: ``` env/ - bootstrap.sh # Adds bootstrap block to your shell's config file. - steps.sh # Definitions for bootstrapping steps - shell_extras # Functions, aliases and exports for the shell. - extras.vim # Common config for NVIM. + bootstrap.sh # Adds bootstrap block to your shell's config file. + files/ + shell_extras # Functions, aliases and exports for the shell. + extras.vim # Common config for neovim. + git_config # Configuration commands for git + starship.toml # Starship prompt configuration ``` Adding code to `shell_extras` will add code that gets executed on shell-start. diff --git a/bootstrap.sh b/bootstrap.sh index 6c01403..7018f62 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,19 +1,223 @@ #!/bin/bash -# Ensuring steps are defined. -. ./steps.sh +########################################################### +# +# Marc's environment bootstrap script. +# +# Table of contents +# +# 1. Helpers and utilities +# These functions are used by individual bootstrap +# steps and are reused all over. +# 2. Steps +# Functions implementing a specific action in the +# bootstrap process. +# 3. Bootstrap sequence and callsite +# Where the magic happens. +# This is where the ordered sequence of steps +# is defined and run. +# +########################################################### -TOTAL_STEPS=8 +########################################################### +# +# 1. Helpers and utilities +# +########################################################### + +STEP_COUNT=0 +SUBSTEP_COUNT=0 + +# Pretty-print step headers. +pre_step() { + STEP_COUNT=$(($STEP_COUNT + 1)) + SUBSTEP_COUNT=0 + echo -e "\e[1m[$STEP_COUNT/$TOTAL_STEPS] <====== $1 =======>\e[0m" +} + +# Pretty-prints substep headers. +pre_substep() { + SUBSTEP_COUNT=$(($SUBSTEP_COUNT + 1)) + echo -e "\e[1m[$STEP_COUNT.$SUBSTEP_COUNT] <====== $1 =======>\e[0m" +} + +########################################################## +# +# 2. Steps +# +########################################################## + +# Ensures that all existing Apt packages are up-to-date. +ensure_apt_up_to_date() { + pre_step "Ensuring apt packages are up-to-date" + + if [ -z "$(apt --version 2> /dev/null)" ]; then + echo -e "\e[33mApt not installed, skipping updates.\e[0m" + else + echo -e "\e[1mEnsuring system packages are up-to-date...\e[0m" + + sudo apt update && sudo apt upgrade -y --autoremove + + echo -e "\e[1;32mSystem packages up-to-date.\e[0m" + fi +} + +# Installs packages as specified in apt.txt +ensure_apt_dependencies() { + pre_step "Installing extra packages" + + if [ -z "$(apt --version 2> /dev/null)" ]; then + echo -e "\e[33mApt not installed, skipping packages.\e[0m" + else + echo -e "\e[1mInstalling packages...\e[0m" + + sudo apt install $(cat ./files/apt.txt) -y --autoremove + + echo -e "\e[1;32mSystem packages installed.\e[0m" + fi +} + +# Installs the rustup toolchain if not installed. +# If installed, the toolchain is updated. +install_rust() { + pre_step "Install and configure Rust toolchain" + + if [ -z "$(rustup --version 2> /dev/null)" ]; then + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + else + rustup update + fi +} + +install_omz() { + pre_step "Installs Oh My ZSH" + curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh | bash +} + +# Installs the Starship prompt and adds an initialization +# command to the shell configuration file. +# +# Requires: install_rust +install_and_configure_starship() { + pre_step "Install and configure Starship" + + pre_substep "Install Starship via cargo" + cargo install starship --locked + + pre_substep "Add initialization command to shell configuration" + STARSHIP_INIT_COMMAND='eval "$(starship init zsh)"' + if [ -z "$(rg "starship init zsh" ~/.zshrc)" ]; then + echo "#Initialize Starship prompt\n$STARSHIP_INIT_COMMAND" >> ~/.zshrc + fi + + pre_substep "Copy configuration in configuration directory" + STARSHIP_CONFIGURATION_PATH=~/.config/starship.toml + if [ -f $STARSHIP_CONFIGURATION_PATH ]; then + cp $STARSHIP_CONFIGURATION_PATH $STARSHIP_CONFIGURATION_PATH.old + fi + + cp ./files/starship.toml $STARSHIP_CONFIGURATION_PATH +} + +install_nvm() { + pre_step "Installing nvm to manage node version" + + pre_substep "Installing NVM from remote" + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash + + pre_substep "Ensuring that NVM can be run right away" + # Ensuring that nvm is usable right away without restarting the shell + export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" +} + +install_gh_plugins() { + pre_step "Installing gh cli plugins" + + gh extension install nektos/gh-act + gh extension install dlvhdr/gh-dash + + gh extension upgrade --all +} + +install_pyenv() { + pre_step "Install and configure pyenv" + + curl https://pyenv.run | bash +} + +# Injects a managed block in the shell configuration. +inject_shell_configuration() { + pre_step "Injecting managed block in shell configuration" + + BLOCK_DELIMITER_PATTERN="mcataford/env" + WORKING_PATH=$(git rev-parse --show-toplevel) + SHELL_CONFIG_PATH="$HOME/.zshrc" + + echo "Setting up shell configuration extras..." + if [[ -z $(cat $SHELL_CONFIG_PATH | grep $BLOCK_DELIMITER_PATTERN) ]]; then + echo "# $BLOCK_DELIMITER_PATTERN\:start + source $WORKING_PATH/files/shell_extras + # $BLOCK_DELIMITER_PATTERN\:end" >> $SHELL_CONFIG_PATH + echo "✅ Added managed block to $SHELL_CONFIG_PATH" + else + echo "No changes to apply!" + fi + + EDITOR_CONFIG=$HOME/.config/nvim + EDITOR_CONFIG_FILE=$EDITOR_CONFIG/init.vim +} + +# Injects a managed block in the vim configuration +inject_vim_configuration() { + pre_step "Inject managed block in vim configuration" + + WORKING_PATH=$(git rev-parse --show-toplevel) + + if [[ -f $EDITOR_CONFIG_FILE ]]; then + echo "Setting up NVIM configuration extras..." + if [[ -z $(cat $EDITOR_CONFIG_FILE | grep $BLOCK_DELIMITER_PATTERN) ]]; then + echo "\" $BLOCK_DELIMITER_PATTERN\:start + source $WORKING_PATH/files/extras.vim + \" $BLOCK_DELIMITER_PATTERN\:end\n\n" >> $EDITOR_CONFIG_FILE.new + cat $EDITOR_CONFIG_FILE >> $EDITOR_CONFIG_FILE.new + + mv $EDITOR_CONFIG_FILE $EDITOR_CONFIG_FILE.old + mv $EDITOR_CONFIG_FILE.new $EDITOR_CONFIG_FILE + echo "✅ Added managed block to $EDITOR_CONFIG_FILE" + else + echo "No changes to apply!" + fi + fi + + echo "Setting up git configuration..." + source $WORKING_PATH/files/git_config + echo "✅ Set up git configuration, see $WORKING_PATH/files/git_config for details!" +} + +########################################################### +# +# 3. Bootstrap sequence +# +########################################################### + +TOTAL_STEPS=10 # Refer to steps.sh for step definition. bootstrap() { + # System updates ensure_apt_up_to_date ensure_apt_dependencies - install_rust - ensure_nvm + # Development tooling and SDKs + install_rust + install_pyenv + install_nvm + install_gh_plugins + # Shell & prompt setup - ensure_omz + install_omz install_and_configure_starship inject_shell_configuration diff --git a/apt.txt b/files/apt.txt similarity index 92% rename from apt.txt rename to files/apt.txt index bf7b028..17dbd6e 100644 --- a/apt.txt +++ b/files/apt.txt @@ -2,3 +2,4 @@ zsh tmux postgresql postgresql-contrib +gh diff --git a/extras.vim b/files/extras.vim similarity index 100% rename from extras.vim rename to files/extras.vim diff --git a/git_config b/files/git_config similarity index 100% rename from git_config rename to files/git_config diff --git a/shell_extras b/files/shell_extras similarity index 100% rename from shell_extras rename to files/shell_extras diff --git a/steps.sh b/steps.sh deleted file mode 100644 index e94c47a..0000000 --- a/steps.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash - -STEP_COUNT=0 -SUBSTEP_COUNT=0 - -# Helpers to pretty-print step titles and count. -pre_step() { - STEP_COUNT=$(($STEP_COUNT + 1)) - SUBSTEP_COUNT=0 - echo -e "\e[1m[$STEP_COUNT/$TOTAL_STEPS] <====== $1 =======>\e[0m" -} - -pre_substep() { - SUBSTEP_COUNT=$(($SUBSTEP_COUNT + 1)) - echo -e "\e[1m[$STEP_COUNT.$SUBSTEP_COUNT] <====== $1 =======>\e[0m" -} - -# Ensures that all existing Apt packages are up-to-date. -ensure_apt_up_to_date() { - pre_step "Ensuring apt packages are up-to-date" - - if [ -z "$(apt --version 2> /dev/null)" ]; then - echo -e "\e[33mApt not installed, skipping updates.\e[0m" - else - echo -e "\e[1mEnsuring system packages are up-to-date...\e[0m" - - sudo apt update && sudo apt upgrade -y --autoremove - - echo -e "\e[1;32mSystem packages up-to-date.\e[0m" - fi -} - -# Installs packages as specified in apt.txt -ensure_apt_dependencies() { - pre_step "Installing extra packages" - - if [ -z "$(apt --version 2> /dev/null)" ]; then - echo -e "\e[33mApt not installed, skipping packages.\e[0m" - else - echo -e "\e[1mInstalling packages...\e[0m" - - sudo apt install $(cat ./apt.txt) -y --autoremove - - echo -e "\e[1;32mSystem packages installed.\e[0m" - fi -} - -# Installs the rustup toolchain if not installed. -# If installed, the toolchain is updated. -install_rust() { - pre_step "Install and configure Rust toolchain" - - if [ -z "$(rustup --version 2> /dev/null)" ]; then - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - else - rustup update - fi -} - -ensure_omz() { - pre_step "Installs Oh My ZSH" - curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh | bash -} - -# Installs the Starship prompt and adds an initialization -# command to the shell configuration file. -# -# Requires: install_rust -install_and_configure_starship() { - pre_step "Install and configure Starship" - - pre_substep "Install Starship via cargo" - cargo install starship --locked - - pre_substep "Add initialization command to shell configuration" - STARSHIP_INIT_COMMAND='eval "$(starship init zsh)"' - if [ -z "$(rg "starship init zsh" ~/.zshrc)" ]; then - echo "#Initialize Starship prompt\n$STARSHIP_INIT_COMMAND" >> ~/.zshrc - fi - - pre_substep "Copy configuration in configuration directory" - STARSHIP_CONFIGURATION_PATH=~/.config/starship.toml - if [ -f $STARSHIP_CONFIGURATION_PATH ]; then - cp $STARSHIP_CONFIGURATION_PATH $STARSHIP_CONFIGURATION_PATH.old - fi - - cp ./files/starship.toml $STARSHIP_CONFIGURATION_PATH -} - -ensure_nvm() { - pre_step "Installing nvm to manage node version" - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash - - # Ensuring that nvm is usable right away without restarting the shell - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" -} - -# Injects a managed block in the shell configuration. -inject_shell_configuration() { - pre_step "Injecting managed block in shell configuration" - - BLOCK_DELIMITER_PATTERN="mcataford/env" - WORKING_PATH=$(git rev-parse --show-toplevel) - SHELL_CONFIG_PATH="$HOME/.zshrc" - - echo "Setting up shell configuration extras..." - if [[ -z $(cat $SHELL_CONFIG_PATH | grep $BLOCK_DELIMITER_PATTERN) ]]; then - echo "# $BLOCK_DELIMITER_PATTERN\:start - source $WORKING_PATH/shell_extras - # $BLOCK_DELIMITER_PATTERN\:end" >> $SHELL_CONFIG_PATH - echo "✅ Added managed block to $SHELL_CONFIG_PATH" - else - echo "No changes to apply!" - fi - - EDITOR_CONFIG=$HOME/.config/nvim - EDITOR_CONFIG_FILE=$EDITOR_CONFIG/init.vim -} - -# Injects a managed block in the vim configuration -inject_vim_configuration() { - pre_step "Inject managed block in vim configuration" - - if [[ -f $EDITOR_CONFIG_FILE ]]; then - echo "Setting up NVIM configuration extras..." - if [[ -z $(cat $EDITOR_CONFIG_FILE | grep $BLOCK_DELIMITER_PATTERN) ]]; then - echo "\" $BLOCK_DELIMITER_PATTERN\:start - source $WORKING_PATH/extras.vim - \" $BLOCK_DELIMITER_PATTERN\:end\n\n" >> $EDITOR_CONFIG_FILE.new - cat $EDITOR_CONFIG_FILE >> $EDITOR_CONFIG_FILE.new - - mv $EDITOR_CONFIG_FILE $EDITOR_CONFIG_FILE.old - mv $EDITOR_CONFIG_FILE.new $EDITOR_CONFIG_FILE - echo "✅ Added managed block to $EDITOR_CONFIG_FILE" - else - echo "No changes to apply!" - fi - fi - - echo "Setting up git configuration..." - source $WORKING_PATH/git_config - echo "✅ Set up git configuration, see $WORKING_PATH/git_config for details!" -}