Monorepositório com Swift: organização de código para projetos iOS e macOS
No desenvolvimento moderno para iOS e macOS, a escolha da estratégia de gerenciamento de código impacta diretamente a velocidade de desenvolvimento, a qualidade da refatoração e a conveniência do trabalho em equipe. A abordagem tradicional com vários repositórios separados (polirepositório) frequentemente leva à duplicação de dependências, dificuldades com sincronização de versões e fragmentação da base de código. Uma alternativa é o monorepositório (monorepo) — um armazenamento único para todos os módulos, bibliotecas e aplicações do projeto. Neste artigo, usando Swift e o ecossistema Apple como exemplo, vamos analisar como organizar um monorepositório, quais ferramentas usar e quais armadilhas considerar.
O que é um monorepositório e por que ele é necessário em projetos Swift
Monorepositório é uma estratégia de gerenciamento de versão onde todo o código do projeto (várias aplicações, bibliotecas, configurações) é armazenado em um único repositório Git. No contexto do Swift, isso significa que você pode ter em um único repositório:
- Aplicativo iOS (por exemplo,
MyApp) - Aplicativo macOS (
MyMacApp) - Biblioteca compartilhada de modelos (
CoreModels) - Camada de rede (
Networking) - Componentes de UI (
UIComponents) - Testes e scripts de CI
Vantagens do monorepositório para projetos Swift:
- Versão única de dependências — todos os módulos usam a mesma versão da biblioteca (por exemplo,
AlamofireouSwiftUI), eliminando conflitos. - Commits atômicos — alterações na API da biblioteca e seu uso no aplicativo são registradas em um único commit, simplificando o code review e o rollback.
- Simplificação da refatoração — você pode renomear um método público em um módulo e corrigir imediatamente todos os locais de chamada no mesmo repositório.
- CI/CD compartilhado — um único pipeline para construir e testar todos os componentes.
Ferramentas para trabalhar com monorepositório em Swift
No ecossistema Apple, existem duas ferramentas principais para organizar um monorepositório: Swift Package Manager (SPM) e Tuist. Vamos analisar suas características.
Swift Package Manager (SPM)
SPM é um gerenciador de pacotes integrado que é excelente para monorepositórios. Você define os módulos através do Package.swift, e o Xcode resolve as dependências automaticamente. Exemplo de estrutura:
MyMonorepo/├── Package.swift├── Sources/│ ├── CoreModels/│ │ └── Models.swift│ ├── Networking/│ │ └── APIClient.swift│ └── UIComponents/│ └── ButtonView.swift├── Apps/│ ├── MyApp/│ │ └── (projeto iOS)│ └── MyMacApp/│ └── (projeto macOS)└── Tests/ ├── CoreModelsTests/ └── NetworkingTests/Exemplo de Package.swift para tal monorepositório:
// swift-tools-version:5.9import PackageDescription
let package = Package( name: "MyMonorepo", platforms: [ .iOS(.v16), .macOS(.v13) ], products: [ .library(name: "CoreModels", targets: ["CoreModels"]), .library(name: "Networking", targets: ["Networking"]), .library(name: "UIComponents", targets: ["UIComponents"]), ], dependencies: [ .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.8.0") ], targets: [ .target(name: "CoreModels"), .target( name: "Networking", dependencies: ["CoreModels", "Alamofire"] ), .target( name: "UIComponents", dependencies: ["CoreModels"] ), .testTarget(name: "CoreModelsTests", dependencies: ["CoreModels"]), .testTarget(name: "NetworkingTests", dependencies: ["Networking"]), ])