diff --git a/.github/workflows/test-install-scripts.yml b/.github/workflows/test-install-scripts.yml index ae2cb7d..73a1c3c 100644 --- a/.github/workflows/test-install-scripts.yml +++ b/.github/workflows/test-install-scripts.yml @@ -8,6 +8,16 @@ on: workflow_dispatch: jobs: + shellcheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run shellcheck + uses: ludeeus/action-shellcheck@master + with: + scandir: './install' + severity: error + changes: runs-on: ubuntu-latest outputs: @@ -381,6 +391,7 @@ jobs: runs-on: ubuntu-latest needs: - changes + - shellcheck - test-nvim-install - test-kitty-install - test-starship-install @@ -391,7 +402,8 @@ jobs: run: | echo "Checking test results..." - if [[ "${{ needs.test-nvim-install.result }}" == "failure" ]] || \ + if [[ "${{ needs.shellcheck.result }}" == "failure" ]] || \ + [[ "${{ needs.test-nvim-install.result }}" == "failure" ]] || \ [[ "${{ needs.test-kitty-install.result }}" == "failure" ]] || \ [[ "${{ needs.test-starship-install.result }}" == "failure" ]] || \ [[ "${{ needs.test-zk-install.result }}" == "failure" ]]; then diff --git a/install/kitty.sh b/install/kitty.sh index 811bc76..58a84af 100755 --- a/install/kitty.sh +++ b/install/kitty.sh @@ -66,9 +66,9 @@ install_kitty() { echo "Installing Kitty..." if [[ "${OS}" == "Darwin" ]]; then - curl -fsSL https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin + download_and_run https://sw.kovidgoyal.net/kitty/installer.sh else - curl -fsSL https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin launch=n + download_and_run https://sw.kovidgoyal.net/kitty/installer.sh launch=n install_kitty_linux_desktop fi } @@ -92,7 +92,14 @@ install_nerd_fonts() { need_cmd curl need_cmd unzip - local font_version="3.3.0" + local font_version + font_version="$(curl -fsSL https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest \ + | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p' | head -n 1)" + if [[ -z "${font_version}" ]]; then + echo "Error: failed to resolve latest Nerd Fonts release" + exit 1 + fi + echo "Latest Nerd Fonts version: ${font_version}" echo "Installing Nerd Fonts..." for font in JetBrainsMono NerdFontsSymbolsOnly; do diff --git a/install/lib/common.sh b/install/lib/common.sh index 13a5542..b5d11b3 100644 --- a/install/lib/common.sh +++ b/install/lib/common.sh @@ -59,6 +59,12 @@ ensure_local_bin_path() { install_fzf() { local local_bin_dir="${HOME}/.local/bin" + local fzf_target="$HOME/.fzf/bin/fzf" + local fzf_link="${local_bin_dir}/fzf" + + if [[ -L "${fzf_link}" && "$(readlink "${fzf_link}")" == "${fzf_target}" && -x "${fzf_target}" ]]; then + return + fi if command -v fzf >/dev/null 2>&1; then return @@ -73,5 +79,45 @@ install_fzf() { "$HOME/.fzf/install" --bin --no-update-rc mkdir -p "${local_bin_dir}" - ln -sf "$HOME/.fzf/bin/fzf" "${local_bin_dir}/fzf" + ln -sf "${fzf_target}" "${fzf_link}" +} + +# sha256_cmd prints the command to use for sha256 verification. +sha256_cmd() { + if command -v sha256sum >/dev/null 2>&1; then + echo "sha256sum" + elif command -v shasum >/dev/null 2>&1; then + echo "shasum -a 256" + else + echo "Error: need sha256sum or shasum to verify checksums." >&2 + exit 1 + fi +} + +# verify_sha256 +verify_sha256() { + local file="$1" + local expected="$2" + local actual + actual="$($(sha256_cmd) "${file}" | awk '{print $1}')" + if [[ "${actual}" != "${expected}" ]]; then + echo "Error: checksum mismatch for ${file}" >&2 + echo " expected: ${expected}" >&2 + echo " actual: ${actual}" >&2 + exit 1 + fi +} + +# download_and_run [args...] — downloads to a temp file, runs it, cleans up. +download_and_run() { + local url="$1" + shift + need_cmd curl + local tmp rc=0 + tmp="$(mktemp)" + curl -fsSL "${url}" -o "${tmp}" + chmod +x "${tmp}" + sh "${tmp}" "$@" || rc=$? + rm -f "${tmp}" + return "${rc}" } diff --git a/install/nvim-bin.sh b/install/nvim-bin.sh index b054bed..a7ee956 100755 --- a/install/nvim-bin.sh +++ b/install/nvim-bin.sh @@ -86,7 +86,11 @@ install_linux_deps() { clang \ libclang-dev - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + local rustup_tmp + rustup_tmp="$(mktemp)" + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o "${rustup_tmp}" + sh "${rustup_tmp}" -y + rm -f "${rustup_tmp}" . "$HOME/.cargo/env" cargo install --locked tree-sitter-cli diff --git a/install/nvim.sh b/install/nvim.sh index f850d5d..7283319 100755 --- a/install/nvim.sh +++ b/install/nvim.sh @@ -17,7 +17,12 @@ install_nvim_config() { } echo "Installing Neovim config..." - rm -rf "${CONFIG_DIR}" + if [[ -d "${CONFIG_DIR}" ]]; then + local backup_dir + backup_dir="${CONFIG_DIR}.bak.$(date +%Y%m%d%H%M%S)" + echo "Backing up existing config to ${backup_dir}" + mv "${CONFIG_DIR}" "${backup_dir}" + fi mkdir -p "$(dirname "${CONFIG_DIR}")" cp -R "${NVIM_SOURCE_DIR}" "${CONFIG_DIR}" } diff --git a/install/starship.sh b/install/starship.sh index aa5b56f..597b16e 100755 --- a/install/starship.sh +++ b/install/starship.sh @@ -27,7 +27,7 @@ install_starship() { brew_install starship else need_cmd curl - curl -fsSL https://starship.rs/install.sh | sh -s -- -y + download_and_run https://starship.rs/install.sh -y fi } diff --git a/install/zk.sh b/install/zk.sh index 1458899..92d4b29 100755 --- a/install/zk.sh +++ b/install/zk.sh @@ -4,6 +4,8 @@ set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)" +OS="$(uname -s)" + # shellcheck source=install/zk-bin.sh source "${SCRIPT_DIR}/zk-bin.sh"