MAUI Forge — Meu segundo projeto de código aberto e por que ele existe
"Conheça o MAUI Forge, uma ferramenta CLI de código aberto para automatizar o versionamento, a compilação e o gerenciamento de dispositivos em projetos .NET MAUI."
MAUI Forge — Meu segundo projeto de código aberto, e por que ele existe
Esta semana, tornei o MAUI Forge código aberto no GitHub. É o meu segundo projeto público e, assim como o primeiro — Papiro, um conversor nativo de HTML para PDF para .NET MAUI — esta ferramenta nasceu de pura necessidade. Ela resolve uma dor de cabeça semanal recorrente que eu simplesmente não podia mais ignorar.
O problema: 2.700 linhas de PowerShell
Na CW Software, mantenho mais de uma dúzia de aplicativos .NET MAUI. Toda vez que eu preparava um lançamento — fosse um pequeno ajuste de layout ou uma funcionalidade importante — eu repetia o mesmo ritual tedioso:
- Abrir o
Info.plist, atualizarCFBundleShortVersionStringeCFBundleVersion. - Abrir o
AndroidManifest.xml, atualizarandroid:versionNameeandroid:versionCode. - Abrir o
.csproj, atualizarApplicationDisplayVersioneApplicationVersion. - Verificar se nenhum número foi digitado incorretamente nos três arquivos.
- Fazer o commit, tag e build.
Multiplique isso por 12 aplicativos em iOS e Android, e você verá por que a automação se tornou uma necessidade.
O Risco Manual
O versionamento inconsistente entre os manifestos específicos da plataforma e o arquivo do projeto é uma das maneiras mais fáceis de quebrar um pipeline de CI/CD ou causar erros de implantação confusos na App Store/Play Store.
A primeira iteração foi um script massivo em PowerShell — maui-version.ps1 — com quase 2.700 linhas. Embora funcionasse, era difícil de manter, impossível de distribuir facilmente e estritamente limitado ao Windows.
A reescrita em C#
No início de 2025, decidi reescrever a ferramenta do zero em C#. Isso me permitiu aproveitar o melhor do ecossistema .NET para desenvolvimento de CLI:
- Spectre.Console: Alimenta toda a interface do usuário, incluindo tabelas, menus interativos, painéis coloridos e indicadores de progresso.
- Microsoft.Extensions.DependencyInjection: Usado para manter os serviços limpos e organizados.
- dotnet tool: Permite a instalação em uma única linha em qualquer plataforma (Windows, macOS, Linux).
O resultado é o MAUI Forge: uma ferramenta de terminal interativa que varre um diretório, identifica todos os aplicativos MAUI, exibe suas versões atuais e status do git, e gerencia atualizações sem edição manual de arquivos.
dotnet tool install -g CwSoftware.MauiForge
maui-forge --path ~/projects
MAUI Forge na prática
Ao abrir o terminal e digitar maui-forge, você é recebido com uma tabela abrangente de seus projetos:
iOS Android Branch Git
── Apps (12) ──────────────────────────────────────────────────────────────
+ MyApp 1.4.3 #19 1.4.3 #19 main clean
* ShippingApp 2.0.0 #103 2.0.0 #103 release/2.0 +2
* OtherApp 1.0.0 #5 ! 1.0.1 #6 feature/x ~
! LegacyApp 2.1.0 #40 2.1.0 #40 main -3
Ao selecionar um aplicativo, você acessa o painel de ações:
-- Version ──────────────────────────────────────────────────────
v+ Increment Version + Build 2.0.0 -> 2.0.1 #103 -> #104
b+ Increment Build only #103 -> #104
~~ Set version manually
<> Sync iOS -- Android
-- iOS ──────────────────────────────────────────────────────────
[#] Archive iOS (Release) Apple Distribution
[>] Run iOS Device Cezar's iPhone
-- Android ──────────────────────────────────────────────────────
[>] Run Android Device R5CX208XXXX
[#] Publish Android (Release) net9.0-android
O comando v+ atualiza todos os três arquivos necessários simultaneamente, fornece uma prévia para confirmação e pode, opcionalmente, realizar um commit no git com uma mensagem padrão:
chore: bump version to 2.0.1 #104 (ShippingApp)
Resolvendo a dor de cabeça do Mac + VS Code
Eu costumo desenvolver no Windows, mas dependo de um Mac para builds de iOS — seja via SSH ou localmente. Embora o VS Code com a extensão MAUI seja uma configuração sólida, ele tem uma limitação recorrente: não permite alternar facilmente entre dispositivos de destino ou simuladores por projeto.
Para trocar de simulador, muitas vezes você precisa vasculhar as configurações de inicialização, encontrar o UDID e montar manualmente o comando correto. Isso é gerenciável para um projeto, mas frustrante para doze.
MAUI Forge simplifica isso. Quando você seleciona "Run iOS Device", um menu dinâmico aparece:
> iPhone 16 Pro (simulator)
> iPhone 15 (simulator)
> Cezar's iPhone — physical device ✓
> iPad Pro 13" (simulator)
> iPad Air (3rd gen) — iOS 16 ✓
Nos bastidores, ele executa xcrun xctrace list devices, analisa a lista e aciona dotnet build -t:Run com o UDID correto. Ele até lembra o dispositivo selecionado por projeto.
Resgatando hardware antigo
Um detalhe específico que me salvou: iPads antigos. O VS Code normalmente lista apenas dispositivos que executam a versão mais recente compatível do iOS. Eu tenho um iPad Air antigo que a Apple não suporta mais com atualizações. O VS Code simplesmente o ignora.
Como o MAUI Forge usa a saída completa do xcrun, ele identifica todos os dispositivos conectados e confiáveis, independentemente da versão do iOS. Isso me permite continuar depurando em hardware mais antigo — exatamente o tipo de dispositivo que meus usuários ainda usam em campo.
Distribuição como uma dotnet tool
Distribuir o projeto como uma dotnet tool foi uma escolha estratégica. Como todo desenvolvedor MAUI já possui o SDK do .NET, a instalação é simples:
Configuração Rápida
Para começar ou manter sua versão atualizada, use estes comandos:
dotnet tool install -g CwSoftware.MauiForge
dotnet tool update -g CwSoftware.MauiForge
O processo de publicação no NuGet é automatizado via GitHub Actions. Sempre que eu crio uma tag de versão (ex: v1.0.5), o workflow aciona o empacotamento e o upload:
- name: Pack and push
run: |
dotnet pack -p:Version=${{ env.VERSION }} -o ./nupkg
dotnet nuget push ./nupkg/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
A ferramenta também inclui uma verificação discreta na inicialização para notificá-lo se uma versão mais recente estiver disponível no NuGet, garantindo que você permaneça atualizado sem interromper seu fluxo de trabalho.
Estrutura do Projeto
Para os interessados em contribuir ou explorar o código-fonte, a arquitetura foi projetada para ser simples:
src/MauiForge/
├── Program.cs ← Ponto de entrada, container DI, loop principal
├── Models/ ← Records imutáveis (AppEntry, GitStatus, etc.)
├── Services/ ← Lógica para Descoberta, Versionamento, Git e Build
└── UI/ ← Telas e lógica do Spectre.Console
Usei records imutáveis para os modelos; a UI nunca altera um AppEntry. Em vez disso, ela atualiza os dados da fonte quando ocorrem mudanças. As configurações persistentes (como seu dispositivo preferido) são armazenadas em ~/.maui-forge.state.json, mantendo as pastas do seu projeto limpas.
O que vem por aí
O roadmap para o MAUI Forge inclui vários recursos para otimizar ainda mais a experiência do desenvolvedor:
- Suporte para múltiplos Macs configurados (ideal para máquinas separadas de CI/Build).
- Integração de changelog: visualize os commits desde o último aumento de versão.
- Geração automática de notas de lançamento dentro das tags do git.
Se você usa .NET MAUI e quer eliminar a sobrecarga do versionamento manual, experimente. Estou buscando feedback ativamente, então issues e PRs são muito bem-vindos!
- GitHub: CW-Software-Apps/maui-forge
- NuGet: CwSoftware.MauiForge
