From 40758483f57447972bc9b1e452c624a50401e8c3 Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 15:23:42 +0100 Subject: [PATCH 01/12] feat: add markdownlint and shellcheck to pre-commit hooks --- .markdownlint.yml | 6 ++++++ .pre-commit-config.yaml | 12 ++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 .markdownlint.yml diff --git a/.markdownlint.yml b/.markdownlint.yml new file mode 100644 index 00000000..0541d71c --- /dev/null +++ b/.markdownlint.yml @@ -0,0 +1,6 @@ +--- +# Base Markdownlint configuration +default: true +# ignore line length rule +MD013: false +MD024: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f2fcb336..17f45693 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,3 +15,15 @@ repos: - id: mixed-line-ending - id: trailing-whitespace exclude: \.md$ + - repo: https://github.com/DavidAnson/markdownlint-cli2 + rev: v0.20.0 + hooks: + - id: markdownlint-cli2 + files: \.md$ + exclude: /copilot-instructions\.md + - repo: https://github.com/koalaman/shellcheck-precommit + rev: v0.11.0 + hooks: + - id: shellcheck + args: ["--severity=error", "--exclude=SC2148,SC2139"] + exclude: \.zsh$ From b426059bc6dbd838a50b0a38c3c0d162a572e9a9 Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 16:00:53 +0100 Subject: [PATCH 02/12] fix: resolve all pre-commit hooks errors --- .assets/config/bash_cfg/functions.sh | 2 +- .assets/provision/fix_azcli_certs.sh | 2 +- .assets/provision/fix_certifi_certs.sh | 4 ++-- .assets/provision/setup_gh_repos.sh | 2 +- ...le_user_zsh.sh => setup_profile_user_zsh.zsh} | 2 +- .assets/scripts/linux_setup.sh | 16 ++++++++-------- wsl/wsl_setup.ps1 | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) rename .assets/provision/{setup_profile_user_zsh.sh => setup_profile_user_zsh.zsh} (98%) diff --git a/.assets/config/bash_cfg/functions.sh b/.assets/config/bash_cfg/functions.sh index 1c19ef36..68b2cf6b 100644 --- a/.assets/config/bash_cfg/functions.sh +++ b/.assets/config/bash_cfg/functions.sh @@ -31,7 +31,7 @@ function sysinfo { # print user@host header printf "\e[1;34m$(id -un)\e[0m@\e[1;34m$([ -n "$HOSTNAME" ] && printf "$HOSTNAME" || printf "$NAME")\e[0m\n" - USER_HOST="$(id -un)@$([ -n "HOSTNAME" ] && printf "$HOSTNAME" || printf "$NAME")" + USER_HOST="$(id -un)@$([ -n "$HOSTNAME" ] && printf "$HOSTNAME" || printf "$NAME")" printf '%0.s-' $(seq 1 ${#USER_HOST}) # print system properties printf "$SYS_PROP\n" diff --git a/.assets/provision/fix_azcli_certs.sh b/.assets/provision/fix_azcli_certs.sh index 3f2a9715..e4ad6b49 100755 --- a/.assets/provision/fix_azcli_certs.sh +++ b/.assets/provision/fix_azcli_certs.sh @@ -50,7 +50,7 @@ cert_count=0 # track unique serials that have been added across all certify files declare -A added_serials=() # iterate over certify files -for path in ${cert_paths[@]}; do +for path in "${cert_paths[@]}"; do serial=$(openssl x509 -in "$path" -noout -serial -nameopt RFC2253 | cut -d= -f2) if ! grep -qw "$serial" "$CERTIFY_CRT"; then echo "$(openssl x509 -in $path -noout -subject -nameopt RFC2253 | sed 's/\\//g')" >&2 diff --git a/.assets/provision/fix_certifi_certs.sh b/.assets/provision/fix_certifi_certs.sh index 08aaa993..532d87f1 100755 --- a/.assets/provision/fix_certifi_certs.sh +++ b/.assets/provision/fix_certifi_certs.sh @@ -63,10 +63,10 @@ if [ -z "$certify_paths" ]; then fi # iterate over certify files -for certify in ${certify_paths[@]}; do +for certify in "${certify_paths[@]}"; do echo "${certify//$HOME/\~}" >&2 # iterate over installed certificates - for path in ${cert_paths[@]}; do + for path in "${cert_paths[@]}"; do serial=$(openssl x509 -in "$path" -noout -serial -nameopt RFC2253 | cut -d= -f2) if ! grep -qw "$serial" "$certify"; then # add certificate to array diff --git a/.assets/provision/setup_gh_repos.sh b/.assets/provision/setup_gh_repos.sh index cb938b7f..3a30cde1 100755 --- a/.assets/provision/setup_gh_repos.sh +++ b/.assets/provision/setup_gh_repos.sh @@ -37,7 +37,7 @@ fi # *clone repositories and add them to workspace file cd ~/source/repos -for repo in ${gh_repos[@]}; do +for repo in "${gh_repos[@]}"; do IFS='/' read -ra gh_path <<<"$repo" mkdir -p "${gh_path[0]}" pushd "${gh_path[0]}" >/dev/null diff --git a/.assets/provision/setup_profile_user_zsh.sh b/.assets/provision/setup_profile_user_zsh.zsh similarity index 98% rename from .assets/provision/setup_profile_user_zsh.sh rename to .assets/provision/setup_profile_user_zsh.zsh index 339ccb8f..0cd7ecc0 100755 --- a/.assets/provision/setup_profile_user_zsh.sh +++ b/.assets/provision/setup_profile_user_zsh.zsh @@ -1,6 +1,6 @@ #!/usr/bin/env zsh : ' -.assets/provision/setup_profile_user_zsh.sh +.assets/provision/setup_profile_user_zsh.zsh ' # path variables PROFILE_PATH='/etc/profile.d' diff --git a/.assets/scripts/linux_setup.sh b/.assets/scripts/linux_setup.sh index 66eefa11..e922c46d 100755 --- a/.assets/scripts/linux_setup.sh +++ b/.assets/scripts/linux_setup.sh @@ -54,11 +54,11 @@ while IFS= read -r line; do array+=("$line") done <<<"$distro_check" # add corresponding scopes -grep -qw 'az' <<<${array[@]} && array+=(python) || true -grep -qw 'k8s_dev' <<<${array[@]} && array+=(k8s_base) || true -grep -qw 'k8s_ext' <<<${array[@]} && array+=(docker) && array+=(k8s_base) && array+=(k8s_dev) || true -grep -qw 'pwsh' <<<${array[@]} && array+=(shell) || true -grep -qw 'zsh' <<<${array[@]} && array+=(shell) || true +grep -qw 'az' <<<"${array[@]}" && array+=(python) || true +grep -qw 'k8s_dev' <<<"${array[@]}" && array+=(k8s_base) || true +grep -qw 'k8s_ext' <<<"${array[@]}" && array+=(docker) && array+=(k8s_base) && array+=(k8s_dev) || true +grep -qw 'pwsh' <<<"${array[@]}" && array+=(shell) || true +grep -qw 'zsh' <<<"${array[@]}" && array+=(shell) || true # add oh_my_posh scope if necessary if [[ -n "$omp_theme" || -f /usr/bin/oh-my-posh ]]; then array+=(oh_my_posh) @@ -107,7 +107,7 @@ fi printf "\e[96minstalling base packages...\e[0m\n" sudo .assets/provision/install_base.sh $user # update pixi packages if pixi is installed -if grep -qw 'pixi' <<<${array[@]}; then +if grep -qw 'pixi' <<<"${array[@]}"; then printf "\e[96mupdating pixi packages...\e[0m\n" "$HOME/.pixi/bin/pixi" global update fi @@ -133,7 +133,7 @@ else .assets/provision/setup_gh_ssh.sh >/dev/null fi -for sc in ${scope_arr[@]}; do +for sc in "${scope_arr[@]}"; do case $sc in az) printf "\e[96minstalling azure cli...\e[0m\n" @@ -232,7 +232,7 @@ for sc in ${scope_arr[@]}; do printf "\e[96minstalling zsh...\e[0m\n" sudo .assets/provision/install_zsh.sh printf "\e[96msetting up zsh profile for current user...\e[0m\n" - .assets/provision/setup_profile_user_zsh.sh + .assets/provision/setup_profile_user_zsh.zsh ;; esac done diff --git a/wsl/wsl_setup.ps1 b/wsl/wsl_setup.ps1 index 047b6cbe..139a2f18 100644 --- a/wsl/wsl_setup.ps1 +++ b/wsl/wsl_setup.ps1 @@ -665,7 +665,7 @@ process { wsl.exe --distribution $Distro --user root --exec .assets/provision/install_zsh.sh # setup profiles Show-LogContext 'setting up zsh profile for current user' - wsl.exe --distribution $Distro --exec .assets/provision/setup_profile_user_zsh.sh + wsl.exe --distribution $Distro --exec .assets/provision/setup_profile_user_zsh.zsh continue } } From 9f9a9bf61b626c1dfeb6ceb47c261ac386b59c29 Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 16:55:22 +0100 Subject: [PATCH 03/12] feat(docs): AGENTS.md --- AGENTS.md | 343 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..4b89057f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,343 @@ +# Linux Setup Scripts Repository + +This repository contains automation scripts for provisioning and configuring Linux systems, with **primary focus on Windows Subsystem for Linux (WSL)** setup and management. Secondary functionality includes support for VMs (Vagrant), bare-metal installations, and distroboxes. + +## Project Overview + +**Primary Focus**: Windows Subsystem for Linux (WSL) setup and configuration +**Main Orchestration Script**: `wsl/wsl_setup.ps1` - orchestrates the entire WSL setup process using scripts from `.assets/provision/` +**Primary Languages**: Shell/Bash (93+ scripts), PowerShell 7.4+ (12+ scripts + 2 modules) +**Supported Distros**: Fedora/RHEL, Debian/Ubuntu, Arch, OpenSUSE, Alpine +**Deployment Targets**: WSL (primary), Vagrant (secondary), bare-metal Linux (secondary), distroboxes (secondary) +**Key Features**: 60+ tool installation scripts, cross-platform PowerShell modules, oh-my-posh configurations + +## Quick Reference + +**WSL Setup**: Run `wsl/wsl_setup.ps1` to orchestrate complete WSL distro setup (see `docs/wsl_setup.md` for details) +**When committing changes**: Run `prek run --all-files` to check for linting issues before committing +**Common linting issues**: Add blank lines around markdown headings/lists/code fences, ensure proper spacing +**Installation scripts**: Most `.assets/provision/install_*.sh` scripts require root and will install tools system-wide + +## Repository Structure + +```text +wsl/ # WSL-specific PowerShell management scripts (PRIMARY FOCUS) +├── wsl_setup.ps1 # MAIN ORCHESTRATION SCRIPT - orchestrates entire WSL setup +├── wsl_install.ps1 # Install WSL distros +├── wsl_*.ps1 # Other WSL management utilities (12 files total) +.assets/ # All helper scripts and assets +├── provision/ # Core provisioning scripts (60+ installation/setup scripts) +│ # Used by wsl_setup.ps1 for installing tools and configuring system +├── config/ # Shell configurations (bash, pwsh, oh-my-posh) +├── scripts/ # Utility scripts (linux_setup.sh for bare-metal/VM setup) +├── docker/ # Dockerfiles (standard + Alpine) +├── playbooks/ # Ansible playbooks (4 files) +├── tools/ # Benchmarking tools +└── trigger/ # External trigger scripts +modules/ # PowerShell modules (InstallUtils, SetupUtils) +vagrant/ # Vagrant configurations (secondary functionality) +docs/ # Documentation (wsl_setup.md, vagrant.md, etc.) +``` + +## Build/Test Commands + +**Note**: This repository uses pre-commit hooks configured in the `.pre-commit-config.yaml` file. +You may get pre-commit hook errors while committing changes that need to be resolved before proceeding. + +### Pre-commit Hooks + +The repository uses pre-commit hooks to enforce code quality and consistency. The hooks are defined in the `.pre-commit-config.yaml` file and include: + +- [pre-commit/pre-commit-hooks](https://github.com/pre-commit/pre-commit-hooks) + - check-executables-have-shebangs + Checks that non-binary executables have a proper shebang. + - check-shebang-scripts-are-executable + Checks that scripts with shebangs are executable. + - end-of-file-fixer + Makes sure files end in a newline and only a newline. + - mixed-line-ending + Replaces or checks mixed line ending. + - trailing-whitespace + Trims trailing whitespace. + - exclude: `*.md` files (double trailing whitespace is used for line breaks in Markdown) +- [DavidAnson/markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) + - markdownlint-cli2 + A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the markdownlint library. + - exclude: `/copilot-instructions.md` +- [koalaman/shellcheck-precommit](https://github.com/koalaman/shellcheck-precommit) + - shellcheck + A static analysis tool for shell scripts. It provides warnings and suggestions for bash/sh shell scripts. + - exclude: `*.zsh` files (ShellCheck doesn't support zsh) +- [hooks/gremlins](tests/hooks/gremlins.py): + - gremlins-check + Detect gremlins / unwanted Unicode characters. + Inspired by [Gremlins tracker for Visual Studio Code](https://github.com/nhoizey/vscode-gremlins) + +**Exclusions**: + +- markdownlint: `/copilot-instructions.md` +- shellcheck: `*.zsh` files (ShellCheck doesn't support zsh) +- trailing-whitespace: `*.md` files + +**Common fixes needed**: + +- Markdownlint MD022: Add blank line before/after headings +- Markdownlint MD031: Add blank line before/after code fences +- Markdownlint MD032: Add blank line before/after lists +- Markdownlint MD040: Specify language for fenced code blocks + +### Development Workflow + +1. Make code changes following the style guidelines below +2. Run `prek run --all-files` to validate changes +3. Fix any reported issues (agents should fix these automatically) +4. Commit changes (pre-commit hooks will run automatically if installed) + +### Docker Build + +```bash +# Build Docker image +.assets/docker/build_docker.sh + +# GitHub Actions handles automated Docker builds (see .github/workflows/build_docker.yml) +``` + +### Vagrant Testing + +**Note**: Vagrant tests are not required as Vagrant development has been stopped. + +### Shell Script Testing + +```bash +# Test individual installation scripts (most require root) +sudo .assets/provision/install_kubectl.sh + +# Test without output +sudo .assets/provision/install_kubectl.sh >/dev/null + +# Test with specific version +sudo .assets/provision/install_terraform.sh 1.6.0 +``` + +### PowerShell Module Testing + +```powershell +# Import modules for testing +Import-Module ./modules/InstallUtils/InstallUtils.psd1 +Import-Module ./modules/SetupUtils/SetupUtils.psd1 + +# Test specific functions +Get-Command -Module InstallUtils, SetupUtils +``` + +## Code Style Guidelines + +### Shell/Bash Scripts (**.sh) + +#### Formatting + +- **Target**: Bash 5.0+, POSIX-compliant, cross-distro compatible +- **Shebang**: `#!/usr/bin/env bash` +- **Indentation**: 2 spaces (NO tabs) +- **Line length**: ≤ 120 characters +- **Error handling**: Use `set -euo pipefail` unless explicitly avoided +- **Spacing**: Spaces around operators and after commas +- **Command substitution**: Use `$(...)`, never backticks + +#### Naming Conventions + +- **Functions**: `snake_case` (e.g., `install_kubectl`, `setup_profile`) +- **Variables**: `snake_case` lowercase for locals, `UPPERCASE` for constants/env vars +- **Private functions**: Prefix with `_` (e.g., `_helper_function`) + +#### Variable Handling + +- **Always quote**: `"$var"` in command arguments +- **Local scope**: Prefer `local` for function variables +- **Arrays**: Use arrays for lists to avoid word splitting +- **Parameter forwarding**: Use `"$@"` to forward all arguments + +#### Function Design + +- Single responsibility per function +- Brief comment above each function explaining purpose +- Use `return` or exit codes for error signaling (NOT `echo`) +- Avoid global variables unless necessary +- Pass parameters explicitly + +#### Common Patterns + +```bash +# Distro detection (standard pattern) +SYS_ID="$(sed -En '/^ID.*(alpine|arch|fedora|debian|ubuntu|opensuse).*/{s//\1/;p;q}' /etc/os-release)" + +# Root check (standard pattern) +if [ $EUID -ne 0 ]; then + printf '\e[31;1mRun the script as root.\e[0m\n' >&2 + exit 1 +fi + +# Version checking with retry +retry_count=0 +while [ -z "$REL" ]; do + REL=$(curl -sLk https://example.com/latest) + ((retry_count++)) + [ $retry_count -eq 10 ] && break +done + +# Associative arrays for state +declare -A state=( + ["key1"]="value1" + ["key2"]=$(command) +) +``` + +### PowerShell Scripts (**.ps1) + +#### Formatting + +- **Target**: PowerShell 7.4+, cross-platform (testable on Linux) +- **Indentation**: 4 spaces (NO tabs) +- **Style**: One True Brace Style (OTBS) + - Opening brace `{` on same line as statement + - Closing brace `}` on own line + - Multi-condition statements: all conditions + `{` on same line + - Block body always on separate lines (never inline) +- **Long arrays**: Use `@(...)` with one element per line if >120 chars + +#### Naming Conventions + +- **Functions**: `Verb-Noun` PascalCase (use approved PowerShell verbs only) +- **Parameters**: `PascalCase` (e.g., `$TargetDir`, `$MaxRetries`) +- **Local variables**: `camelCase` (e.g., `$retryCount`, `$exit`) +- **Properties**: `camelCase` + +#### Documentation + +- Always include comment-based help with: + - `.SYNOPSIS` + - `.PARAMETER` (for each parameter) + - `.EXAMPLE` +- Ensure `Get-Help` compatibility for all public functions + +#### Function Design + +- Single responsibility per function +- Use parameter splatting for >3 parameters +- Consistent error handling patterns +- Appropriate exception handling with try/catch + +#### Common Patterns + +```powershell +# Standard function template +function Invoke-SomeAction { + [CmdletBinding()] + param ( + [Parameter(Mandatory, Position = 0)] + [string]$TargetPath, + + [Parameter(HelpMessage = 'Number of retries')] + [int]$MaxRetries = 10 + ) + + # Use camelCase for local variables + $retryCount = 0 + + # OTBS style for conditionals + if ($condition) { + # code + } elseif ($otherCondition) { + # code + } else { + # code + } +} +``` + +## Import Conventions + +### Bash + +- **Dotsource shared functions**: `. .assets/provision/source.sh` +- **Profile sourcing**: `. "$HOME/.bashrc"` or `. /etc/profile.d/script.sh` + +### PowerShell + +- **Module imports**: `Import-Module ./modules/ModuleName/ModuleName.psd1` +- **Dot-sourcing**: `. "$PSScriptRoot/Functions/common.ps1"` + +## Error Handling + +### Bash + +- Use `set -euo pipefail` for strict error handling +- Check command success: `command || handle_error` +- Exit codes: Return 0 for success, non-zero for errors +- Error messages to stderr: `echo "error" >&2` +- Color-coded output: `\e[31;1m` (red), `\e[32m` (green), `\e[92m` (bright green) + +### PowerShell + +- Use try/catch for exception handling +- Check specific exception types (e.g., `[System.IO.IOException]`) +- Use `-ErrorAction Stop` to make cmdlets throw +- Write errors: `Write-Error`, verbose: `Write-Verbose` +- Retry pattern: See `Invoke-CommandRetry` in `modules/InstallUtils/Functions/common.ps1` + +## Type Usage + +### Bash + +- Prefer typed declarations when possible: `declare -i` (integer), `declare -a` (array), `declare -A` (associative) +- Use `[[ ]]` for conditionals (more robust than `[ ]`) +- Regex matching: `[[ "$var" =~ ^pattern$ ]]` + +### PowerShell + +- Always specify parameter types: `[string]`, `[int]`, `[switch]`, etc. +- Use `[CmdletBinding()]` for advanced functions +- Output types: `[OutputType([string])]` when appropriate +- Generic collections: `[System.Collections.Generic.List[string]]::new()` + +## Special Considerations + +### WSL Primary Focus + +- **Main script**: `wsl/wsl_setup.ps1` orchestrates complete WSL distro setup +- **Provisioning scripts**: Located in `.assets/provision/` are called by wsl_setup.ps1 +- **WSL-specific features**: PowerShell scripts in `wsl/` manage WSL configuration, networking, systemd, certificates +- **Windows host interaction**: WSL scripts often bridge between Linux distro and Windows host + +### Cross-Platform Compatibility + +- Shell scripts must work across Fedora, Debian, Ubuntu, Arch, OpenSUSE, Alpine +- PowerShell must be testable on Linux (use cross-platform cmdlets) +- Avoid distro-specific commands without fallbacks + +### Root vs User Context + +- Most `.assets/provision/install_*.sh` scripts require root (check with `$EUID -ne 0`) +- Setup scripts (`setup_*.sh`) typically run as user +- WSL PowerShell scripts often interact with Windows host + +### Path Conventions + +- Scripts reference `.assets/` relative paths +- User-specific: `$HOME/.local/bin`, `$HOME/.config` +- System-wide: `/usr/bin`, `/usr/local/bin`, `/etc/profile.d` + +## Enforcement + +All guidelines are **mandatory requirements**. When modifying code: + +1. Follow ALL standards without requiring explicit reminders +2. Update existing code to meet standards when modifying related sections +3. Flag potential violations in your responses + +## Additional Documentation + +- WSL setup: `docs/wsl_setup.md` (primary focus - comprehensive WSL setup guide) +- WSL scripts reference: `docs/wsl_scripts.md` (detailed WSL management scripts documentation) +- Vagrant provisioning: `docs/vagrant.md` (secondary functionality) +- Repository scoped instructions: `.github/copilot-instructions.md` From 5f0563891efc84b84876bca40440f4bca134dabf Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 17:46:45 +0100 Subject: [PATCH 04/12] feat: add strict error handling to source.sh and safe scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add set -euo pipefail to source.sh library (critical - sourced by 37 scripts) - Fix parameter handling in source.sh functions: - download_file() and get_gh_release_latest(): declare $param="$2" → declare $param="${2:-}" - Initialize local variables with empty defaults: local owner='' instead of local owner - Fix download_url variable in get_gh_release_latest() - initialize before use - Add set -euo pipefail to 6 safe bash scripts (already used ${1:-} pattern): - install_distrobox.sh, install_docker.sh, install_edge.sh - install_xrdp.sh, setup_profile_allusers.sh, install_azurecli_uv.sh - Add set -eu to 1 POSIX sh script: install_base.sh (no pipefail - not POSIX) - Move set -e statements to appear after comment blocks with blank line for readability - All scripts tested and validated with shellcheck Phase 1 of 4: source.sh library + scripts with safe parameter handling Affected: 8 files (source.sh + 7 provision scripts) --- .assets/provision/install_azurecli_uv.sh | 2 ++ .assets/provision/install_base.sh | 2 ++ .assets/provision/install_distrobox.sh | 2 ++ .assets/provision/install_docker.sh | 2 ++ .assets/provision/install_edge.sh | 2 ++ .assets/provision/install_xrdp.sh | 2 ++ .assets/provision/setup_profile_allusers.sh | 2 ++ .assets/provision/source.sh | 40 ++++++++++++--------- 8 files changed, 38 insertions(+), 16 deletions(-) diff --git a/.assets/provision/install_azurecli_uv.sh b/.assets/provision/install_azurecli_uv.sh index a491c690..e991a42f 100755 --- a/.assets/provision/install_azurecli_uv.sh +++ b/.assets/provision/install_azurecli_uv.sh @@ -3,6 +3,8 @@ .assets/provision/install_azurecli_uv.sh .assets/provision/install_azurecli_uv.sh --fix_certify true ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_base.sh b/.assets/provision/install_base.sh index 66ccc3da..c0d1d757 100755 --- a/.assets/provision/install_base.sh +++ b/.assets/provision/install_base.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_base.sh $(id -un) ' +set -eu + if [ $(id -u) -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_distrobox.sh b/.assets/provision/install_distrobox.sh index 667059a9..1db51e4d 100755 --- a/.assets/provision/install_distrobox.sh +++ b/.assets/provision/install_distrobox.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_distrobox.sh $(id -un) ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_docker.sh b/.assets/provision/install_docker.sh index c8498f80..3ddeccee 100755 --- a/.assets/provision/install_docker.sh +++ b/.assets/provision/install_docker.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_docker.sh $(id -un) ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_edge.sh b/.assets/provision/install_edge.sh index 1b9a3fc8..98415616 100755 --- a/.assets/provision/install_edge.sh +++ b/.assets/provision/install_edge.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_edge.sh $(id -un) ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_xrdp.sh b/.assets/provision/install_xrdp.sh index f266be75..d3156e9f 100755 --- a/.assets/provision/install_xrdp.sh +++ b/.assets/provision/install_xrdp.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_xrdp.sh $(id -un) ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/setup_profile_allusers.sh b/.assets/provision/setup_profile_allusers.sh index 0788776c..59e0e27e 100755 --- a/.assets/provision/setup_profile_allusers.sh +++ b/.assets/provision/setup_profile_allusers.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/setup_profile_allusers.sh $(id -un) ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/source.sh b/.assets/provision/source.sh index 2b0bc467..5dbeb8cf 100755 --- a/.assets/provision/source.sh +++ b/.assets/provision/source.sh @@ -2,7 +2,15 @@ : ' . .assets/provision/source.sh ' -# *function to log in to GitHub as the specified user using the gh CLI + +# *Helper to enable strict mode in the current shell when explicitly requested. +# This file is intended to be dot-sourced, so we avoid changing shell options +# implicitly on import. Call enable_strict_mode from scripts that want it. +enable_strict_mode() { + set -euo pipefail +} + +# *Function to log in to GitHub as the specified user using the gh CLI # Usage: login_gh_user # logs in the current user # Usage: login_gh_user -u $user # logs in the specified user # Usage: login_gh_user -u $user -k # logs in the specified user admin:public_key scope @@ -100,16 +108,16 @@ login_gh_user() { return 0 } -# *function to download file from specified uri +# *Function to download file from specified uri download_file() { # initialize local variables used as named parameters - local uri - local target_dir + local uri='' + local target_dir='' # parse named parameters while [ $# -gt 0 ]; do if [[ $1 == *"--"* ]]; then param="${1/--/}" - declare $param="$2" + declare $param="${2:-}" fi shift done @@ -154,18 +162,18 @@ download_file() { return 1 } -# *function to get the latest release from the specified GitHub repo +# *Function to get the latest release from the specified GitHub repo get_gh_release_latest() { # initialize local variables used as named parameters - local owner - local repo - local asset - local regex + local owner='' + local repo='' + local asset='' + local regex='' # parse named parameters while [ $# -gt 0 ]; do if [[ $1 == *"--"* ]]; then param="${1/--/}" - declare $param="$2" + declare $param="${2:-}" fi shift done @@ -173,8 +181,8 @@ get_gh_release_latest() { # define local variables local max_retries=8 local retry_count=0 - local api_response - local token + local api_response='' + local token='' if [[ -z "$owner" || -z "$repo" ]]; then printf "\e[31mError: The \e[4mowner\e[24m and \e[4mrepo\e[24m parameters are required.\e[0m\n" >&2 @@ -229,15 +237,15 @@ get_gh_release_latest() { # Check if 'tag_name' exists if echo "$api_response" | jq -e '.tag_name | select(. != null and . != "")' >/dev/null; then + local tag_name download_url rel tag_name="$(echo "$api_response" | jq -r '.tag_name')" - rel="$(echo $tag_name | sed -E 's/[^0-9]*([0-9]+\.[0-9]+\.[0-9]+)/\1/')" + rel="$(echo "$tag_name" | sed -E 's/[^0-9]*([0-9]+\.[0-9]+\.[0-9]+)/\1/')" if [ -n "$rel" ]; then + download_url='' if [ -n "$asset" ]; then download_url="$(echo "$api_response" | jq -r ".assets[] | select(.name == \"$asset\") | .browser_download_url")" elif [ -n "$regex" ]; then download_url="$(echo "$api_response" | jq -r ".assets[] | select(.name | test(\"$regex\")) | .browser_download_url")" - else - unset download_url fi # return the version and download URL if available if [ -n "$download_url" ]; then From cb81fb5543e9e30b4b71f2485b2640950a26c2d3 Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 17:46:55 +0100 Subject: [PATCH 05/12] feat: add strict error handling to standard install scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add set -euo pipefail to 33 install_*.sh scripts with version parameter pattern - Fix parameter handling: REL=$1 → REL=${1:-} in all 33 scripts to handle unset parameters safely - Fix additional unbound variable bugs in source.sh: - Initialized local variables with empty defaults: local owner='' instead of local owner - Fixed download_url variable in get_gh_release_latest() - was referenced before initialization - Changed unset download_url → download_url='' initialization pattern - Move set -e statements to appear after comment blocks with blank line for readability - All scripts tested and validated with shellcheck Phase 2 of 4: Standard install scripts with version parameters Affected: 33 install_*.sh scripts + source.sh improvements Scripts: argorolloutscli, azcopy, bat, brew, cilium, crictl, etcdctl, exa, eza, fastfetch, flux, fonts_cascadiacode, helm, k3d, k9s, kind, kubecolor, kubectl, kubectx, kubelogin, kubeseal, kustomize, minikube, nerdctl, omp, pwsh, ripgrep, terraform, terrascan, tflint, tfswitch, uv, yq --- .assets/provision/install_argorolloutscli.sh | 4 +++- .assets/provision/install_azcopy.sh | 4 +++- .assets/provision/install_bat.sh | 4 +++- .assets/provision/install_brew.sh | 4 +++- .assets/provision/install_cilium.sh | 4 +++- .assets/provision/install_crictl.sh | 4 +++- .assets/provision/install_etcdctl.sh | 4 +++- .assets/provision/install_exa.sh | 4 +++- .assets/provision/install_eza.sh | 4 +++- .assets/provision/install_fastfetch.sh | 4 +++- .assets/provision/install_flux.sh | 4 +++- .assets/provision/install_fonts_cascadiacode.sh | 4 +++- .assets/provision/install_helm.sh | 4 +++- .assets/provision/install_k3d.sh | 4 +++- .assets/provision/install_k9s.sh | 4 +++- .assets/provision/install_kind.sh | 4 +++- .assets/provision/install_kubecolor.sh | 4 +++- .assets/provision/install_kubectl.sh | 4 +++- .assets/provision/install_kubectx.sh | 4 +++- .assets/provision/install_kubelogin.sh | 4 +++- .assets/provision/install_kubeseal.sh | 6 ++++-- .assets/provision/install_kustomize.sh | 4 +++- .assets/provision/install_minikube.sh | 4 +++- .assets/provision/install_nerdctl.sh | 4 +++- .assets/provision/install_omp.sh | 6 ++++-- .assets/provision/install_pwsh.sh | 4 +++- .assets/provision/install_ripgrep.sh | 4 +++- .assets/provision/install_terraform.sh | 4 +++- .assets/provision/install_terrascan.sh | 4 +++- .assets/provision/install_tflint.sh | 4 +++- .assets/provision/install_tfswitch.sh | 4 +++- .assets/provision/install_uv.sh | 4 +++- .assets/provision/install_yq.sh | 4 +++- 33 files changed, 101 insertions(+), 35 deletions(-) diff --git a/.assets/provision/install_argorolloutscli.sh b/.assets/provision/install_argorolloutscli.sh index 3a7901a1..52951e69 100755 --- a/.assets/provision/install_argorolloutscli.sh +++ b/.assets/provision/install_argorolloutscli.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_argorolloutscli.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='kubectl-argo-rollouts' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'argoproj' --repo 'argo-rollouts')" diff --git a/.assets/provision/install_azcopy.sh b/.assets/provision/install_azcopy.sh index d94f5bc2..2e4944fa 100755 --- a/.assets/provision/install_azcopy.sh +++ b/.assets/provision/install_azcopy.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_azcopy.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -13,7 +15,7 @@ fi # define variables SYS_ID="$(sed -En '/^ID.*(alpine|arch|fedora|debian|ubuntu|opensuse).*/{s//\1/;p;q}' /etc/os-release)" APP='azcopy' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'Azure' --repo 'azure-storage-azcopy')" diff --git a/.assets/provision/install_bat.sh b/.assets/provision/install_bat.sh index a8e1ace0..6474842c 100755 --- a/.assets/provision/install_bat.sh +++ b/.assets/provision/install_bat.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_bat.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -30,7 +32,7 @@ esac . .assets/provision/source.sh # define variables -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'sharkdp' --repo 'bat')" diff --git a/.assets/provision/install_brew.sh b/.assets/provision/install_brew.sh index 563c907e..ad027779 100755 --- a/.assets/provision/install_brew.sh +++ b/.assets/provision/install_brew.sh @@ -3,6 +3,8 @@ # https://docs.brew.sh/Installation .assets/provision/install_brew.sh >/dev/null ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 exit 1 @@ -13,7 +15,7 @@ fi # define variables APP='brew' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'Homebrew' --repo 'brew')" diff --git a/.assets/provision/install_cilium.sh b/.assets/provision/install_cilium.sh index a9c2a96f..4aa1d15b 100755 --- a/.assets/provision/install_cilium.sh +++ b/.assets/provision/install_cilium.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_cilium.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='cilium' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'cilium' --repo 'cilium-cli')" diff --git a/.assets/provision/install_crictl.sh b/.assets/provision/install_crictl.sh index a06a8720..ebd1fb81 100755 --- a/.assets/provision/install_crictl.sh +++ b/.assets/provision/install_crictl.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_crictl.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='crictl' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'kubernetes-sigs' --repo 'cri-tools')" diff --git a/.assets/provision/install_etcdctl.sh b/.assets/provision/install_etcdctl.sh index 0031c4ad..8f7b7452 100755 --- a/.assets/provision/install_etcdctl.sh +++ b/.assets/provision/install_etcdctl.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_etcdctl.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='etcdctl' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'etcd-io' --repo 'etcd')" diff --git a/.assets/provision/install_exa.sh b/.assets/provision/install_exa.sh index 6b93ca67..920dd41e 100755 --- a/.assets/provision/install_exa.sh +++ b/.assets/provision/install_exa.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_exa.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -30,7 +32,7 @@ esac . .assets/provision/source.sh # define variables -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'ogham' --repo 'exa')" diff --git a/.assets/provision/install_eza.sh b/.assets/provision/install_eza.sh index a1d99576..c1bc9ea2 100755 --- a/.assets/provision/install_eza.sh +++ b/.assets/provision/install_eza.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_eza.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -36,7 +38,7 @@ esac . .assets/provision/source.sh # define variables -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'eza-community' --repo 'eza')" diff --git a/.assets/provision/install_fastfetch.sh b/.assets/provision/install_fastfetch.sh index 2951b4fb..78a606c0 100755 --- a/.assets/provision/install_fastfetch.sh +++ b/.assets/provision/install_fastfetch.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_fastfetch.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -27,7 +29,7 @@ esac . .assets/provision/source.sh # define variables -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'fastfetch-cli' --repo 'fastfetch')" diff --git a/.assets/provision/install_flux.sh b/.assets/provision/install_flux.sh index 39697f91..21a21b85 100755 --- a/.assets/provision/install_flux.sh +++ b/.assets/provision/install_flux.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_flux.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='flux' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'fluxcd' --repo 'flux2')" diff --git a/.assets/provision/install_fonts_cascadiacode.sh b/.assets/provision/install_fonts_cascadiacode.sh index 331772d1..0f26bcb9 100755 --- a/.assets/provision/install_fonts_cascadiacode.sh +++ b/.assets/provision/install_fonts_cascadiacode.sh @@ -3,6 +3,8 @@ # sudo .assets/provision/install_fonts_cascadiacode.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi . .assets/provision/source.sh # define variables -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'microsoft' --repo 'cascadia-code')" diff --git a/.assets/provision/install_helm.sh b/.assets/provision/install_helm.sh index 92b77201..cf6d37e9 100755 --- a/.assets/provision/install_helm.sh +++ b/.assets/provision/install_helm.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_helm.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='helm' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'helm' --repo 'helm')" diff --git a/.assets/provision/install_k3d.sh b/.assets/provision/install_k3d.sh index cabee919..e8095637 100755 --- a/.assets/provision/install_k3d.sh +++ b/.assets/provision/install_k3d.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_k3d.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='k3d' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'k3d-io' --repo 'k3d')" diff --git a/.assets/provision/install_k9s.sh b/.assets/provision/install_k9s.sh index 4a71e846..e10a5082 100755 --- a/.assets/provision/install_k9s.sh +++ b/.assets/provision/install_k9s.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_k9s.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='k9s' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'derailed' --repo 'k9s')" diff --git a/.assets/provision/install_kind.sh b/.assets/provision/install_kind.sh index 7863e603..3bfa85a3 100755 --- a/.assets/provision/install_kind.sh +++ b/.assets/provision/install_kind.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_kind.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='kind' -REL=$1 +REL=${1:-} OWNER='kubernetes-sigs' REPO='kind' # get latest release if not provided as a parameter diff --git a/.assets/provision/install_kubecolor.sh b/.assets/provision/install_kubecolor.sh index 905ad707..8195b02c 100755 --- a/.assets/provision/install_kubecolor.sh +++ b/.assets/provision/install_kubecolor.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_kubecolor.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -27,7 +29,7 @@ esac . .assets/provision/source.sh # define variables -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'kubecolor' --repo 'kubecolor')" diff --git a/.assets/provision/install_kubectl.sh b/.assets/provision/install_kubectl.sh index dd7040be..7d854ab0 100755 --- a/.assets/provision/install_kubectl.sh +++ b/.assets/provision/install_kubectl.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_kubectl.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -17,7 +19,7 @@ arch) ;; esac -REL=$1 +REL=${1:-} retry_count=0 # try 10 times to get latest release if not provided as a parameter while [ -z "$REL" ]; do diff --git a/.assets/provision/install_kubectx.sh b/.assets/provision/install_kubectx.sh index 1316a2f7..2ea627f9 100755 --- a/.assets/provision/install_kubectx.sh +++ b/.assets/provision/install_kubectx.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_kubectx.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='kubectx' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'ahmetb' --repo 'kubectx')" diff --git a/.assets/provision/install_kubelogin.sh b/.assets/provision/install_kubelogin.sh index 4cc56aa7..561efb3f 100755 --- a/.assets/provision/install_kubelogin.sh +++ b/.assets/provision/install_kubelogin.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_kubelogin.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='kubelogin' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'Azure' --repo 'kubelogin')" diff --git a/.assets/provision/install_kubeseal.sh b/.assets/provision/install_kubeseal.sh index 5af53410..eea879ef 100755 --- a/.assets/provision/install_kubeseal.sh +++ b/.assets/provision/install_kubeseal.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_kubeseal.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,8 +14,8 @@ fi # define variables APP='kubeseal' -REL=$1 -URL=$2 +REL=${1:-} +URL=${2:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then response="$(get_gh_release_latest --owner 'bitnami-labs' --repo 'sealed-secrets' --regex '^kubeseal-.+-linux-amd64.tar.gz$')" diff --git a/.assets/provision/install_kustomize.sh b/.assets/provision/install_kustomize.sh index e71ed19f..46896e7d 100755 --- a/.assets/provision/install_kustomize.sh +++ b/.assets/provision/install_kustomize.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_kustomize.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='kustomize' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'kubernetes-sigs' --repo 'kustomize')" diff --git a/.assets/provision/install_minikube.sh b/.assets/provision/install_minikube.sh index 6111eea6..6d9f12f1 100755 --- a/.assets/provision/install_minikube.sh +++ b/.assets/provision/install_minikube.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_minikube.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -24,7 +26,7 @@ esac . .assets/provision/source.sh # define variables -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'kubernetes' --repo 'minikube')" diff --git a/.assets/provision/install_nerdctl.sh b/.assets/provision/install_nerdctl.sh index 5d9806dc..8f9f1f28 100755 --- a/.assets/provision/install_nerdctl.sh +++ b/.assets/provision/install_nerdctl.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_nerdctl.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='nerdctl' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'containerd' --repo 'nerdctl')" diff --git a/.assets/provision/install_omp.sh b/.assets/provision/install_omp.sh index 3dd16c37..5e276c2a 100755 --- a/.assets/provision/install_omp.sh +++ b/.assets/provision/install_omp.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_omp.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,8 +14,8 @@ fi # define variables APP='oh-my-posh' -REL=$1 -URL=$2 +REL=${1:-} +URL=${2:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then response="$(get_gh_release_latest --owner 'JanDeDobbeleer' --repo 'oh-my-posh' --asset 'posh-linux-amd64')" diff --git a/.assets/provision/install_pwsh.sh b/.assets/provision/install_pwsh.sh index 6526d7e4..a25fc075 100755 --- a/.assets/provision/install_pwsh.sh +++ b/.assets/provision/install_pwsh.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_pwsh.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='pwsh' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'PowerShell' --repo 'PowerShell')" diff --git a/.assets/provision/install_ripgrep.sh b/.assets/provision/install_ripgrep.sh index e1f5d402..daa703ec 100755 --- a/.assets/provision/install_ripgrep.sh +++ b/.assets/provision/install_ripgrep.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_ripgrep.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -30,7 +32,7 @@ esac . .assets/provision/source.sh # define variables -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'BurntSushi' --repo 'ripgrep')" diff --git a/.assets/provision/install_terraform.sh b/.assets/provision/install_terraform.sh index 32405565..ebf1ad58 100755 --- a/.assets/provision/install_terraform.sh +++ b/.assets/provision/install_terraform.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_terraform.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -30,7 +32,7 @@ esac . .assets/provision/source.sh # define variables -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'hashicorp' --repo 'terraform')" diff --git a/.assets/provision/install_terrascan.sh b/.assets/provision/install_terrascan.sh index 8ef7b589..52ed8c0b 100755 --- a/.assets/provision/install_terrascan.sh +++ b/.assets/provision/install_terrascan.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_terrascan.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='terrascan' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'tenable' --repo 'terrascan')" diff --git a/.assets/provision/install_tflint.sh b/.assets/provision/install_tflint.sh index 1fa49b2f..e225d475 100755 --- a/.assets/provision/install_tflint.sh +++ b/.assets/provision/install_tflint.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_tflint.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='tflint' -REL=$1 +REL=${1:-} OWNER='terraform-linters' REPO='tflint' # get latest release if not provided as a parameter diff --git a/.assets/provision/install_tfswitch.sh b/.assets/provision/install_tfswitch.sh index b0a8ca54..0d4a339b 100755 --- a/.assets/provision/install_tfswitch.sh +++ b/.assets/provision/install_tfswitch.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_tfswitch.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='tfswitch' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'warrensbox' --repo 'terraform-switcher')" diff --git a/.assets/provision/install_uv.sh b/.assets/provision/install_uv.sh index 522369b4..8647dde5 100755 --- a/.assets/provision/install_uv.sh +++ b/.assets/provision/install_uv.sh @@ -2,6 +2,8 @@ : ' .assets/provision/install_uv.sh >/dev/null ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='uv' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'astral-sh' --repo 'uv')" diff --git a/.assets/provision/install_yq.sh b/.assets/provision/install_yq.sh index be653fe5..c04d6af6 100755 --- a/.assets/provision/install_yq.sh +++ b/.assets/provision/install_yq.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_yq.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -12,7 +14,7 @@ fi # define variables APP='yq' -REL=$1 +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then REL="$(get_gh_release_latest --owner 'mikefarah' --repo 'yq')" From b47e579fe91442061a06a50a914e41b77a04674c Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 17:47:03 +0100 Subject: [PATCH 06/12] feat: add strict error handling to complex install and setup scripts - Add set -euo pipefail to remaining install_*.sh scripts (btop, cmatrix, cowsay, fonts_nerd, fzf, gh, gnome, kde, kubectl-convert, nodejs, pixi, podman, prek, smee, zsh) - Add set -eu to remaining POSIX sh scripts (autoexec, fix_secure_path, upgrade_system) - Add set -euo pipefail to certificate fix scripts (fix_azcli_certs, fix_certifi_certs, fix_nodejs_certs) - Fix parameter handling in install_azurecli, install_miniconda, install_miniforge (declare $param="${2:-}") - Add set -euo pipefail to all setup_*.sh scripts (docker_mount, gh_https, gh_repos, gh_ssh, gnome, omp, profile_user, python, ssh) - Add set -euo pipefail to set_*.sh scripts (authorized_keys, ulimits) - Add set -euo pipefail to distro_check.sh utility script - Fix unbound variable issues with ${1:-} and ${2:-} patterns throughout - Initialize local variables in setup_gh_https.sh (gh_cfg='', key='') - Move set -e statements to appear after comment blocks with blank line for readability - All scripts tested and validated with shellcheck Phase 3 of 4: Complex scripts with parameter parsing and setup scripts Affected: 36 files (install, setup, set, fix, utility scripts) --- .assets/provision/autoexec.sh | 1 + .assets/provision/distro_check.sh | 4 +++- .assets/provision/fix_azcli_certs.sh | 2 ++ .assets/provision/fix_certifi_certs.sh | 2 ++ .assets/provision/fix_nodejs_certs.sh | 2 ++ .assets/provision/fix_secure_path.sh | 2 ++ .assets/provision/install_azurecli.sh | 4 +++- .assets/provision/install_btop.sh | 2 ++ .assets/provision/install_cmatrix.sh | 2 ++ .assets/provision/install_cowsay.sh | 2 ++ .assets/provision/install_fonts_nerd.sh | 2 ++ .assets/provision/install_fzf.sh | 2 ++ .assets/provision/install_gh.sh | 2 ++ .assets/provision/install_gnome.sh | 2 ++ .assets/provision/install_kde.sh | 2 ++ .assets/provision/install_kubectl-convert.sh | 2 ++ .assets/provision/install_miniconda.sh | 4 +++- .assets/provision/install_miniforge.sh | 4 +++- .assets/provision/install_nodejs.sh | 2 ++ .assets/provision/install_pixi.sh | 2 ++ .assets/provision/install_podman.sh | 2 ++ .assets/provision/install_prek.sh | 3 +++ .assets/provision/install_smee.sh | 2 ++ .assets/provision/install_zsh.sh | 2 ++ .assets/provision/set_authorized_keys.sh | 5 +++-- .assets/provision/set_ulimits.sh | 4 +++- .assets/provision/setup_docker_mount.sh | 4 +++- .assets/provision/setup_gh_https.sh | 6 +++++- .assets/provision/setup_gh_repos.sh | 6 ++++-- .assets/provision/setup_gh_ssh.sh | 2 ++ .assets/provision/setup_gnome.sh | 2 ++ .assets/provision/setup_omp.sh | 6 ++++-- .assets/provision/setup_profile_user.sh | 2 ++ .assets/provision/setup_python.sh | 2 ++ .assets/provision/setup_ssh.sh | 4 +++- .assets/provision/upgrade_system.sh | 2 ++ 36 files changed, 87 insertions(+), 14 deletions(-) diff --git a/.assets/provision/autoexec.sh b/.assets/provision/autoexec.sh index 7986a51f..dba80b16 100755 --- a/.assets/provision/autoexec.sh +++ b/.assets/provision/autoexec.sh @@ -1,2 +1,3 @@ #!/usr/bin/env sh +set -eu # :script executed on WSL startup via [boot] command defined in wsl.conf diff --git a/.assets/provision/distro_check.sh b/.assets/provision/distro_check.sh index e003e212..a56159a2 100755 --- a/.assets/provision/distro_check.sh +++ b/.assets/provision/distro_check.sh @@ -3,6 +3,8 @@ .assets/provision/distro_check.sh | jq .assets/provision/distro_check.sh array ' +set -euo pipefail + # store the state in an associative array declare -A state=( @@ -43,7 +45,7 @@ is_excluded() { } # check if array parameter is provided -if [ "$1" = 'array' ]; then +if [ "${1:-}" = 'array' ]; then # keys to exclude exclude_keys=('git_user' 'git_email' 'ssh_key' 'systemd' 'wslg' 'wsl_boot' 'gtkd') # print only the keys with true values, excluding specified keys diff --git a/.assets/provision/fix_azcli_certs.sh b/.assets/provision/fix_azcli_certs.sh index e4ad6b49..afeda723 100755 --- a/.assets/provision/fix_azcli_certs.sh +++ b/.assets/provision/fix_azcli_certs.sh @@ -2,6 +2,8 @@ : ' .assets/provision/fix_azcli_certs.sh ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/fix_certifi_certs.sh b/.assets/provision/fix_certifi_certs.sh index 532d87f1..8c0be542 100755 --- a/.assets/provision/fix_certifi_certs.sh +++ b/.assets/provision/fix_certifi_certs.sh @@ -2,6 +2,8 @@ : ' .assets/provision/fix_certifi_certs.sh ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/fix_nodejs_certs.sh b/.assets/provision/fix_nodejs_certs.sh index 88505106..0a79aea3 100755 --- a/.assets/provision/fix_nodejs_certs.sh +++ b/.assets/provision/fix_nodejs_certs.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/fix_nodejs_certs.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/fix_secure_path.sh b/.assets/provision/fix_secure_path.sh index 78401030..13bcdb4b 100755 --- a/.assets/provision/fix_secure_path.sh +++ b/.assets/provision/fix_secure_path.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/fix_secure_path.sh ' +set -eu + if [ $(id -u) -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_azurecli.sh b/.assets/provision/install_azurecli.sh index e47d845e..4933dc39 100755 --- a/.assets/provision/install_azurecli.sh +++ b/.assets/provision/install_azurecli.sh @@ -3,6 +3,8 @@ .assets/provision/install_azurecli.sh .assets/provision/install_azurecli.sh --fix_certify true ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 exit 1 @@ -13,7 +15,7 @@ fix_certify=${fix_certify:-false} while [ $# -gt 0 ]; do if [[ $1 == *"--"* ]]; then param="${1/--/}" - declare $param="$2" + declare $param="${2:-}" fi shift done diff --git a/.assets/provision/install_btop.sh b/.assets/provision/install_btop.sh index 0a4f3876..bf2708ec 100755 --- a/.assets/provision/install_btop.sh +++ b/.assets/provision/install_btop.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_btop.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_cmatrix.sh b/.assets/provision/install_cmatrix.sh index 0de8fbc7..3efd8baa 100755 --- a/.assets/provision/install_cmatrix.sh +++ b/.assets/provision/install_cmatrix.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_cmatrix.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_cowsay.sh b/.assets/provision/install_cowsay.sh index 32e78388..1614e49c 100755 --- a/.assets/provision/install_cowsay.sh +++ b/.assets/provision/install_cowsay.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_cowsay.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_fonts_nerd.sh b/.assets/provision/install_fonts_nerd.sh index f66d7c3b..581f409e 100755 --- a/.assets/provision/install_fonts_nerd.sh +++ b/.assets/provision/install_fonts_nerd.sh @@ -6,6 +6,8 @@ sudo .assets/provision/install_fonts_nerd.sh "RobotoMono" sudo .assets/provision/install_fonts_nerd.sh --uninstall "RobotoMono" sudo .assets/provision/install_fonts_nerd.sh --version ' +set -euo pipefail + __ScriptVersion='0.1' if [ $EUID -ne 0 ]; then diff --git a/.assets/provision/install_fzf.sh b/.assets/provision/install_fzf.sh index 5d3b9a88..2fdf5703 100755 --- a/.assets/provision/install_fzf.sh +++ b/.assets/provision/install_fzf.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_fzf.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_gh.sh b/.assets/provision/install_gh.sh index fe426726..8f751003 100755 --- a/.assets/provision/install_gh.sh +++ b/.assets/provision/install_gh.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_gh.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_gnome.sh b/.assets/provision/install_gnome.sh index 026ca38f..63a5c37e 100755 --- a/.assets/provision/install_gnome.sh +++ b/.assets/provision/install_gnome.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_gnome.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_kde.sh b/.assets/provision/install_kde.sh index 4250cbca..86c9e868 100755 --- a/.assets/provision/install_kde.sh +++ b/.assets/provision/install_kde.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_gnome.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_kubectl-convert.sh b/.assets/provision/install_kubectl-convert.sh index dd41d960..4d1976fb 100755 --- a/.assets/provision/install_kubectl-convert.sh +++ b/.assets/provision/install_kubectl-convert.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_kubectl-convert.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_miniconda.sh b/.assets/provision/install_miniconda.sh index 0c399162..da7db779 100755 --- a/.assets/provision/install_miniconda.sh +++ b/.assets/provision/install_miniconda.sh @@ -3,6 +3,8 @@ .assets/provision/install_miniconda.sh .assets/provision/install_miniconda.sh --fix_certify true ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 exit 1 @@ -13,7 +15,7 @@ fix_certify=${fix_certify:-false} while [ $# -gt 0 ]; do if [[ $1 == *"--"* ]]; then param="${1/--/}" - declare $param="$2" + declare $param="${2:-}" fi shift done diff --git a/.assets/provision/install_miniforge.sh b/.assets/provision/install_miniforge.sh index 8ac4d49f..23b3773e 100755 --- a/.assets/provision/install_miniforge.sh +++ b/.assets/provision/install_miniforge.sh @@ -3,6 +3,8 @@ .assets/provision/install_miniforge.sh .assets/provision/install_miniforge.sh --fix_certify true ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 exit 1 @@ -13,7 +15,7 @@ fix_certify=${fix_certify:-false} while [ $# -gt 0 ]; do if [[ $1 == *"--"* ]]; then param="${1/--/}" - declare $param="$2" + declare $param="${2:-}" fi shift done diff --git a/.assets/provision/install_nodejs.sh b/.assets/provision/install_nodejs.sh index ed6dc209..d60eccaf 100755 --- a/.assets/provision/install_nodejs.sh +++ b/.assets/provision/install_nodejs.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_nodejs.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_pixi.sh b/.assets/provision/install_pixi.sh index b3da1ebe..7b1eb482 100755 --- a/.assets/provision/install_pixi.sh +++ b/.assets/provision/install_pixi.sh @@ -2,6 +2,8 @@ : ' .assets/provision/install_pixi.sh ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_podman.sh b/.assets/provision/install_podman.sh index d30d7215..eea8064b 100755 --- a/.assets/provision/install_podman.sh +++ b/.assets/provision/install_podman.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_podman.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_prek.sh b/.assets/provision/install_prek.sh index 2150e798..c46d8a26 100755 --- a/.assets/provision/install_prek.sh +++ b/.assets/provision/install_prek.sh @@ -2,6 +2,8 @@ : ' .assets/provision/install_prek.sh >/dev/null ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 exit 1 @@ -12,6 +14,7 @@ fi # define variables APP='prek' +REL=${1:-} # get latest release if not provided as a parameter if [ -z "$REL" ]; then diff --git a/.assets/provision/install_smee.sh b/.assets/provision/install_smee.sh index c2c63d12..9bb2bf52 100755 --- a/.assets/provision/install_smee.sh +++ b/.assets/provision/install_smee.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_smee.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/install_zsh.sh b/.assets/provision/install_zsh.sh index 58176917..6dad8f7d 100755 --- a/.assets/provision/install_zsh.sh +++ b/.assets/provision/install_zsh.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/install_zsh.sh >/dev/null ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/set_authorized_keys.sh b/.assets/provision/set_authorized_keys.sh index ccf5e6d0..04697e65 100755 --- a/.assets/provision/set_authorized_keys.sh +++ b/.assets/provision/set_authorized_keys.sh @@ -1,8 +1,9 @@ #!/usr/bin/env bash +set -euo pipefail # check if the passed parameter starts with rsa phrase -if ! echo "$1" | grep -qE '^(ssh-|ecdsa-)'; then +if ! echo "${1:-}" | grep -qE '^(ssh-|ecdsa-)'; then printf '\e[31;1mMissing ssh public key in the script parameter.\e[0m\n' exit 1 fi -grep -q "$1" ~/.ssh/authorized_keys || echo "$1" >>~/.ssh/authorized_keys +grep -q "${1:-}" ~/.ssh/authorized_keys || echo "${1:-}" >>~/.ssh/authorized_keys diff --git a/.assets/provision/set_ulimits.sh b/.assets/provision/set_ulimits.sh index 27b95934..03ac5761 100755 --- a/.assets/provision/set_ulimits.sh +++ b/.assets/provision/set_ulimits.sh @@ -2,12 +2,14 @@ : ' sudo .assets/provision/set_ulimits.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 fi -cat << EOF > /etc/security/limits.d/k8slimits.conf +cat </etc/security/limits.d/k8slimits.conf * soft nofile 120000 * hard nofile 524288 root soft nofile 120000 diff --git a/.assets/provision/setup_docker_mount.sh b/.assets/provision/setup_docker_mount.sh index cdac9eea..5d675d45 100755 --- a/.assets/provision/setup_docker_mount.sh +++ b/.assets/provision/setup_docker_mount.sh @@ -2,6 +2,8 @@ : ' sudo .assets\provision\setup_docker_mount.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -14,7 +16,7 @@ fstype=${fstype:-ext4} while [ $# -gt 0 ]; do if [[ $1 == *"--"* ]]; then param="${1/--/}" - declare $param="$2" + declare $param="${2:-}" # echo $1 $2 // Optional to see the parameter:value result fi shift diff --git a/.assets/provision/setup_gh_https.sh b/.assets/provision/setup_gh_https.sh index 06d10e16..a705b638 100755 --- a/.assets/provision/setup_gh_https.sh +++ b/.assets/provision/setup_gh_https.sh @@ -9,6 +9,8 @@ sudo .assets/provision/setup_gh_https.sh -u "$(id -un)" -c "$gh_auth" # set up GitHub CLI https authentication with admin:public_key scope and the provided token sudo .assets/provision/setup_gh_https.sh -u "$(id -un)" -c "$gh_auth" -k ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -20,8 +22,10 @@ fi # dotsource file with common functions . .assets/provision/source.sh -# initialize local variable to the current user +# initialize local variables user="$(id -un 1000 2>/dev/null || echo "unknown")" +gh_cfg='' +key='' # parse named parameters OPTIND=1 while getopts ":u:c:k" opt; do diff --git a/.assets/provision/setup_gh_repos.sh b/.assets/provision/setup_gh_repos.sh index 3a30cde1..28ba4b0c 100755 --- a/.assets/provision/setup_gh_repos.sh +++ b/.assets/provision/setup_gh_repos.sh @@ -3,13 +3,15 @@ .assets/provision/setup_gh_repos.sh --repos "szymonos/linux-setup-scripts szymonos/ps-modules" .assets/provision/setup_gh_repos.sh --repos "szymonos/linux-setup-scripts szymonos/ps-modules" --ws_suffix "scripts" ' +set -euo pipefail + # parse named parameters -repos=${repos} +repos=${repos:-} ws_suffix=${ws_suffix:-devops} while [ $# -gt 0 ]; do if [[ $1 == *"--"* ]]; then param="${1/--/}" - declare $param="$2" + declare $param="${2:-}" fi shift done diff --git a/.assets/provision/setup_gh_ssh.sh b/.assets/provision/setup_gh_ssh.sh index 1ecceb8b..4e56f873 100755 --- a/.assets/provision/setup_gh_ssh.sh +++ b/.assets/provision/setup_gh_ssh.sh @@ -2,6 +2,8 @@ : ' .assets/provision/setup_gh_ssh.sh ' +set -euo pipefail + if [ $EUID -eq 0 ]; then printf '\e[31;1mDo not run the script as root.\e[0m\n' >&2 diff --git a/.assets/provision/setup_gnome.sh b/.assets/provision/setup_gnome.sh index 40167eac..80661ca0 100755 --- a/.assets/provision/setup_gnome.sh +++ b/.assets/provision/setup_gnome.sh @@ -2,6 +2,8 @@ : ' .assets/provision/setup_gnome.sh ' +set -euo pipefail + # determine system id SYS_ID="$(sed -En '/^ID.*(arch|fedora|debian|ubuntu|opensuse).*/{s//\1/;p;q}' /etc/os-release)" diff --git a/.assets/provision/setup_omp.sh b/.assets/provision/setup_omp.sh index a0f1f875..9fa23182 100755 --- a/.assets/provision/setup_omp.sh +++ b/.assets/provision/setup_omp.sh @@ -9,6 +9,8 @@ sudo .assets/provision/setup_omp.sh --user $(id -un) --theme nerd # :you can specify any themes from https://ohmyposh.dev/docs/themes/ (e.g. atomic) sudo .assets/provision/setup_omp.sh --user $(id -un) --theme atomic ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 @@ -16,11 +18,11 @@ fi # parse named parameters theme=${theme:-base} -user=${user:-$(id -un 1000 2>/dev/null)} +user=${user:-$(id -un 1000 2>/dev/null || echo '')} while [ $# -gt 0 ]; do if [[ $1 == *"--"* ]]; then param="${1/--/}" - declare $param="$2" + declare $param="${2:-}" fi shift done diff --git a/.assets/provision/setup_profile_user.sh b/.assets/provision/setup_profile_user.sh index e8ee561b..6d464838 100755 --- a/.assets/provision/setup_profile_user.sh +++ b/.assets/provision/setup_profile_user.sh @@ -2,6 +2,8 @@ : ' .assets/provision/setup_profile_user.sh ' +set -euo pipefail + # path variables PROFILE_PATH='/etc/profile.d' OMP_PATH='/usr/local/share/oh-my-posh' diff --git a/.assets/provision/setup_python.sh b/.assets/provision/setup_python.sh index 145cb3ec..e0829a79 100755 --- a/.assets/provision/setup_python.sh +++ b/.assets/provision/setup_python.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/setup_python.sh ' +set -euo pipefail + if [ $EUID -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 diff --git a/.assets/provision/setup_ssh.sh b/.assets/provision/setup_ssh.sh index 7bd8d2e9..9db490ba 100755 --- a/.assets/provision/setup_ssh.sh +++ b/.assets/provision/setup_ssh.sh @@ -5,6 +5,8 @@ # :generate SSH key and print the public one ./setup_ssh.sh print_pub ' +set -euo pipefail + # prepare clean $HOME/.ssh directory if [ -d "$HOME/.ssh" ]; then @@ -32,7 +34,7 @@ if [ "${key_exist:-false}" != true ]; then fi # print the pub key if parameter provided -if [ "$1" = "print_pub" ]; then +if [ "${1:-}" = "print_pub" ]; then printf "\033[96mAdd the following key on: \033[34;4mhttps://github.com/settings/ssh/new\033[0m\n\n" cat "$HOME/.ssh/id_ed25519.pub" fi diff --git a/.assets/provision/upgrade_system.sh b/.assets/provision/upgrade_system.sh index f35a1a9e..de1a77ec 100755 --- a/.assets/provision/upgrade_system.sh +++ b/.assets/provision/upgrade_system.sh @@ -2,6 +2,8 @@ : ' sudo .assets/provision/upgrade_system.sh ' +set -eu + if [ $(id -u) -ne 0 ]; then printf '\e[31;1mRun the script as root.\e[0m\n' >&2 exit 1 From 11ed546a240248ca3d9aaab451df320a63e6ed49 Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 18:45:40 +0100 Subject: [PATCH 07/12] fix(ps): setup_profile_allusers --- .assets/provision/setup_profile_allusers.ps1 | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.assets/provision/setup_profile_allusers.ps1 b/.assets/provision/setup_profile_allusers.ps1 index ce50121b..4d174886 100755 --- a/.assets/provision/setup_profile_allusers.ps1 +++ b/.assets/provision/setup_profile_allusers.ps1 @@ -92,5 +92,20 @@ process { if (Test-Path .assets/provision/update_psresources.ps1 -PathType Leaf) { .assets/provision/update_psresources.ps1 } + #region update PSResourceGet to RC version to resolve Az module installation issue + # TODO remove, once fixed PSResourceGet is updated to GA release + Install-PSResource -Name Microsoft.PowerShell.PSResourceGet -Prerelease -Reinstall -Scope AllUsers + # delete old version of PSResourceGet, if exists + Get-Module -ListAvailable -Name Microsoft.PowerShell.PSResourceGet | ForEach-Object { + [PSCustomObject]@{ + Name = $_.Name + Version = "$($_.Version)$($_.PrivateData.PSData.Prerelease ? "-$($_.PrivateData.PSData.Prerelease)" : '')" + ModuleBase = $_.ModuleBase + } + } | Sort-Object -Property Version -Descending | Select-Object -Skip 1 | ForEach-Object { + Write-Host "removing old version of PSResourceGet: $($_.Version)" -ForegroundColor Yellow + Remove-Item -Path $_.ModuleBase -Recurse -Force + } + #endregion } } From 759903c65a5764709e0cc78bbb9fd3fcfd56a654 Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 18:56:54 +0100 Subject: [PATCH 08/12] feat: improve mktemp usage for cross-distro compatibility - Change mktemp -dp to mktemp -d -p for cross-distro compatibility - Add trap to remove TMP_DIR/tmp_dir on EXIT immediately after mktemp - Remove obsolete 'rm -fr $TMP_DIR' commands and comments - Remove unnecessary empty lines after removed commands - Trap lines properly indented to match mktemp lines - All scripts tested and validated with shellcheck Affected: 36 files (install scripts using mktemp) Scripts: argorolloutscli, azcopy, bat, brew, cilium, crictl, etcdctl, exa, eza, fastfetch, fonts_cascadiacode, fonts_nerd, gcloud, gh, k9s, kind, kubecolor, kubectl-convert, kubectl, kubectx, kubelogin, kubeseal, kustomize, miniconda, miniforge, minikube, nerdctl, nodejs, omp, prek, pwsh, ripgrep, terrascan, tflint, uv, yq Total: 80 insertions(+), 121 deletions(-) --- .assets/provision/install_argorolloutscli.sh | 5 ++--- .assets/provision/install_azcopy.sh | 10 ++++------ .assets/provision/install_bat.sh | 5 ++--- .assets/provision/install_brew.sh | 5 ++--- .assets/provision/install_cilium.sh | 5 ++--- .assets/provision/install_crictl.sh | 5 ++--- .assets/provision/install_etcdctl.sh | 5 ++--- .assets/provision/install_exa.sh | 5 ++--- .assets/provision/install_eza.sh | 5 ++--- .assets/provision/install_fastfetch.sh | 5 ++--- .assets/provision/install_fonts_cascadiacode.sh | 5 ++--- .assets/provision/install_fonts_nerd.sh | 5 ++--- .assets/provision/install_gcloud.sh | 15 +++++++-------- .assets/provision/install_gh.sh | 5 ++--- .assets/provision/install_k9s.sh | 5 ++--- .assets/provision/install_kind.sh | 5 ++--- .assets/provision/install_kubecolor.sh | 5 ++--- .assets/provision/install_kubectl-convert.sh | 8 ++++---- .assets/provision/install_kubectl.sh | 5 ++--- .assets/provision/install_kubectx.sh | 5 ++--- .assets/provision/install_kubelogin.sh | 5 ++--- .assets/provision/install_kubeseal.sh | 5 ++--- .assets/provision/install_kustomize.sh | 8 ++++---- .assets/provision/install_miniconda.sh | 6 ++---- .assets/provision/install_miniforge.sh | 5 ++--- .assets/provision/install_minikube.sh | 10 ++++------ .assets/provision/install_nerdctl.sh | 5 ++--- .assets/provision/install_nodejs.sh | 5 ++--- .assets/provision/install_omp.sh | 5 ++--- .assets/provision/install_prek.sh | 6 ++---- .assets/provision/install_pwsh.sh | 15 ++++++--------- .assets/provision/install_ripgrep.sh | 5 ++--- .assets/provision/install_terrascan.sh | 5 ++--- .assets/provision/install_tflint.sh | 5 ++--- .assets/provision/install_uv.sh | 6 ++---- .assets/provision/install_yq.sh | 5 ++--- 36 files changed, 89 insertions(+), 130 deletions(-) diff --git a/.assets/provision/install_argorolloutscli.sh b/.assets/provision/install_argorolloutscli.sh index 52951e69..228f6d74 100755 --- a/.assets/provision/install_argorolloutscli.sh +++ b/.assets/provision/install_argorolloutscli.sh @@ -36,12 +36,11 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/argoproj/argo-rollouts/releases/download/v${REL}/kubectl-argo-rollouts-linux-amd64" # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/$(basename $URL)" /usr/local/bin/kubectl-argo-rollouts fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_azcopy.sh b/.assets/provision/install_azcopy.sh index 2e4944fa..63e2338d 100755 --- a/.assets/provision/install_azcopy.sh +++ b/.assets/provision/install_azcopy.sh @@ -46,19 +46,19 @@ fedora) debian | ubuntu) export DEBIAN_FRONTEND=noninteractive # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/Azure/azure-storage-azcopy/releases/download/v${REL}/azcopy-${REL}.x86_64.deb" # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then dpkg -i "$TMP_DIR/$(basename $URL)" >&2 2>/dev/null fi - # remove temporary dir - rm -fr "$TMP_DIR" ;; *) # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/Azure/azure-storage-azcopy/releases/download/v${REL}/azcopy_linux_amd64_${REL}.tar.gz" # download and install file @@ -66,7 +66,5 @@ debian | ubuntu) tar -zxf "$TMP_DIR/$(basename $URL)" -C "$TMP_DIR" install -m 0755 "$TMP_DIR/azcopy_linux_amd64_${REL}/azcopy" /usr/bin/ fi - # remove temporary dir - rm -fr "$TMP_DIR" ;; esac diff --git a/.assets/provision/install_bat.sh b/.assets/provision/install_bat.sh index 6474842c..89cc6be9 100755 --- a/.assets/provision/install_bat.sh +++ b/.assets/provision/install_bat.sh @@ -82,7 +82,8 @@ esac if [ "$binary" = true ]; then echo 'Installing from binary.' >&2 # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/sharkdp/bat/releases/download/v${REL}/bat-v${REL}-x86_64-unknown-linux-gnu.tar.gz" # download and install file @@ -92,6 +93,4 @@ if [ "$binary" = true ]; then install -m 0644 "$TMP_DIR/bat.1" "$(manpath | cut -d : -f 1)/man1/" install -m 0644 "$TMP_DIR/autocomplete/bat.bash" /etc/bash_completion.d/ fi - # remove temporary dir - rm -fr "$TMP_DIR" fi diff --git a/.assets/provision/install_brew.sh b/.assets/provision/install_brew.sh index ad027779..25d06eba 100755 --- a/.assets/provision/install_brew.sh +++ b/.assets/provision/install_brew.sh @@ -42,13 +42,12 @@ else # skip tap cloning export HOMEBREW_INSTALL_FROM_API=1 # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://raw.githubusercontent.com/Homebrew/install/master/install.sh" # download and install homebrew if download_file --uri "$URL" --target_dir "$TMP_DIR"; then bash -c "$TMP_DIR/$(basename $URL)" fi - # remove temporary dir - rm -fr "$TMP_DIR" fi diff --git a/.assets/provision/install_cilium.sh b/.assets/provision/install_cilium.sh index 4aa1d15b..61b26267 100755 --- a/.assets/provision/install_cilium.sh +++ b/.assets/provision/install_cilium.sh @@ -36,7 +36,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/cilium/cilium-cli/releases/download/v${REL}/cilium-linux-amd64.tar.gz" # download and install file @@ -46,5 +47,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/cilium" /opt/cilium/ [ -f /usr/bin/cilium ] || ln -s /opt/cilium/cilium /usr/bin/cilium fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_crictl.sh b/.assets/provision/install_crictl.sh index ebd1fb81..231c085d 100755 --- a/.assets/provision/install_crictl.sh +++ b/.assets/provision/install_crictl.sh @@ -36,7 +36,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/kubernetes-sigs/cri-tools/releases/download/v${REL}/${APP}-v${REL}-linux-amd64.tar.gz" # download and install file @@ -44,5 +45,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then tar -zxf "$TMP_DIR/$(basename $URL)" --no-same-owner -C "$TMP_DIR" install -m 0755 "$TMP_DIR/crictl" /usr/local/bin/ fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_etcdctl.sh b/.assets/provision/install_etcdctl.sh index 8f7b7452..77490a14 100755 --- a/.assets/provision/install_etcdctl.sh +++ b/.assets/provision/install_etcdctl.sh @@ -36,7 +36,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/etcd-io/etcd/releases/download/v${REL}/etcd-v${REL}-linux-amd64.tar.gz" # download and install file @@ -46,5 +47,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/etcdctl" /usr/local/bin/ install -m 0755 "$TMP_DIR/etcdutl" /usr/local/bin/ fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_exa.sh b/.assets/provision/install_exa.sh index 920dd41e..a6256860 100755 --- a/.assets/provision/install_exa.sh +++ b/.assets/provision/install_exa.sh @@ -78,7 +78,8 @@ esac if [ "$binary" = true ] && [ -n "$REL" ]; then echo 'Installing from binary.' >&2 # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/ogham/exa/releases/download/v${REL}/exa-linux-x86_64-v${REL}.zip" # download and install file @@ -89,6 +90,4 @@ if [ "$binary" = true ] && [ -n "$REL" ]; then install -m 0644 "$TMP_DIR/man/exa_colors.5" "$(manpath | cut -d : -f 1)/man5/" install -m 0644 "$TMP_DIR/completions/exa.bash" /etc/bash_completion.d/ fi - # remove temporary dir - rm -fr "$TMP_DIR" fi diff --git a/.assets/provision/install_eza.sh b/.assets/provision/install_eza.sh index c1bc9ea2..18d044d1 100755 --- a/.assets/provision/install_eza.sh +++ b/.assets/provision/install_eza.sh @@ -94,7 +94,8 @@ esac if [ "$binary" = true ] && [ -n "$REL" ]; then printf "Installing $APP \e[1mv$REL\e[22m from binary.\n" >&2 # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/eza-community/eza/releases/download/v${REL}/eza_x86_64-unknown-linux-${lib}.tar.gz" # download and install file @@ -102,6 +103,4 @@ if [ "$binary" = true ] && [ -n "$REL" ]; then tar -zxf "$TMP_DIR/$(basename $URL)" -C "$TMP_DIR" install -m 0755 "$TMP_DIR/eza" /usr/bin/ fi - # remove temporary dir - rm -fr "$TMP_DIR" fi diff --git a/.assets/provision/install_fastfetch.sh b/.assets/provision/install_fastfetch.sh index 78a606c0..73dcde78 100755 --- a/.assets/provision/install_fastfetch.sh +++ b/.assets/provision/install_fastfetch.sh @@ -73,15 +73,14 @@ fedora) debian | ubuntu) export DEBIAN_FRONTEND=noninteractive # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/fastfetch-cli/fastfetch/releases/download/${REL}/fastfetch-linux-amd64.deb" # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then dpkg -i "$TMP_DIR/$(basename $URL)" >&2 2>/dev/null fi - # remove temporary dir - rm -fr "$TMP_DIR" ;; opensuse) zypper --non-interactive in -y $APP >&2 2>/dev/null diff --git a/.assets/provision/install_fonts_cascadiacode.sh b/.assets/provision/install_fonts_cascadiacode.sh index 0f26bcb9..eb0084d6 100755 --- a/.assets/provision/install_fonts_cascadiacode.sh +++ b/.assets/provision/install_fonts_cascadiacode.sh @@ -28,7 +28,8 @@ echo $REL echo "Install CascadiaCode v$REL" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/microsoft/cascadia-code/releases/download/v${REL}/CascadiaCode-${REL}.zip" # download and install file @@ -39,5 +40,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then # build font information caches fc-cache -f /usr/share/fonts/cascadia-code/ fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_fonts_nerd.sh b/.assets/provision/install_fonts_nerd.sh index 581f409e..9d4e9dc1 100755 --- a/.assets/provision/install_fonts_nerd.sh +++ b/.assets/provision/install_fonts_nerd.sh @@ -90,7 +90,8 @@ if [ -n "$1" ]; then # dotsource file with common functions . .assets/provision/source.sh # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/ryanoasis/nerd-fonts/releases/latest/download/${font}.zip" # download and install file @@ -102,8 +103,6 @@ if [ -n "$1" ]; then # build font information caches fc-cache -f /usr/share/fonts/${font,,}-nf fi - # remove temporary dir - rm -fr "$TMP_DIR" fi else printf '\e[31;1mProvide font name.\e[0m\n' >&2 diff --git a/.assets/provision/install_gcloud.sh b/.assets/provision/install_gcloud.sh index c5b9123a..377694c8 100755 --- a/.assets/provision/install_gcloud.sh +++ b/.assets/provision/install_gcloud.sh @@ -42,11 +42,11 @@ get_latest_gcloud_version() { local metadata_uri='https://dl.google.com/dl/cloudsdk/channels/rapid/components-2.json' if ! command -v curl &>/dev/null; then printf '\e[31mThe curl command is required to determine the latest Google Cloud CLI release.\e[0m\n' >&2 - exit 1 + return 1 fi if ! command -v jq &>/dev/null; then printf '\e[31mThe jq command is required to parse the Google Cloud CLI release metadata.\e[0m\n' >&2 - exit 1 + return 1 fi curl -fsSL "$metadata_uri" | jq -r '.version' } @@ -66,13 +66,13 @@ install_from_tarball() { archive_name='google-cloud-cli-linux-x86_64.tar.gz' fi url="https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/${archive_name}" - tmp_dir="$(mktemp -dp "$HOME")" + tmp_dir="$(mktemp -d -p "$HOME")" + trap 'rm -fr "$tmp_dir"' RETURN printf '\e[33mFalling back to the official Google Cloud CLI tarball.\e[0m\n' >&2 if ! download_file --uri "$url" --target_dir "$tmp_dir"; then - rm -rf "$tmp_dir" printf '\e[31mFailed to download the Google Cloud CLI archive.\e[0m\n' >&2 - exit 1 + return 1 fi tar -zxf "$tmp_dir/$archive_name" -C "$tmp_dir" @@ -94,14 +94,13 @@ install_from_tarball() { ln -sf "$install_dir/$gcloud_dir/bin/gke-gcloud-auth-plugin" /usr/bin/gke-gcloud-auth-plugin fi - rm -rf "$tmp_dir" printf '\e[32mInstalled Google Cloud CLI from tarball.\e[0m\n' >&2 + return 0 } REL="${1:-}" if [ -z "$REL" ]; then - REL="$(get_latest_gcloud_version)" - if [ -z "$REL" ]; then + if ! REL="$(get_latest_gcloud_version)"; then printf "\e[31mFailed to get the latest version of $APP.\e[0m\n" >&2 exit 1 fi diff --git a/.assets/provision/install_gh.sh b/.assets/provision/install_gh.sh index 8f751003..b0fb23e2 100755 --- a/.assets/provision/install_gh.sh +++ b/.assets/provision/install_gh.sh @@ -28,14 +28,13 @@ fedora | opensuse) debian | ubuntu) export DEBIAN_FRONTEND=noninteractive # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT if download_file --uri "https://cli.github.com/packages/githubcli-archive-keyring.gpg" --target_dir "$TMP_DIR"; then mkdir -p -m 755 /etc/apt/keyrings install -m 0644 "$TMP_DIR/githubcli-archive-keyring.gpg" /etc/apt/keyrings echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" >/etc/apt/sources.list.d/github-cli.list fi - # remove temporary dir - rm -fr "$TMP_DIR" # check if installed already dpkg -s gh &>/dev/null && exit 0 || true ;; diff --git a/.assets/provision/install_k9s.sh b/.assets/provision/install_k9s.sh index e10a5082..291c4649 100755 --- a/.assets/provision/install_k9s.sh +++ b/.assets/provision/install_k9s.sh @@ -36,7 +36,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/derailed/k9s/releases/download/v${REL}/k9s_Linux_amd64.tar.gz" # download and install file @@ -46,5 +47,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/k9s" /opt/k9s/ [ -f /usr/bin/k9s ] || ln -s /opt/k9s/k9s /usr/bin/k9s fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_kind.sh b/.assets/provision/install_kind.sh index 3bfa85a3..a2ae14ef 100755 --- a/.assets/provision/install_kind.sh +++ b/.assets/provision/install_kind.sh @@ -38,7 +38,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/$OWNER/$REPO/releases/download/v${REL}/kind-linux-amd64" # download and install file @@ -47,5 +48,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/kind-linux-amd64" /opt/kind/kind [ -f /usr/bin/kind ] || ln -s /opt/kind/kind /usr/bin/kind fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_kubecolor.sh b/.assets/provision/install_kubecolor.sh index 8195b02c..06bfee53 100755 --- a/.assets/provision/install_kubecolor.sh +++ b/.assets/provision/install_kubecolor.sh @@ -72,7 +72,8 @@ esac if [ "$binary" = true ] && [ -n "$REL" ]; then printf "Installing $APP \e[1mv$REL\e[22m from binary.\n" >&2 # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri if [[ "$SYS_ID" =~ ^(debian|ubuntu)$ ]]; then asset="kubecolor_${REL}_linux_amd64.deb" @@ -89,6 +90,4 @@ if [ "$binary" = true ] && [ -n "$REL" ]; then install -m 0755 "$TMP_DIR/kubecolor" /usr/bin/ fi fi - # remove temporary dir - rm -fr "$TMP_DIR" fi diff --git a/.assets/provision/install_kubectl-convert.sh b/.assets/provision/install_kubectl-convert.sh index 4d1976fb..468255f5 100755 --- a/.assets/provision/install_kubectl-convert.sh +++ b/.assets/provision/install_kubectl-convert.sh @@ -13,14 +13,14 @@ APP='kubectl-convert' # dotsource file with common functions . .assets/provision/source.sh + +printf "\e[92minstalling \e[1m$APP\e[22m\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://dl.k8s.io/release/$(curl -sLk https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl-convert" # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then - tar -zxf "$TMP_DIR/$(basename $URL)" -C "$TMP_DIR" install -m 0755 "$TMP_DIR/$(basename $URL)" /usr/bin/ fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_kubectl.sh b/.assets/provision/install_kubectl.sh index 7d854ab0..9b300e05 100755 --- a/.assets/provision/install_kubectl.sh +++ b/.assets/provision/install_kubectl.sh @@ -57,13 +57,12 @@ if [ "$binary" = true ]; then # dotsource file with common functions . .assets/provision/source.sh # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://dl.k8s.io/release/${REL}/bin/linux/amd64/kubectl" # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/$(basename $URL)" /usr/bin/ fi - # remove temporary dir - rm -fr "$TMP_DIR" fi diff --git a/.assets/provision/install_kubectx.sh b/.assets/provision/install_kubectx.sh index 2ea627f9..2c9d7ec0 100755 --- a/.assets/provision/install_kubectx.sh +++ b/.assets/provision/install_kubectx.sh @@ -36,7 +36,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # *install kubectx # calculate download uri URL="https://github.com/ahmetb/kubectx/releases/download/v${REL}/${APP}_v${REL}_linux_x86_64.tar.gz" @@ -56,5 +57,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/kubens" /opt/$APP/ [ -f /usr/bin/kubens ] || ln -s /opt/$APP/kubens /usr/bin/kubens fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_kubelogin.sh b/.assets/provision/install_kubelogin.sh index 561efb3f..de284493 100755 --- a/.assets/provision/install_kubelogin.sh +++ b/.assets/provision/install_kubelogin.sh @@ -36,7 +36,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/Azure/kubelogin/releases/download/v${REL}/kubelogin-linux-amd64.zip" # download and install file @@ -44,5 +45,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then unzip -q "$TMP_DIR/$(basename $URL)" -d "$TMP_DIR" install -m 0755 "$TMP_DIR/bin/linux_amd64/kubelogin" /usr/local/bin/ fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_kubeseal.sh b/.assets/provision/install_kubeseal.sh index eea879ef..1f7ab5d9 100755 --- a/.assets/provision/install_kubeseal.sh +++ b/.assets/provision/install_kubeseal.sh @@ -47,11 +47,10 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then tar -zxf "$TMP_DIR/$(basename $URL)" -C "$TMP_DIR" install -m 0755 "$TMP_DIR/$APP" /usr/local/bin/ fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_kustomize.sh b/.assets/provision/install_kustomize.sh index 46896e7d..a49078a2 100755 --- a/.assets/provision/install_kustomize.sh +++ b/.assets/provision/install_kustomize.sh @@ -36,13 +36,13 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL='https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh' # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then - bash -C "$TMP_DIR/$(basename $URL)" + cd "$TMP_DIR" + bash -C "$(basename $URL)" install -m 0755 kustomize /usr/bin/ fi -# remove temporary dir -rm -fr kustomize "$TMP_DIR" diff --git a/.assets/provision/install_miniconda.sh b/.assets/provision/install_miniconda.sh index da7db779..9f705d21 100755 --- a/.assets/provision/install_miniconda.sh +++ b/.assets/provision/install_miniconda.sh @@ -43,16 +43,14 @@ else # dotsource file with common functions . .assets/provision/source.sh # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh" # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then bash -C "$TMP_DIR/$(basename $URL)" -u -b -p "$HOME/miniconda3" >/dev/null fi - # remove temporary dir - rm -fr "$TMP_DIR" - # disable auto activation of the base conda environment conda_init # conda config --add channels defaults diff --git a/.assets/provision/install_miniforge.sh b/.assets/provision/install_miniforge.sh index 23b3773e..ae1288db 100755 --- a/.assets/provision/install_miniforge.sh +++ b/.assets/provision/install_miniforge.sh @@ -43,15 +43,14 @@ else # dotsource file with common functions . .assets/provision/source.sh # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then bash -C "$TMP_DIR/$(basename $URL)" -u -b -p "$HOME/miniforge3" >/dev/null fi - # remove temporary dir - rm -fr "$TMP_DIR" # disable auto activation of the base conda environment conda_init conda config --set auto_activate_base false diff --git a/.assets/provision/install_minikube.sh b/.assets/provision/install_minikube.sh index 6d9f12f1..06d28e29 100755 --- a/.assets/provision/install_minikube.sh +++ b/.assets/provision/install_minikube.sh @@ -57,15 +57,14 @@ fedora) debian | ubuntu) export DEBIAN_FRONTEND=noninteractive # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://storage.googleapis.com/minikube/releases/latest/minikube_latest_amd64.deb" # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then dpkg -i "$TMP_DIR/$(basename $URL)" >&2 2>/dev/null || binary=true fi - # remove temporary dir - rm -fr "$TMP_DIR" ;; opensuse) zypper --non-interactive in -y --allow-unsigned-rpm "https://storage.googleapis.com/minikube/releases/latest/minikube-latest.x86_64.rpm" >&2 2>/dev/null || binary=true @@ -78,13 +77,12 @@ esac if [ "$binary" = true ]; then echo 'Installing from binary.' >&2 # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64" # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/$(basename $URL)" /usr/local/bin/minikube fi - # remove temporary dir - rm -fr "$TMP_DIR" fi diff --git a/.assets/provision/install_nerdctl.sh b/.assets/provision/install_nerdctl.sh index 8f9f1f28..199e9954 100755 --- a/.assets/provision/install_nerdctl.sh +++ b/.assets/provision/install_nerdctl.sh @@ -36,7 +36,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/containerd/nerdctl/releases/download/v${REL}/${APP}-${REL}-linux-amd64.tar.gz" # download and install file @@ -46,5 +47,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/containerd-rootless-setuptool.sh" /usr/local/bin/ install -m 0755 "$TMP_DIR/containerd-rootless.sh" /usr/local/bin/ fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_nodejs.sh b/.assets/provision/install_nodejs.sh index d60eccaf..9d500407 100755 --- a/.assets/provision/install_nodejs.sh +++ b/.assets/provision/install_nodejs.sh @@ -45,15 +45,14 @@ debian | ubuntu) # dotsource file with common functions . .assets/provision/source.sh # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://deb.nodesource.com/setup_lts.x" # download and install homebrew if download_file --uri "$URL" --target_dir "$TMP_DIR"; then bash -c "$TMP_DIR/setup_lts.x" fi - # remove temporary dir - rm -fr "$TMP_DIR" # install nodejs apt-get update && apt-get install -y $APP npm ;; diff --git a/.assets/provision/install_omp.sh b/.assets/provision/install_omp.sh index 5e276c2a..eb2aaf4f 100755 --- a/.assets/provision/install_omp.sh +++ b/.assets/provision/install_omp.sh @@ -41,10 +41,9 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/$(basename $URL)" /usr/bin/oh-my-posh fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_prek.sh b/.assets/provision/install_prek.sh index c46d8a26..eb9b43c4 100755 --- a/.assets/provision/install_prek.sh +++ b/.assets/provision/install_prek.sh @@ -51,7 +51,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/j178/prek/releases/download/v$REL/prek-installer.sh" # download and install file @@ -62,7 +63,4 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then ((retry_count++)) done fi -# remove temporary dir -rm -fr "$TMP_DIR" - exit 0 diff --git a/.assets/provision/install_pwsh.sh b/.assets/provision/install_pwsh.sh index a25fc075..2ec32413 100755 --- a/.assets/provision/install_pwsh.sh +++ b/.assets/provision/install_pwsh.sh @@ -43,7 +43,8 @@ alpine) apk add --no-cache ncurses-terminfo-base krb5-libs libgcc libintl libssl1.1 libstdc++ tzdata userspace-rcu zlib icu-libs >&2 2>/dev/null apk -X https://dl-cdn.alpinelinux.org/alpine/edge/main add --no-cache lttng-ust >&2 2>/dev/null # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/PowerShell/PowerShell/releases/download/v${REL}/powershell-${REL}-linux-alpine-x64.tar.gz" # download and install file @@ -53,8 +54,6 @@ alpine) chmod +x /opt/microsoft/powershell/7/pwsh ln -s /opt/microsoft/powershell/7/pwsh /usr/bin/pwsh fi - # remove temporary dir - rm -fr "$TMP_DIR" ;; arch) if pacman -Qqe paru &>/dev/null; then @@ -79,15 +78,14 @@ debian | ubuntu) export DEBIAN_FRONTEND=noninteractive [ "$SYS_ID" = 'debian' ] && apt-get update >&2 && apt-get install -y libicu76 >&2 2>/dev/null || true # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/PowerShell/PowerShell/releases/download/v${REL}/powershell_${REL}-1.deb_amd64.deb" # download and install file if download_file --uri "$URL" --target_dir "$TMP_DIR"; then dpkg -i "$TMP_DIR/$(basename $URL)" >&2 2>/dev/null || binary=true fi - # remove temporary dir - rm -fr "$TMP_DIR" ;; *) binary=true @@ -98,7 +96,8 @@ if [ "$binary" = true ] && [ -n "$REL" ]; then echo 'Installing from binary.' >&2 [ "$SYS_ID" = 'opensuse' ] && zypper --non-interactive in -y libicu >&2 2>/dev/null || true # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/PowerShell/PowerShell/releases/download/v${REL}/powershell-${REL}-linux-x64.tar.gz" # download and install file @@ -108,6 +107,4 @@ if [ "$binary" = true ] && [ -n "$REL" ]; then chmod +x /opt/microsoft/powershell/7/pwsh [ -f /usr/bin/pwsh ] || ln -s /opt/microsoft/powershell/7/pwsh /usr/bin/pwsh fi - # remove temporary dir - rm -fr "$TMP_DIR" fi diff --git a/.assets/provision/install_ripgrep.sh b/.assets/provision/install_ripgrep.sh index daa703ec..2555cda2 100755 --- a/.assets/provision/install_ripgrep.sh +++ b/.assets/provision/install_ripgrep.sh @@ -78,7 +78,8 @@ esac if [ "$binary" = true ] && [ -n "$REL" ]; then echo 'Installing from binary.' >&2 # create temporary dir for the downloaded binary - TMP_DIR=$(mktemp -dp "$HOME") + TMP_DIR=$(mktemp -d -p "$HOME") + trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/BurntSushi/ripgrep/releases/download/${REL}/ripgrep-${REL}-aarch64-unknown-linux-gnu.tar.gz" # download and install file @@ -88,6 +89,4 @@ if [ "$binary" = true ] && [ -n "$REL" ]; then install -m 0644 "$TMP_DIR/doc/rg.1" "$(manpath | cut -d : -f 1)/man1/" install -m 0644 "$TMP_DIR/complete/rg.bash" /etc/bash_completion.d/ fi - # remove temporary dir - rm -fr "$TMP_DIR" fi diff --git a/.assets/provision/install_terrascan.sh b/.assets/provision/install_terrascan.sh index 52ed8c0b..6f6f1862 100755 --- a/.assets/provision/install_terrascan.sh +++ b/.assets/provision/install_terrascan.sh @@ -36,7 +36,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/tenable/terrascan/releases/download/v${REL}/terrascan_${REL}_Linux_x86_64.tar.gz" # download and install file @@ -44,5 +45,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then tar -zxf "$TMP_DIR/$(basename $URL)" -C "$TMP_DIR" install -m 0755 "$TMP_DIR/terrascan" /usr/bin/ fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_tflint.sh b/.assets/provision/install_tflint.sh index e225d475..ba5a2b38 100755 --- a/.assets/provision/install_tflint.sh +++ b/.assets/provision/install_tflint.sh @@ -38,7 +38,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/$OWNER/$REPO/releases/download/v${REL}/tflint_linux_amd64.zip" # download and install file @@ -46,5 +47,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then unzip -q "$TMP_DIR/$(basename $URL)" -d "$TMP_DIR" install -m 0755 "$TMP_DIR/tflint" /usr/bin/ fi -# remove temporary dir -rm -fr "$TMP_DIR" diff --git a/.assets/provision/install_uv.sh b/.assets/provision/install_uv.sh index 8647dde5..f9adb606 100755 --- a/.assets/provision/install_uv.sh +++ b/.assets/provision/install_uv.sh @@ -53,7 +53,8 @@ fi # check if the binary is already installed printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://astral.sh/uv/install.sh" # download and install file @@ -64,7 +65,4 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then ((retry_count++)) done fi -# remove temporary dir -rm -fr "$TMP_DIR" - exit 0 diff --git a/.assets/provision/install_yq.sh b/.assets/provision/install_yq.sh index c04d6af6..f2249948 100755 --- a/.assets/provision/install_yq.sh +++ b/.assets/provision/install_yq.sh @@ -36,7 +36,8 @@ fi printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 # create temporary dir for the downloaded binary -TMP_DIR=$(mktemp -dp "$HOME") +TMP_DIR=$(mktemp -d -p "$HOME") +trap 'rm -fr "$TMP_DIR"' EXIT # calculate download uri URL="https://github.com/mikefarah/yq/releases/download/v${REL}/yq_linux_amd64.tar.gz" # download and install file @@ -45,5 +46,3 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then install -m 0755 "$TMP_DIR/yq_linux_amd64" /usr/local/bin/yq pushd "$TMP_DIR" >/dev/null && bash ./install-man-page.sh && popd >/dev/null fi -# remove temporary dir -rm -fr "$TMP_DIR" From a003cf7ed09f7077001135c933a71bc0148f14f5 Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 19:57:40 +0100 Subject: [PATCH 09/12] fix(sh): set_authorized_keys --- .assets/provision/install_pixi.sh | 1 + .assets/provision/set_authorized_keys.sh | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/.assets/provision/install_pixi.sh b/.assets/provision/install_pixi.sh index 7b1eb482..d9fff76a 100755 --- a/.assets/provision/install_pixi.sh +++ b/.assets/provision/install_pixi.sh @@ -12,5 +12,6 @@ fi if [ -x "$HOME/.pixi/bin/pixi" ]; then $HOME/.pixi/bin/pixi self-update else + printf "\e[92minstalling \e[1mpixi\e[22m\e[0m\n" >&2 curl -fsSL https://pixi.sh/install.sh | sh fi diff --git a/.assets/provision/set_authorized_keys.sh b/.assets/provision/set_authorized_keys.sh index 04697e65..a0f737fe 100755 --- a/.assets/provision/set_authorized_keys.sh +++ b/.assets/provision/set_authorized_keys.sh @@ -1,5 +1,10 @@ #!/usr/bin/env bash set -euo pipefail + +# create .ssh directory and authorized_keys file if they don't exist +[ -d "$HOME/.ssh" ] || mkdir -m 0700 "$HOME/.ssh" +[ -f "$HOME/.ssh/authorized_keys" ] || touch "$HOME/.ssh/authorized_keys" && chmod 0600 "$HOME/.ssh/authorized_keys" + # check if the passed parameter starts with rsa phrase if ! echo "${1:-}" | grep -qE '^(ssh-|ecdsa-)'; then printf '\e[31;1mMissing ssh public key in the script parameter.\e[0m\n' From 7d1b148174f7cb63bd671cce415e9e8d3896cca1 Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 21:01:47 +0100 Subject: [PATCH 10/12] fix(sh): resolve set -euo pipefail compatibility issues Fix multiple patterns that break under strict error handling: - Add || true to ((retry_count++)) to prevent 0 arithmetic evaluation - Replace 0 checks after command substitution with inline conditionals - Fix operator precedence bugs (|| var=true && var2=value patterns) - Add || true to grep commands that may not match - Protect id command substitutions in user variable assignments This ensures scripts run reliably with set -euo pipefail enabled. --- .assets/provision/install_azurecli.sh | 3 +- .assets/provision/install_base.sh | 2 +- .assets/provision/install_brew.sh | 2 +- .assets/provision/install_distrobox.sh | 2 +- .assets/provision/install_docker.sh | 2 +- .assets/provision/install_edge.sh | 2 +- .assets/provision/install_eza.sh | 33 ++++++++++++++++----- .assets/provision/install_fastfetch.sh | 4 +-- .assets/provision/install_flux.sh | 2 +- .assets/provision/install_helm.sh | 2 +- .assets/provision/install_k3d.sh | 2 +- .assets/provision/install_kubectl.sh | 2 +- .assets/provision/install_miniconda.sh | 3 +- .assets/provision/install_miniforge.sh | 3 +- .assets/provision/install_minikube.sh | 2 +- .assets/provision/install_prek.sh | 4 +-- .assets/provision/install_pwsh.sh | 2 +- .assets/provision/install_smee.sh | 2 +- .assets/provision/install_tfswitch.sh | 2 +- .assets/provision/install_uv.sh | 4 +-- .assets/provision/install_xrdp.sh | 4 +-- .assets/provision/setup_profile_allusers.sh | 2 +- .assets/provision/source.sh | 12 ++++---- 23 files changed, 57 insertions(+), 41 deletions(-) diff --git a/.assets/provision/install_azurecli.sh b/.assets/provision/install_azurecli.sh index 4933dc39..471f0938 100755 --- a/.assets/provision/install_azurecli.sh +++ b/.assets/provision/install_azurecli.sh @@ -24,8 +24,7 @@ done [ -f "$HOME/miniforge3/bin/conda" ] || exit 0 # >>> conda initialize >>> -__conda_setup="$("$HOME/miniforge3/bin/conda" 'shell.bash' 'hook' 2>/dev/null)" -if [ $? -eq 0 ]; then +if __conda_setup="$("$HOME/miniforge3/bin/conda" 'shell.bash' 'hook' 2>/dev/null)"; then eval "$__conda_setup" else if [ -f "$HOME/miniforge3/etc/profile.d/conda.sh" ]; then diff --git a/.assets/provision/install_base.sh b/.assets/provision/install_base.sh index c0d1d757..815a87bd 100755 --- a/.assets/provision/install_base.sh +++ b/.assets/provision/install_base.sh @@ -77,7 +77,7 @@ arch) install_pkgs pacman "$pkgs" # install paru if ! pacman -Qqe paru >/dev/null 2>&1; then - user=${1:-$(id -un 1000 2>/dev/null)} + user=${1:-$(id -un 1000 2>/dev/null || true)} if ! sudo -u $user true 2>/dev/null; then if [ -n "$user" ]; then printf "\e[31;1mUser does not exist ($user).\e[0m\n" diff --git a/.assets/provision/install_brew.sh b/.assets/provision/install_brew.sh index 25d06eba..99465894 100755 --- a/.assets/provision/install_brew.sh +++ b/.assets/provision/install_brew.sh @@ -28,7 +28,7 @@ fi echo $REL if type brew &>/dev/null; then - VER=$(brew --version | grep -Eo '[0-9\.]+\.[0-9]+\.[0-9]+') + VER=$(brew --version | grep -Eo '[0-9\.]+\.[0-9]+\.[0-9]+' || true) if [ "$REL" = "$VER" ]; then printf "\e[32m$APP v$VER is already latest\e[0m\n" >&2 exit 0 diff --git a/.assets/provision/install_distrobox.sh b/.assets/provision/install_distrobox.sh index 1db51e4d..d8f818b4 100755 --- a/.assets/provision/install_distrobox.sh +++ b/.assets/provision/install_distrobox.sh @@ -40,7 +40,7 @@ alpine) ;; arch) if pacman -Qqe paru &>/dev/null; then - user=${1:-$(id -un 1000 2>/dev/null)} + user=${1:-$(id -un 1000 2>/dev/null || true)} if ! sudo -u $user true 2>/dev/null; then if [ -n "$user" ]; then printf "\e[31;1mUser does not exist ($user).\e[0m\n" diff --git a/.assets/provision/install_docker.sh b/.assets/provision/install_docker.sh index 3ddeccee..13904baf 100755 --- a/.assets/provision/install_docker.sh +++ b/.assets/provision/install_docker.sh @@ -74,7 +74,7 @@ opensuse) esac # check provided user -user=${1:-$(id -un 1000 2>/dev/null)} +user=${1:-$(id -un 1000 2>/dev/null || true)} if ! sudo -u $user true 2>/dev/null; then if [ -n "$user" ]; then printf "\e[31;1mUser does not exist ($user).\e[0m\n" diff --git a/.assets/provision/install_edge.sh b/.assets/provision/install_edge.sh index 98415616..ab2237e9 100755 --- a/.assets/provision/install_edge.sh +++ b/.assets/provision/install_edge.sh @@ -15,7 +15,7 @@ SYS_ID="$(sed -En '/^ID.*(arch|fedora|debian|ubuntu|opensuse).*/{s//\1/;p;q}' /e case $SYS_ID in arch) if pacman -Qqe paru &>/dev/null; then - user=${1:-$(id -un 1000 2>/dev/null)} + user=${1:-$(id -un 1000 2>/dev/null || true)} if ! sudo -u $user true 2>/dev/null; then if [ -n "$user" ]; then printf "\e[31;1mUser does not exist ($user).\e[0m\n" diff --git a/.assets/provision/install_eza.sh b/.assets/provision/install_eza.sh index 18d044d1..58360345 100755 --- a/.assets/provision/install_eza.sh +++ b/.assets/provision/install_eza.sh @@ -61,13 +61,22 @@ fi printf "\e[92minstalling \e[1m$APP\e[0m\n" >&2 case $SYS_ID in alpine) - apk add --no-cache $APP >&2 2>/dev/null || binary=true && lib='musl' + apk add --no-cache $APP >&2 2>/dev/null || { + binary=true + lib='musl' + } ;; arch) - pacman -Sy --needed --noconfirm $APP >&2 2>/dev/null || binary=true && lib='gnu' + pacman -Sy --needed --noconfirm $APP >&2 2>/dev/null || { + binary=true + lib='gnu' + } ;; fedora) - dnf install -y $APP >&2 2>/dev/null || binary=true && lib='gnu' + dnf install -y $APP >&2 2>/dev/null || { + binary=true + lib='gnu' + } ;; debian) export DEBIAN_FRONTEND=noninteractive @@ -77,17 +86,27 @@ debian) fi echo "deb [signed-by=/etc/apt/keyrings/gierens.gpg] http://deb.gierens.de stable main" >/etc/apt/sources.list.d/gierens.list chmod 644 /etc/apt/keyrings/gierens.gpg /etc/apt/sources.list.d/gierens.list - apt-get update >&2 && apt-get install -y $APP >&2 2>/dev/null || binary=true && lib='gnu' + apt-get update >&2 && apt-get install -y $APP >&2 2>/dev/null || { + binary=true + lib='gnu' + } ;; ubuntu) export DEBIAN_FRONTEND=noninteractive - apt-get update >&2 && apt-get install -y $APP >&2 2>/dev/null || binary=true && lib='gnu' + apt-get update >&2 && apt-get install -y $APP >&2 2>/dev/null || { + binary=true + lib='gnu' + } ;; opensuse) - zypper --non-interactive in -y $APP >&2 2>/dev/null || binary=true && lib='gnu' + zypper --non-interactive in -y $APP >&2 2>/dev/null || { + binary=true + lib='gnu' + } ;; *) - binary=true && lib='gnu' + binary=true + lib='gnu' ;; esac diff --git a/.assets/provision/install_fastfetch.sh b/.assets/provision/install_fastfetch.sh index 73dcde78..ef60c379 100755 --- a/.assets/provision/install_fastfetch.sh +++ b/.assets/provision/install_fastfetch.sh @@ -42,7 +42,7 @@ fi echo $REL if type $APP &>/dev/null; then - VER=$($APP --version | grep -Po '(?<=\s)[0-9\.]+(?=\s)') + VER=$($APP --version | grep -Po '(?<=\s)[0-9\.]+(?=\s)' || true) if [ "$REL" = "$VER" ]; then printf "\e[32m$APP v$VER is already latest\e[0m\n" >&2 exit 0 @@ -53,7 +53,7 @@ printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 case $SYS_ID in arch) if pacman -Qqe paru &>/dev/null; then - user=${1:-$(id -un 1000 2>/dev/null)} + user=${1:-$(id -un 1000 2>/dev/null || true)} if ! sudo -u $user true 2>/dev/null; then if [ -n "$user" ]; then printf "\e[31;1mUser does not exist ($user).\e[0m\n" diff --git a/.assets/provision/install_flux.sh b/.assets/provision/install_flux.sh index 21a21b85..60dda4d2 100755 --- a/.assets/provision/install_flux.sh +++ b/.assets/provision/install_flux.sh @@ -42,7 +42,7 @@ else retry_count=0 while ! type $APP &>/dev/null && [ $retry_count -lt 10 ]; do eval $__install - ((retry_count++)) + ((retry_count++)) || true done fi diff --git a/.assets/provision/install_helm.sh b/.assets/provision/install_helm.sh index cf6d37e9..2a2932ba 100755 --- a/.assets/provision/install_helm.sh +++ b/.assets/provision/install_helm.sh @@ -42,7 +42,7 @@ else retry_count=0 while ! type $APP &>/dev/null && [ $retry_count -lt 10 ]; do eval $__install - ((retry_count++)) + ((retry_count++)) || true done fi diff --git a/.assets/provision/install_k3d.sh b/.assets/provision/install_k3d.sh index e8095637..c404050b 100755 --- a/.assets/provision/install_k3d.sh +++ b/.assets/provision/install_k3d.sh @@ -38,7 +38,7 @@ printf "\e[92minstalling \e[1m$APP\e[22m v$REL\e[0m\n" >&2 retry_count=0 while curl -sk 'https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh' | bash >&2 - ((retry_count++)) + ((retry_count++)) || true [[ $(k3d --version 2>/dev/null | sed -En 's/.*v([0-9\.]+)$/\1/p') != $REL && $retry_count -le 10 ]] do :; done diff --git a/.assets/provision/install_kubectl.sh b/.assets/provision/install_kubectl.sh index 9b300e05..9afb4f69 100755 --- a/.assets/provision/install_kubectl.sh +++ b/.assets/provision/install_kubectl.sh @@ -24,7 +24,7 @@ retry_count=0 # try 10 times to get latest release if not provided as a parameter while [ -z "$REL" ]; do REL=$(curl -sLk https://dl.k8s.io/release/stable.txt) - ((retry_count++)) + ((retry_count++)) || true if [ $retry_count -eq 10 ]; then printf "\e[33m$APP version couldn't be retrieved\e[0m\n" >&2 exit 0 diff --git a/.assets/provision/install_miniconda.sh b/.assets/provision/install_miniconda.sh index 9f705d21..b20aa14e 100755 --- a/.assets/provision/install_miniconda.sh +++ b/.assets/provision/install_miniconda.sh @@ -22,8 +22,7 @@ done # *conda init function. function conda_init { - __conda_setup="$("$HOME/miniconda3/bin/conda" 'shell.bash' 'hook' 2>/dev/null)" - if [ $? -eq 0 ]; then + if __conda_setup="$("$HOME/miniconda3/bin/conda" 'shell.bash' 'hook' 2>/dev/null)"; then eval "$__conda_setup" else if [ -f "$HOME/miniconda3/etc/profile.d/conda.sh" ]; then diff --git a/.assets/provision/install_miniforge.sh b/.assets/provision/install_miniforge.sh index ae1288db..5cd1109a 100755 --- a/.assets/provision/install_miniforge.sh +++ b/.assets/provision/install_miniforge.sh @@ -22,8 +22,7 @@ done # *conda init function. function conda_init { - __conda_setup="$("$HOME/miniforge3/bin/conda" 'shell.bash' 'hook' 2>/dev/null)" - if [ $? -eq 0 ]; then + if __conda_setup="$("$HOME/miniforge3/bin/conda" 'shell.bash' 'hook' 2>/dev/null)"; then eval "$__conda_setup" else if [ -f "$HOME/miniforge3/etc/profile.d/conda.sh" ]; then diff --git a/.assets/provision/install_minikube.sh b/.assets/provision/install_minikube.sh index 06d28e29..4e9098de 100755 --- a/.assets/provision/install_minikube.sh +++ b/.assets/provision/install_minikube.sh @@ -39,7 +39,7 @@ fi echo $REL if type $APP &>/dev/null; then - VER=$(minikube version | grep -Po '(?<=v)[0-9\.]+$') + VER=$(minikube version | grep -Po '(?<=v)[0-9\.]+$' || true) if [ "$REL" = "$VER" ]; then printf "\e[32m$APP v$VER is already latest\e[0m\n" >&2 exit 0 diff --git a/.assets/provision/install_prek.sh b/.assets/provision/install_prek.sh index eb9b43c4..abbce705 100755 --- a/.assets/provision/install_prek.sh +++ b/.assets/provision/install_prek.sh @@ -39,7 +39,7 @@ if [ -x "$HOME/.local/bin/prek" ]; then while [ $retry_count -le $max_retries ]; do $HOME/.local/bin/prek self update >&2 [ $? -eq 0 ] && break || true - ((retry_count++)) + ((retry_count++)) || true echo "retrying... $retry_count/$max_retries" >&2 if [ $retry_count -eq $max_retries ]; then printf "\e[31mFailed to update $APP after $max_retries attempts.\e[0m\n" >&2 @@ -60,7 +60,7 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then retry_count=0 while [ ! -x "$HOME/.local/bin/prek" ] && [ $retry_count -lt 10 ]; do sh "$TMP_DIR/prek-installer.sh" - ((retry_count++)) + ((retry_count++)) || true done fi exit 0 diff --git a/.assets/provision/install_pwsh.sh b/.assets/provision/install_pwsh.sh index 2ec32413..2efdca2c 100755 --- a/.assets/provision/install_pwsh.sh +++ b/.assets/provision/install_pwsh.sh @@ -57,7 +57,7 @@ alpine) ;; arch) if pacman -Qqe paru &>/dev/null; then - user=${1:-$(id -un 1000 2>/dev/null)} + user=${1:-$(id -un 1000 2>/dev/null || true)} if ! sudo -u $user true 2>/dev/null; then if [ -n "$user" ]; then printf "\e[31;1mUser does not exist ($user).\e[0m\n" diff --git a/.assets/provision/install_smee.sh b/.assets/provision/install_smee.sh index 9bb2bf52..72307533 100755 --- a/.assets/provision/install_smee.sh +++ b/.assets/provision/install_smee.sh @@ -17,7 +17,7 @@ else retry_count=0 while ! type $APP &>/dev/null && [ $retry_count -lt 10 ]; do npm install -g smee-client - ((retry_count++)) + ((retry_count++)) || true done fi diff --git a/.assets/provision/install_tfswitch.sh b/.assets/provision/install_tfswitch.sh index 0d4a339b..c9939999 100755 --- a/.assets/provision/install_tfswitch.sh +++ b/.assets/provision/install_tfswitch.sh @@ -42,7 +42,7 @@ else retry_count=0 while ! type $APP &>/dev/null && [ $retry_count -lt 10 ]; do eval $__install - ((retry_count++)) + ((retry_count++)) || true done fi diff --git a/.assets/provision/install_uv.sh b/.assets/provision/install_uv.sh index f9adb606..29351783 100755 --- a/.assets/provision/install_uv.sh +++ b/.assets/provision/install_uv.sh @@ -40,7 +40,7 @@ if [ -x "$HOME/.local/bin/uv" ]; then while [ $retry_count -le $max_retries ]; do $HOME/.local/bin/uv self update --native-tls >&2 [ $? -eq 0 ] && break || true - ((retry_count++)) + ((retry_count++)) || true echo "retrying... $retry_count/$max_retries" >&2 if [ $retry_count -eq $max_retries ]; then printf "\e[31mFailed to update $APP after $max_retries attempts.\e[0m\n" >&2 @@ -62,7 +62,7 @@ if download_file --uri "$URL" --target_dir "$TMP_DIR"; then retry_count=0 while [ ! -x "$HOME/.local/bin/uv" ] && [ $retry_count -lt 10 ]; do sh "$TMP_DIR/install.sh" - ((retry_count++)) + ((retry_count++)) || true done fi exit 0 diff --git a/.assets/provision/install_xrdp.sh b/.assets/provision/install_xrdp.sh index d3156e9f..96f19607 100755 --- a/.assets/provision/install_xrdp.sh +++ b/.assets/provision/install_xrdp.sh @@ -15,7 +15,7 @@ SYS_ID="$(sed -En '/^ID.*(arch|fedora|debian|ubuntu|opensuse).*/{s//\1/;p;q}' /e case $SYS_ID in arch) if pacman -Qqe paru &>/dev/null; then - user=${1:-$(id -un 1000 2>/dev/null)} + user=${1:-$(id -un 1000 2>/dev/null || true)} if ! sudo -u $user true 2>/dev/null; then if [ -n "$user" ]; then printf "\e[31;1mUser does not exist ($user).\e[0m\n" @@ -31,7 +31,7 @@ arch) ;; fedora) # Load the Hyper-V kernel module - if ! [ -f "/etc/modules-load.d/hv_sock.conf" ] || [ "$(cat /etc/modules-load.d/hv_sock.conf | grep hv_sock)" = "" ]; then + if ! [ -f "/etc/modules-load.d/hv_sock.conf" ] || ! grep -q hv_sock /etc/modules-load.d/hv_sock.conf 2>/dev/null; then echo "hv_sock" >>/etc/modules-load.d/hv_sock.conf fi dnf -y install xrdp tigervnc-server diff --git a/.assets/provision/setup_profile_allusers.sh b/.assets/provision/setup_profile_allusers.sh index 59e0e27e..f26d376f 100755 --- a/.assets/provision/setup_profile_allusers.sh +++ b/.assets/provision/setup_profile_allusers.sh @@ -10,7 +10,7 @@ if [ $EUID -ne 0 ]; then fi # check if specified user exists -user=${1:-$(id -un 1000 2>/dev/null)} +user=${1:-$(id -un 1000 2>/dev/null || true)} if ! sudo -u $user true 2>/dev/null; then if [ -n "$user" ]; then printf "\e[31;1mUser does not exist ($user).\e[0m\n" diff --git a/.assets/provision/source.sh b/.assets/provision/source.sh index 5dbeb8cf..5535d22f 100755 --- a/.assets/provision/source.sh +++ b/.assets/provision/source.sh @@ -68,7 +68,7 @@ login_gh_user() { while [[ $retries -lt 5 ]] && [ -z "$token" ]; do sudo -u "$user" gh auth refresh -s admin:public_key >&2 token="$(sudo -u "$user" gh auth token 2>/dev/null)" - ((retries++)) + ((retries++)) || true done fi else @@ -83,7 +83,7 @@ login_gh_user() { sudo -u "$user" gh auth login >&2 fi token="$(sudo -u "$user" gh auth token 2>/dev/null)" - ((retries++)) + ((retries++)) || true done if [ -n "$token" ]; then @@ -152,7 +152,7 @@ download_file() { return 1 ;; *) - ((retry_count++)) + ((retry_count++)) || true echo "retrying... $retry_count/$max_retries" >&2 ;; esac @@ -260,7 +260,7 @@ get_gh_release_latest() { fi else # increment the retry count - ((retry_count++)) + ((retry_count++)) || true echo "retrying... $retry_count/$max_retries" >&2 fi done @@ -376,7 +376,7 @@ install_github_release_user() { [ -n "$latest_release" ] && break fi - ((retry_count++)) + ((retry_count++)) || true if [ $retry_count -eq 5 ]; then printf "\e[31m5/5 failed to get latest release for \e[4m%s/%s\e[0m\n" "$gh_owner" "$gh_repo" >&2 return 1 @@ -411,7 +411,7 @@ install_github_release_user() { break fi - ((retry_count++)) + ((retry_count++)) || true if [ $retry_count -eq 5 ]; then printf "\e[31m5/5 failed to download \e[1m%s\e[22m v%s\e[0m\n" "$binary_name" "$latest_release" >&2 return 1 From 134d3018632046d8bf41d62159d29aeea1e11fe5 Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 21:32:00 +0100 Subject: [PATCH 11/12] fix(sh): preserve outer scope traps in cleanup pattern Change trap pattern to save and restore outer scope traps. Pattern: local saved_return=$(trap -p RETURN) local saved_exit=$(trap -p EXIT) local cleanup="rm -rf '$tmp_dir'" [ -n "$saved_return" ] && cleanup="$cleanup; $saved_return" || cleanup="$cleanup; trap - RETURN" [ -n "$saved_exit" ] && cleanup="$cleanup; $saved_exit" || cleanup="$cleanup; trap - EXIT" trap "$cleanup" RETURN EXIT This ensures: - RETURN: Cleans up when function returns normally - EXIT: Cleans up when script exits due to set -euo pipefail failures - Trap restoration: Preserves and restores any outer scope traps Benefits: - Works correctly for both nested and direct function calls - Prevents trap conflicts between nested functions - Makes functions more reusable in different contexts - Automatic cleanup on any failure path Note: RETURN traps are per-function scope in bash, so they don't show up in 'trap -p RETURN' from nested functions. However, EXIT traps are global and must be properly saved/restored. --- .assets/provision/install_gcloud.sh | 11 ++++++++++- .assets/provision/source.sh | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.assets/provision/install_gcloud.sh b/.assets/provision/install_gcloud.sh index 377694c8..7fc43566 100755 --- a/.assets/provision/install_gcloud.sh +++ b/.assets/provision/install_gcloud.sh @@ -67,7 +67,16 @@ install_from_tarball() { fi url="https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/${archive_name}" tmp_dir="$(mktemp -d -p "$HOME")" - trap 'rm -fr "$tmp_dir"' RETURN + + # Save existing traps to restore after cleanup + local saved_return=$(trap -p RETURN) + local saved_exit=$(trap -p EXIT) + + # Create trap that cleans up and restores outer traps (if any) + local cleanup="rm -fr '$tmp_dir'" + [ -n "$saved_return" ] && cleanup="$cleanup; $saved_return" || cleanup="$cleanup; trap - RETURN" + [ -n "$saved_exit" ] && cleanup="$cleanup; $saved_exit" || cleanup="$cleanup; trap - EXIT" + trap "$cleanup" RETURN EXIT printf '\e[33mFalling back to the official Google Cloud CLI tarball.\e[0m\n' >&2 if ! download_file --uri "$url" --target_dir "$tmp_dir"; then diff --git a/.assets/provision/source.sh b/.assets/provision/source.sh index 5535d22f..c468631b 100755 --- a/.assets/provision/source.sh +++ b/.assets/provision/source.sh @@ -347,7 +347,16 @@ install_github_release_user() { # create temporary directory and set cleanup trap tmp_dir=$(mktemp -d -p "$HOME") - trap "rm -rf \"$tmp_dir\" >/dev/null 2>&1" RETURN + + # Save existing traps to restore after cleanup + local saved_return=$(trap -p RETURN) + local saved_exit=$(trap -p EXIT) + + # Create trap that cleans up and restores outer traps (if any) + local cleanup="rm -rf \"$tmp_dir\" >/dev/null 2>&1" + [ -n "$saved_return" ] && cleanup="$cleanup; $saved_return" || cleanup="$cleanup; trap - RETURN" + [ -n "$saved_exit" ] && cleanup="$cleanup; $saved_exit" || cleanup="$cleanup; trap - EXIT" + trap "$cleanup" RETURN EXIT #endregion #region get latest release version From 79a3ff664a5f5be320931028414af9dd665a9732 Mon Sep 17 00:00:00 2001 From: Szymon Osiecki Date: Sun, 8 Feb 2026 21:57:50 +0100 Subject: [PATCH 12/12] refactor(sh): improve trap cleanup pattern and fix shellcheck warnings - Separate declaration and assignment for saved_return/saved_exit (SC2155) - Add shellcheck disable directives for intentional trap expansion pattern - Use consistent rm -fr flag order across codebase - Declare all local variables upfront in install_github_release_user - Remove unnecessary output redirection and duplicate local declarations --- .assets/provision/install_gcloud.sh | 11 +---------- .assets/provision/source.sh | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/.assets/provision/install_gcloud.sh b/.assets/provision/install_gcloud.sh index 7fc43566..4e096652 100755 --- a/.assets/provision/install_gcloud.sh +++ b/.assets/provision/install_gcloud.sh @@ -67,16 +67,7 @@ install_from_tarball() { fi url="https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/${archive_name}" tmp_dir="$(mktemp -d -p "$HOME")" - - # Save existing traps to restore after cleanup - local saved_return=$(trap -p RETURN) - local saved_exit=$(trap -p EXIT) - - # Create trap that cleans up and restores outer traps (if any) - local cleanup="rm -fr '$tmp_dir'" - [ -n "$saved_return" ] && cleanup="$cleanup; $saved_return" || cleanup="$cleanup; trap - RETURN" - [ -n "$saved_exit" ] && cleanup="$cleanup; $saved_exit" || cleanup="$cleanup; trap - EXIT" - trap "$cleanup" RETURN EXIT + trap 'rm -fr "$tmp_dir"' RETURN EXIT printf '\e[33mFalling back to the official Google Cloud CLI tarball.\e[0m\n' >&2 if ! download_file --uri "$url" --target_dir "$tmp_dir"; then diff --git a/.assets/provision/source.sh b/.assets/provision/source.sh index c468631b..0a6280fd 100755 --- a/.assets/provision/source.sh +++ b/.assets/provision/source.sh @@ -297,7 +297,8 @@ find_file() { # *Function to download and install GitHub releases into user directory install_github_release_user() { local gh_owner gh_repo file_name binary_name current_version - local auth_header retry_count latest_release response http_code body file url tmp_dir binary_path + local auth_header retry_count latest_release response http_code body file url binary_path + local tmp_dir cleanup saved_return saved_exit # Parse arguments while [[ $# -gt 0 ]]; do @@ -347,15 +348,16 @@ install_github_release_user() { # create temporary directory and set cleanup trap tmp_dir=$(mktemp -d -p "$HOME") - - # Save existing traps to restore after cleanup - local saved_return=$(trap -p RETURN) - local saved_exit=$(trap -p EXIT) - - # Create trap that cleans up and restores outer traps (if any) - local cleanup="rm -rf \"$tmp_dir\" >/dev/null 2>&1" + # save existing traps to restore after cleanup + saved_return="$(trap -p RETURN)" + saved_exit="$(trap -p EXIT)" + # create trap that cleans up and restores outer traps (if any) + # shellcheck disable=SC2016 # $tmp_dir should not expand here + cleanup='rm -fr "$tmp_dir"' + # restore saved traps if they exist, otherwise just remove the trap for that signal [ -n "$saved_return" ] && cleanup="$cleanup; $saved_return" || cleanup="$cleanup; trap - RETURN" [ -n "$saved_exit" ] && cleanup="$cleanup; $saved_exit" || cleanup="$cleanup; trap - EXIT" + # shellcheck disable=SC2064 # We want $cleanup to expand now trap "$cleanup" RETURN EXIT #endregion