Skip to content

Instantly share code, notes, and snippets.

@biliboss
Last active December 9, 2025 02:55
Show Gist options
  • Select an option

  • Save biliboss/a068100ca7bbc198cfb27b33949b26ce to your computer and use it in GitHub Desktop.

Select an option

Save biliboss/a068100ca7bbc198cfb27b33949b26ce to your computer and use it in GitHub Desktop.
MacBook Setup
curl -sL https://gist.githubusercontent.com/biliboss/a068100ca7bbc198cfb27b33949b26ce/raw | bash
Ó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
#!/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