Use cargo-dist quando você mantém uma aplicação ou CLI Rust e precisa transformar uma tag em binários instaláveis para Linux, macOS e Windows sem manter toda a matriz de release à mão. O fluxo recomendado é instalar uma versão fixada da ferramenta, inicializar a configuração, revisar o plano gerado, commitar a pipeline e validar cada artefato com smoke tests antes de anunciar o release.
cargo install cargo-dist --locked
cargo dist init
cargo dist plan
Os comandos exatos e o formato da configuração podem mudar entre versões. Antes de automatizar o projeto, execute cargo dist --help, consulte a documentação da versão instalada e mantenha a ferramenta pinada na CI. O ganho do cargo-dist não é “apertar um botão e confiar”: é padronizar uma linha de montagem que continua sob responsabilidade do time.
Resposta rápida: quando cargo-dist vale a pena
| Situação | Recomendação |
|---|---|
| CLI interna para um único servidor Linux | Uma pipeline simples pode bastar |
| CLI pública para Linux, macOS e Windows | cargo-dist tende a reduzir trabalho repetitivo |
| Projeto oferece binários, checksums e instaladores | Forte caso de uso para cargo-dist |
| Biblioteca publicada somente no crates.io | Normalmente não é o foco principal da ferramenta |
| Aplicação com dependências nativas complexas | Use, mas valide target por target em runners adequados |
| Produto exige assinatura formal e compliance | Integre etapas próprias; não suponha que a configuração padrão cobre tudo |
A ferramenta é especialmente útil depois que uma CLI construída com Clap deixa de ser um experimento local. Nesse momento, o usuário não quer conhecer sua toolchain: quer baixar, instalar, executar --version e começar a trabalhar.
O problema que cargo-dist resolve
Publicar um binário parece fácil até o projeto precisar suportar mais de uma plataforma. Uma release minimamente profissional pode exigir:
- compilar targets Linux GNU e/ou musl;
- gerar binários para macOS Intel e Apple Silicon;
- compilar e empacotar no Windows;
- nomear arquivos de forma consistente;
- criar
.tar.gz,.zipou outros pacotes; - calcular checksums;
- produzir instaladores shell e PowerShell;
- anexar artefatos à release do repositório;
- manter permissões executáveis;
- documentar versão, commit e target;
- testar o arquivo baixado, não apenas o código-fonte.
É possível escrever tudo isso manualmente em GitHub Actions, Gitea Actions ou outro sistema. O custo aparece na manutenção: YAML duplicado, targets divergentes, scripts diferentes por sistema operacional e detalhes de empacotamento que só falham no dia da release.
O cargo-dist lê os metadados do projeto e gera uma estratégia de distribuição mais padronizada. Ele se encaixa no processo mais amplo de release engineering em Rust, que inclui versionamento, changelog, builds reproduzíveis, supply chain e rollback.
Pré-requisitos antes de inicializar
Não comece pela ferramenta. Comece pelo produto que será distribuído.
Confirme primeiro:
- o workspace compila com
cargo build --locked --release; - testes e lints passam na toolchain oficial;
- o binário responde
--versione--help; Cargo.lockestá versionado para a aplicação ou CLI;- o pacote possui nome, versão, licença e repositório coerentes;
- os targets oficialmente suportados estão definidos;
- existe ao menos um smoke test representativo;
- segredos de assinatura ou publicação ficam no cofre da CI, nunca no repositório.
Um ponto importante é a versão. O release precisa ter uma fonte de verdade clara — normalmente a versão do pacote e uma tag compatível com a convenção adotada. Se workspace e tags discordarem, a automação apenas tornará o erro mais rápido.
Antes de distribuir, rode também cargo-audit e considere as políticas de cargo-deny e SBOM. Empacotar bem uma dependência vulnerável não torna o release seguro.
Instalação e configuração inicial
Para uma estação de manutenção:
cargo install cargo-dist --locked
cargo dist --version
cargo dist --help
Em ambientes reproduzíveis, fixe uma versão homologada em vez de instalar “a mais recente” em toda execução:
cargo install cargo-dist --version X.Y.Z --locked
Substitua X.Y.Z pela versão aprovada pelo projeto. O pin evita que uma mudança da própria ferramenta altere a pipeline no mesmo commit em que o código permaneceu igual.
Na raiz do repositório, inicialize a configuração:
cargo dist init
O assistente pode perguntar sobre targets, instaladores, provedor de CI e outras opções suportadas pela versão instalada. Não aceite tudo automaticamente. Se o projeto não testa Windows, não anuncie Windows como suportado apenas porque a matriz consegue compilar. Suporte significa que o time consegue reproduzir, testar e corrigir problemas naquela plataforma.
Depois, revise os arquivos criados ou modificados:
git status --short
git diff -- .github Cargo.toml dist-workspace.toml
O local exato da configuração depende da geração e da versão do cargo-dist. Trate o diff produzido como código: revise permissões, eventos que disparam publicação, versões de actions, uso de secrets e escopo dos tokens.
Use cargo dist plan antes de publicar
Uma das práticas mais úteis é inspecionar o plano sem realizar um release real:
cargo dist plan
O plano ajuda a responder:
- quais pacotes e binários serão distribuídos;
- quais targets entram na matriz;
- quais arquivos serão produzidos;
- quais instaladores ou pacotes estão previstos;
- se o nome e a versão esperados foram detectados;
- se algum artefato importante ficou de fora.
Salve a saída durante a primeira implantação e compare com mudanças futuras. Quando alguém adiciona outro binário ao workspace, altera features default ou muda targets, o plano oferece uma revisão mais legível do impacto de distribuição.
Para CLIs com features opcionais, seja explícito sobre o conjunto compilado. Um executável gerado sem TLS, banco ou backend esperado pode compilar perfeitamente e ainda assim ser inútil para o usuário. O mesmo risco aparece em compilação condicional com cfg e features: a matriz precisa testar o produto que será entregue, não uma combinação acidental.
Targets: nativo, cross-compilation e dependências do sistema
Rust facilita cross-compilation, mas o ecossistema ao redor do binário pode complicar o processo. Uma aplicação puramente Rust tende a viajar melhor do que um projeto ligado a OpenSSL, bibliotecas C, drivers, frameworks gráficos ou SDKs específicos.
Para cada target, pergunte:
- existe linker disponível no runner?
- alguma dependência executa
build.rse procura headers do sistema? - o artefato depende de glibc, musl ou DLLs externas?
- o binário precisa de assinatura do sistema operacional?
- conseguimos executar um smoke test no sistema de destino?
O cargo-zigbuild pode simplificar vários targets Linux, mas não elimina a necessidade de testar o binário resultante. Cross-compilar é produzir; validar é executar em um ambiente compatível.
Para macOS e Windows, runners nativos costumam ser o caminho mais previsível quando há assinatura, empacotamento específico ou dependências nativas. Para Linux, escolha conscientemente entre GNU e musl. Um binário musl pode ser mais portátil em certos cenários, mas DNS, TLS e bibliotecas ligadas exigem teste real.
Binários pré-compilados versus cargo install
Os dois canais resolvem necessidades diferentes:
| Canal | Quem compila | Melhor para |
|---|---|---|
cargo install | o usuário | Desenvolvedores com toolchain Rust |
| binário da release | o mantenedor/CI | Usuários finais e ambientes sem Rust |
| pacote de sistema | mantenedor ou distribuidor | Gestão centralizada em servidores e desktops |
| imagem de container | pipeline do projeto | Serviços e jobs isolados |
O guia de cargo install explica o primeiro caminho. cargo-dist fortalece o segundo. Uma boa CLI pública pode oferecer ambos:
cargo install --locked minha-cli
ou:
curl --proto '=https' --tlsv1.2 -LsSf \
https://exemplo.invalid/minha-cli/installer.sh | sh
O segundo comando é apenas ilustrativo. Nunca publique um instalador por curl | sh sem HTTPS, revisão do script, origem estável e instrução alternativa para baixar e inspecionar o arquivo. Em ambientes sensíveis, disponibilize checksum, assinatura e instalação manual documentada.
CI: tag, permissões e princípio do menor privilégio
A configuração gerada precisa publicar somente quando o evento correto ocorrer. Em geral, releases são associadas a tags, não a qualquer push na branch principal. Revise:
- padrão aceito para tags;
- relação entre tag e versão do pacote;
- permissões de escrita no repositório;
- acesso a secrets por jobs e pull requests;
- actions de terceiros e versões pinadas;
- proteção contra execução de código não confiável com token de release.
Não misture o workflow de validação de pull request com o workflow que possui credenciais de publicação sem uma barreira clara. O job de release deve operar com o menor conjunto possível de permissões.
Se o repositório possui mais de um provedor de CI, evite drift. A automação gerada para GitHub Actions não atualiza automaticamente uma pipeline paralela de Gitea, GitLab ou outro sistema. Mantenha uma lista explícita das fontes de verdade e compare versões da toolchain, targets e etapas de segurança.
Smoke tests: valide o artefato que o usuário recebe
cargo test valida o código do workspace. Ele não prova que o .zip contém o arquivo certo, que a permissão executável foi preservada ou que o instalador colocou o programa no PATH.
Depois de gerar cada artefato:
# Exemplo conceitual para um tarball Linux
mkdir -p /tmp/minha-cli-smoke
tar -xzf minha-cli-x86_64-unknown-linux-gnu.tar.gz \
-C /tmp/minha-cli-smoke
/tmp/minha-cli-smoke/minha-cli --version
/tmp/minha-cli-smoke/minha-cli --help
/tmp/minha-cli-smoke/minha-cli validar fixtures/exemplo.toml
No Windows, execute o .exe em runner Windows. No macOS, teste o binário correspondente à arquitetura. Se houver instalador, teste instalação e desinstalação em ambiente descartável.
O smoke test deve usar dados pequenos, determinísticos e sem depender de credenciais de produção. Para uma CLI HTTP, aponte para um servidor local de teste. Para uma ferramenta de arquivos, use fixtures versionadas. Para um programa que altera estado, execute em diretório temporário.
Checksums, assinatura, SBOM e proveniência
Checksums detectam corrupção e permitem confirmar que o download corresponde ao arquivo anunciado. Eles não provam, sozinhos, quem publicou o artefato: se atacante e binário estiverem no mesmo canal comprometido, o checksum também pode ser substituído.
Por isso, avalie camadas conforme o risco:
- checksum para integridade básica;
- assinatura para verificar origem;
- SBOM para inventariar componentes;
- proveniência/attestation para registrar como o artefato foi construído;
- runner isolado e dependências pinadas para reduzir risco na construção.
cargo-dist pode participar desse processo, mas políticas corporativas frequentemente exigem etapas adicionais. Verifique exatamente o que sua versão gera. Não escreva “artefato assinado” na documentação se a pipeline produz apenas checksum.
Changelog, notas de release e atualização
Um pacote instalável precisa de contexto. As notas devem responder:
- o que mudou;
- existe quebra de compatibilidade?
- o formato de configuração mudou?
- qual versão mínima de sistema é necessária?
- como atualizar?
- como voltar para a versão anterior?
Se a CLI lê arquivos persistentes, preserve compatibilidade ou ofereça migração explícita. Se uma versão nova grava formato irreversível, avise antes da instalação. A qualidade do pacote não compensa uma atualização que destrói o caminho de rollback.
Para times, uma boa prática é promover canais: primeiro prerelease em projeto de teste, depois release candidata, por fim estável. Isso permite validar o pipeline sem usar imediatamente o mesmo canal consumido por todos.
Erros frequentes ao adotar cargo-dist
Inicializar e commitar sem revisar
A configuração gerada é um ponto de partida. Revise eventos, tokens, targets, actions e scripts como qualquer outro código de infraestrutura.
Anunciar plataformas que ninguém testa
Compilar não é suportar. Cada plataforma oficial precisa de smoke test e de uma expectativa realista de manutenção.
Deixar a versão de cargo-dist flutuante
Uma ferramenta atualizada silenciosamente pode mudar configuração, defaults ou formato dos artefatos. Pine a versão usada para gerar e executar releases.
Ignorar dependências nativas
OpenSSL, bibliotecas C, runtimes gráficos e SDKs podem tornar um target muito menos portátil do que parecia. Valide em máquina limpa.
Testar apenas antes do empacotamento
Execute o arquivo baixável e o instalador. É essa camada que o usuário recebe.
Tratar checksum como assinatura
Checksum verifica integridade em relação ao valor publicado; assinatura acrescenta identidade criptográfica. Documente cada garantia corretamente.
Não testar rollback
Mantenha releases anteriores acessíveis e confira se reinstalar uma versão anterior funciona com arquivos e configurações existentes.
Checklist de publicação
- A versão do pacote corresponde à tag planejada.
-
cargo fmt, Clippy e testes passam com lockfile. -
cargo dist plancontém apenas pacotes e targets esperados. - A versão de
cargo-distestá fixada. - Dependências nativas foram verificadas por target.
- O workflow usa permissões mínimas e secrets protegidos.
- Cada pacote foi baixado e executado em smoke test.
- Checksums foram conferidos.
- Assinatura, SBOM e proveniência foram adicionadas quando exigidas.
- Notas de release explicam instalação, atualização e mudanças incompatíveis.
- A versão anterior continua disponível para rollback.
- A documentação não promete plataformas ou garantias que o time não valida.
Perguntas frequentes
Para que serve o cargo-dist?
cargo-dist automatiza parte do release de aplicações Rust, especialmente CLIs: planeja artefatos, gera configuração de CI, compila para targets selecionados, empacota binários e pode produzir checksums e instaladores. Ele não substitui testes, versionamento, assinatura, revisão de segurança nem um plano de rollback.
cargo-dist é obrigatório para publicar uma CLI Rust?
Não. Um projeto pequeno pode publicar artefatos com cargo build --release e uma pipeline própria. A ferramenta vale a pena quando o time quer padronizar releases para Linux, macOS e Windows, reduzir YAML artesanal e oferecer instalação consistente.
Qual é a diferença entre cargo install e cargo-dist?
cargo install compila uma crate na máquina do usuário e coloca o executável no PATH. cargo-dist ajuda o mantenedor a produzir e publicar binários pré-compilados e instaladores. Os dois canais podem coexistir.
Preciso compilar todos os targets em uma única máquina?
Não necessariamente. A matriz pode distribuir builds entre runners Linux, macOS e Windows. Cross-compilation funciona em alguns casos, mas dependências nativas, assinatura e testes frequentemente pedem runners do próprio sistema.
Como validar um release criado com cargo-dist?
Revise o plano, execute uma tag de teste, baixe cada artefato, confira checksums, extraia ou instale o pacote e rode --version, --help e um comando real. Teste também atualização e rollback.
Conclusão
cargo-dist é mais útil quando o desafio já deixou de ser “compilar Rust” e passou a ser “entregar o mesmo produto, de forma previsível, para várias plataformas”. Ele reduz scripts repetidos, organiza a matriz e aproxima uma CLI de uma experiência de instalação profissional.
A decisão correta não é adotar a ferramenta em todo projeto. É usá-la onde padronização, binários pré-compilados e manutenção multiplataforma pagam o custo. Comece com um release candidato, revise o plano, teste os arquivos finais e documente as garantias reais. Assim, sua automação vira parte confiável do produto — e não apenas mais um YAML que só alguém entende no dia em que quebra.