Last active
December 9, 2025 02:55
-
-
Save biliboss/a068100ca7bbc198cfb27b33949b26ce to your computer and use it in GitHub Desktop.
MacBook Setup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| curl -sL https://gist.githubusercontent.com/biliboss/a068100ca7bbc198cfb27b33949b26ce/raw | bash |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Ótima pergunta! Erros no meio do processo são comuns. Vou mostrar como cada abordagem lida com isso: | |
| ## 🔴 Script Tradicional (Seu atual) | |
| **PROBLEMA:** Com `set -e`, para no primeiro erro e deixa sistema em estado inconsistente[1] | |
| ```bash | |
| #!/bin/bash | |
| set -e # Para no primeiro erro ❌ | |
| brew install git # ✅ OK | |
| brew install xyz-nao-existe # ❌ ERRO - script para aqui | |
| brew install gh # 🚫 Nunca executa | |
| brew install uv # 🚫 Nunca executa | |
| ``` | |
| **RECUPERAÇÃO:** | |
| - Comentar linhas que já funcionaram | |
| - Executar de novo | |
| - Muito manual 😓 | |
| *** | |
| ## ✅ Brewfile (Idempotente e Seguro)[2][3] | |
| **VANTAGEM:** Homebrew é **idempotente** - pode executar quantas vezes quiser | |
| ```bash | |
| # Primeira execução | |
| brew bundle install | |
| # ✅ git installed | |
| # ✅ gh installed | |
| # ❌ xyz-failed (erro de rede) | |
| # ✅ uv installed | |
| # Resultado: 3 de 4 instalados | |
| # Segunda execução (mesmos comandos) | |
| brew bundle install | |
| # ⏭️ git já instalado (pula) | |
| # ⏭️ gh já instalado (pula) | |
| # ❌ xyz-failed (tenta de novo) | |
| # ⏭️ uv já instalado (pula) | |
| ``` | |
| **RECUPERAÇÃO AUTOMÁTICA:** | |
| ```bash | |
| # Apenas execute de novo - continua de onde parou! | |
| brew bundle install | |
| # Verificar o que falta | |
| brew bundle check | |
| # Ver detalhes | |
| brew bundle list --all | |
| ``` | |
| **ERRO HANDLING:** | |
| - ✅ Não para no primeiro erro | |
| - ✅ Continua instalando o resto | |
| - ✅ Mostra relatório no final | |
| - ✅ Re-executável sem problemas | |
| *** | |
| ## ✅ chezmoi (Com Preview e Dry-Run)[4][5] | |
| **PROTEÇÕES BUILT-IN:** | |
| ```bash | |
| # 1. SEMPRE fazer dry-run primeiro | |
| chezmoi diff | |
| # Mostra EXATAMENTE o que vai mudar | |
| # 2. Preview antes de aplicar | |
| chezmoi apply --dry-run --verbose | |
| # Simula sem mudar nada | |
| # 3. Aplicar com confirmação | |
| chezmoi apply --verbose | |
| # Avisa antes de sobrescrever arquivos modificados | |
| # 4. BACKUP automático antes de qualquer mudança | |
| chezmoi apply | |
| # ⚠️ warning: ~/.zshrc has changed since chezmoi last wrote it | |
| # ⚠️ continue? [y/N] | |
| ``` | |
| **SE DER ERRO:** | |
| ```bash | |
| # 1. Ver o que mudou | |
| chezmoi diff | |
| # 2. Desfazer aplicação (se Git configurado) | |
| cd ~/.local/share/chezmoi | |
| git log # Ver histórico | |
| chezmoi apply --source-path <commit-anterior> | |
| # 3. Resetar tudo (último recurso) | |
| rm -rf ~/.local/share/chezmoi | |
| chezmoi init --apply <seu-repo> | |
| ``` | |
| **BACKUP AUTOMÁTICO:**[4] | |
| chezmoi cria backup em `~/.config/chezmoi/chezmoistate.boltdb` antes de mudanças | |
| *** | |
| ## 🛡️ Abordagem Mais Segura (Recomendado) | |
| Combine **Brewfile + chezmoi com proteções**: | |
| ```bash | |
| #!/bin/bash | |
| # install.sh - Setup seguro e recuperável | |
| set -e # Para em erros críticos | |
| # ============================================ | |
| # FUNÇÃO: Executar com retry | |
| # ============================================ | |
| retry() { | |
| local max_attempts=3 | |
| local attempt=1 | |
| while [ $attempt -le $max_attempts ]; do | |
| echo "Tentativa $attempt/$max_attempts: $@" | |
| if "$@"; then | |
| return 0 | |
| fi | |
| echo "Falhou. Tentando novamente em 5s..." | |
| sleep 5 | |
| ((attempt++)) | |
| done | |
| echo "❌ Falhou após $max_attempts tentativas: $@" | |
| return 1 | |
| } | |
| # ============================================ | |
| # PASSO 1: Homebrew (idempotente) | |
| # ============================================ | |
| echo "📦 Instalando Homebrew..." | |
| if ! command -v brew &> /dev/null; then | |
| retry /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" | |
| else | |
| echo "✓ Homebrew já instalado" | |
| fi | |
| # ============================================ | |
| # PASSO 2: Brewfile (continua em erros) | |
| # ============================================ | |
| echo "📦 Instalando pacotes do Brewfile..." | |
| if [ -f ~/.Brewfile ]; then | |
| # Não para se um pacote falhar | |
| brew bundle install --global --no-lock || { | |
| echo "⚠️ Alguns pacotes falharam. Verifique o log acima." | |
| echo "Execute 'brew bundle install --global' novamente para tentar de novo." | |
| } | |
| # Mostrar o que falta | |
| brew bundle check --global || echo "⚠️ Alguns itens não foram instalados" | |
| else | |
| echo "⚠️ ~/.Brewfile não encontrado" | |
| fi | |
| # ============================================ | |
| # PASSO 3: chezmoi (com backup) | |
| # ============================================ | |
| echo "🔧 Configurando dotfiles com chezmoi..." | |
| if ! command -v chezmoi &> /dev/null; then | |
| retry brew install chezmoi | |
| fi | |
| # SEMPRE fazer diff primeiro | |
| if [ -d ~/.local/share/chezmoi ]; then | |
| echo "📋 Mostrando mudanças..." | |
| chezmoi diff || true | |
| echo "" | |
| read -p "Aplicar mudanças? [y/N] " -n 1 -r | |
| echo | |
| if [[ $REPLY =~ ^[Yy]$ ]]; then | |
| chezmoi apply --verbose | |
| else | |
| echo "⏭️ Pulando aplicação de dotfiles" | |
| fi | |
| else | |
| echo "⚠️ chezmoi não inicializado. Execute:" | |
| echo " chezmoi init --apply <seu-github-username>" | |
| fi | |
| # ============================================ | |
| # PASSO 4: Verificação Final | |
| # ============================================ | |
| echo "" | |
| echo "✅ VERIFICAÇÃO FINAL" | |
| echo "====================" | |
| # Checar Brewfile | |
| echo "📦 Brewfile:" | |
| brew bundle check --global && echo " ✅ Tudo instalado" || echo " ⚠️ Alguns itens faltando" | |
| # Checar chezmoi | |
| echo "🔧 Dotfiles:" | |
| chezmoi verify && echo " ✅ Sincronizados" || echo " ⚠️ Diferenças detectadas" | |
| # Checar comandos críticos | |
| echo "🛠️ Comandos:" | |
| for cmd in git gh uv volta node python3; do | |
| if command -v $cmd &> /dev/null; then | |
| echo " ✅ $cmd" | |
| else | |
| echo " ❌ $cmd (faltando)" | |
| fi | |
| done | |
| echo "" | |
| echo "🎉 Setup concluído!" | |
| echo "Em caso de erros, execute novamente: ./install.sh" | |
| ``` | |
| *** | |
| ## 🔄 Recuperação de Erros Comuns | |
| ### **1. Erro de Rede (Download falhou)** | |
| ```bash | |
| # Homebrew retenta automaticamente | |
| brew bundle install --global | |
| # Se continuar falhando | |
| brew update | |
| brew doctor | |
| brew bundle install --global | |
| ``` | |
| ### **2. Permissões Negadas** | |
| ```bash | |
| # Corrigir permissões Homebrew | |
| sudo chown -R $(whoami) /opt/homebrew | |
| # Refazer instalação | |
| brew bundle install --global | |
| ``` | |
| ### **3. Dependência Faltando** | |
| ```bash | |
| # Instalar Xcode Command Line Tools | |
| xcode-select --install | |
| # Depois continuar | |
| brew bundle install --global | |
| ``` | |
| ### **4. chezmoi Sobrescreveu Arquivo Errado** | |
| ```bash | |
| # Se tinha Git | |
| cd ~/.local/share/chezmoi | |
| git log | |
| git checkout HEAD~1 -- dot_zshrc | |
| chezmoi apply | |
| # Se não tinha Git - restaurar de backup macOS | |
| open ~/Library/Mobile\ Documents/com~apple~CloudDocs/ | |
| # ou usar Time Machine | |
| ``` | |
| ### **5. Script Parou no Meio** | |
| ```bash | |
| # Com Brewfile - apenas execute de novo! | |
| brew bundle install --global | |
| # Com script - comente o que já foi feito | |
| # Ou melhor: use Brewfile :) | |
| ``` | |
| *** | |
| ## 💡 Melhor Prática: Instalação em Camadas | |
| ```bash | |
| # 1. Essencial (deve funcionar 100%) | |
| brew install git gh | |
| # 2. Core Tools (pode falhar alguns) | |
| brew bundle install --file=Brewfile.core || true | |
| # 3. Optional Apps (não crítico) | |
| brew bundle install --file=Brewfile.apps || true | |
| # 4. Dotfiles (com confirmação) | |
| chezmoi init --apply <repo> | |
| ``` | |
| **Brewfile.core:** | |
| ```ruby | |
| brew "git" | |
| brew "gh" | |
| brew "uv" | |
| brew "volta" | |
| ``` | |
| **Brewfile.apps:** | |
| ```ruby | |
| cask "orbstack" | |
| cask "raycast" | |
| cask "iterm2" | |
| ``` | |
| *** | |
| ## ✅ Resumo: Qual Usar? | |
| | Situação | Ferramenta | Motivo | | |
| |----------|-----------|--------| | |
| | **Primeira vez** | Brewfile + chezmoi | Idempotente, seguro, re-executável [2] | | |
| | **Erro no meio** | Re-executar `brew bundle` | Continua de onde parou | | |
| | **Testar mudanças** | `chezmoi diff` primeiro | Preview sem riscos | | |
| | **Rollback** | Git no chezmoi | Desfazer mudanças | | |
| | **Script customizado** | Apenas lógica específica | Use Brewfile para pacotes | | |
| **Resposta direta:** Use **Brewfile** - ele é **idempotente** e **continua em erros**. Scripts param no primeiro problema. 🎯 | |
| Fontes | |
| [1] Interrupted install does not gracefully recover · Issue #395 · Homebrew/brew https://github.com/Homebrew/brew/issues/395 | |
| [2] run "run_once_install-packages.sh" again when another ... https://github.com/twpayne/chezmoi/issues/401 | |
| [3] brew install and brew upgrade should be idempotent #11393 https://github.com/Homebrew/brew/issues/11393 | |
| [4] After use "chezmoi -v apply", can I recovery my file? #1779 https://github.com/twpayne/chezmoi/issues/1779 | |
| [5] How to reset chezmoi #3247 https://github.com/twpayne/chezmoi/discussions/3247 | |
| [6] brew(1) – The Missing Package Manager for macOS (or ... https://docs.brew.sh/Manpage | |
| [7] Idempotent setup instructions · Issue #559 · Homebrew/install https://github.com/Homebrew/install/issues/559 | |
| [8] separating Brewfiles and loading them in chunks https://stackoverflow.com/questions/79487066/separating-brewfiles-and-loading-them-in-chunks | |
| [9] Syncing Homebrew Installs - weblog.masukomi.org https://weblog.masukomi.org/2022/09/07/syncing-homebrew-installs/ | |
| [10] Explanation for brew install vs. bundle install needed ... https://stackoverflow.com/questions/28568884/explanation-for-brew-install-vs-bundle-install-needed-for-pgsql-error-how-to |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # setup-biliboss.sh — Setup macOS/MacBook (M-series) para desenvolvimento | |
| # | |
| # Instala e configura: | |
| # - Homebrew, Python 3.12, UV, pipx | |
| # - Ferramentas: Node.js, Git, wget, curl, jq, tree | |
| # - Aplicativos via Homebrew Casks: OrbStack, iTerm2, Rectangle, Windsurf | |
| # - Fonts para desenvolvimento | |
| # - Configurações macOS | |
| # | |
| # Uso: | |
| # ./setup-biliboss.sh | |
| # | |
| set -euo pipefail | |
| GREEN='\033[0;32m' | |
| BLUE='\033[0;34m' | |
| YELLOW='\033[1;33m' | |
| NC='\033[0m' | |
| print_step() { echo -e "${BLUE}▶ $1${NC}"; } | |
| print_success(){ echo -e "${GREEN}✓ $1${NC}"; echo ""; } | |
| print_info() { echo -e "${YELLOW}ℹ $1${NC}"; } | |
| retry() { | |
| local max_attempts=${1:-3} | |
| shift | |
| local attempt=1 | |
| until "$@"; do | |
| if (( attempt >= max_attempts )); then | |
| print_info "Comando falhou após $attempt tentativas: $*" | |
| return 1 | |
| fi | |
| print_info "Falhou. Tentando novamente em 5s... ($attempt/$max_attempts)" | |
| sleep 5 | |
| ((attempt++)) | |
| done | |
| return 0 | |
| } | |
| install_brew() { | |
| print_step "Verificando Homebrew..." | |
| if ! command -v brew &>/dev/null; then | |
| print_info "Instalando Homebrew..." | |
| retry 3 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" | |
| echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile | |
| eval "$(/opt/homebrew/bin/brew shellenv)" | |
| print_success "Homebrew instalado!" | |
| else | |
| print_success "Homebrew já instalado!" | |
| fi | |
| } | |
| brew_update_and_install() { | |
| print_step "Atualizando Homebrew..." | |
| brew update | |
| print_success "Homebrew atualizado!" | |
| } | |
| brew_install_formulae() { | |
| local pkgs=(python@3.12 git node wget curl jq tree) | |
| print_step "Instalando formulas essenciais: ${pkgs[*]}..." | |
| brew install "${pkgs[@]}" | |
| print_success "Fórmulas instaladas!" | |
| } | |
| brew_install_cask_apps() { | |
| local apps=(orbstack iterm2 rectangle windsurf) | |
| print_step "Instalando aplicativos via Cask: ${apps[*]}..." | |
| for app in "${apps[@]}"; do | |
| if ! brew list --cask "$app" &>/dev/null; then | |
| brew install --cask "$app" || print_info "Falha ao instalar $app — talvez baixe manualmente" | |
| else | |
| print_info "$app já instalado" | |
| fi | |
| done | |
| print_success "Casks processados!" | |
| } | |
| install_python_tools() { | |
| print_step "Instalando ferramentas Python: uv, pipx +ensurepath..." | |
| brew install uv pipx | |
| pipx ensurepath | |
| print_success "Ferramentas Python instaladas!" | |
| } | |
| install_fonts() { | |
| print_step "Instalando fonts para desenvolvimento..." | |
| brew tap homebrew/cask-fonts | |
| brew install --cask font-fira-code font-jetbrains-mono font-cascadia-code font-hack-nerd-font | |
| print_success "Fonts instaladas!" | |
| } | |
| apply_macos_configs() { | |
| print_step "Aplicando configurações do macOS..." | |
| defaults write com.apple.finder AppleShowAllFiles -bool true | |
| defaults write NSGlobalDomain AppleShowAllExtensions -bool true | |
| defaults write com.apple.finder FXEnableExtensionChangeWarning -bool false | |
| killall Finder && print_success "Configurações do Finder aplicadas!" | |
| } | |
| configure_git() { | |
| print_step "Configurando Git global..." | |
| git config --global user.name "Gabriel Fonseca" | |
| git config --global user.email "gabryelfs@gmail.com" | |
| print_success "Git configurado para Gabriel Fonseca <gabryelfs@gmail.com>!" | |
| } | |
| post_install_instructions() { | |
| cat << EOF | |
| ============================================ | |
| ✨ CONFIGURAÇÃO CONCLUÍDA! ✨ | |
| ============================================ | |
| Algumas coisas para revisar manualmente: | |
| • Caso queira mudar o usuário/email do Git: | |
| git config --global user.name "Outro Nome" | |
| git config --global user.email "outro-email@example.com" | |
| • Reinicie seu terminal para aplicar PATH / zprofile. | |
| EOF | |
| } | |
| main() { | |
| print_step "Iniciando configuração do MacBook para desenvolvimento..." | |
| install_brew | |
| brew_update_and_install | |
| brew_install_formulae | |
| install_python_tools | |
| brew_install_cask_apps | |
| install_fonts | |
| apply_macos_configs | |
| configure_git | |
| post_install_instructions | |
| print_success "Setup concluído!" | |
| } | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment