cargo-generate: Templates para Projetos Rust | Rust Brasil

Use cargo-generate para criar projetos Rust a partir de templates: variáveis, arquivos condicionais, favoritos, Git, CI e padrões seguros para equipes.

cargo-generate cria projetos Rust a partir de templates versionados, substituindo variáveis e montando uma estrutura pronta para a stack do time. Enquanto cargo new entrega o crate mínimo, cargo generate pode iniciar uma API com Axum, um workspace, uma CLI, um serviço com observabilidade ou uma biblioteca já acompanhada de testes e CI. Ele vale a pena quando a organização repete decisões estáveis — não quando tenta esconder toda a arquitetura atrás de um gerador mágico.

O fluxo básico é direto:

cargo install cargo-generate --locked
cargo generate --git https://github.com/sua-org/template-rust.git

A ferramenta pergunta o nome do projeto e outras opções definidas pelo template. No final, você recebe uma nova pasta, normalmente com histórico Git próprio, pronta para ser inspecionada e compilada. O passo decisivo vem depois: rode os checks, leia o código gerado e remova tudo o que não pertence ao produto.

Resposta rápida: quando usar cargo-generate

SituaçãoRecomendaçãoMotivo
Primeiro exercício em Rustuse cargo newa estrutura mínima ajuda a aprender Cargo e módulos
APIs repetidas com a mesma stackuse cargo-generatepadroniza dependências, erros, logs e CI
Workspace com vários cratesconsidere um templatereduz configuração manual e nomes inconsistentes
Biblioteca pública pequenacomece com cargo new --libboilerplate excessivo aumenta manutenção
Projeto corporativo com compliancetemplate versionado e testadopolíticas podem nascer no repositório desde o primeiro commit
Protótipo descartávelescolha o caminho mais simplesmanter um template pode custar mais que criar o projeto

A melhor pergunta não é “como gerar mais arquivos?”, mas “quais decisões queremos repetir com segurança?”.

cargo new vs cargo-generate

O Cargo já oferece dois começos oficiais:

cargo new minha-cli
cargo new minha-lib --lib

Eles criam Cargo.toml, src/main.rs ou src/lib.rs e, por padrão, inicializam um repositório Git. Essa simplicidade é excelente para exemplos, katas, bibliotecas pequenas e aprendizado.

cargo-generate entra quando o ponto de partida precisa representar uma arquitetura real. Um template de backend pode conter:

  • workspace com crates para domínio, aplicação e infraestrutura;
  • Axum, Tokio e Tower;
  • configuração em camadas;
  • erros com thiserror e contexto com anyhow onde fizer sentido;
  • SQLx e migrations;
  • logs estruturados com Tracing;
  • testes unitários e de integração;
  • Dockerfile, health check e pipeline de CI;
  • README com comandos e decisões iniciais.

A diferença é de intenção: cargo new cria um crate; cargo-generate pode criar um sistema inicial opinativo.

Instalando com reprodutibilidade

A instalação local mais comum é:

cargo install cargo-generate --locked
cargo generate --version

O --locked pede que a instalação respeite o lockfile publicado pela ferramenta quando disponível, reduzindo variações inesperadas na resolução de dependências. Em uma equipe, registre a versão homologada em documentação, script ou gerenciador de ferramentas. Instalar sempre “a mais recente” na CI pode fazer o mesmo template produzir resultados diferentes sem mudança no repositório do produto.

Antes de automatizar flags, confira a interface da versão instalada:

cargo generate --help

Isso é especialmente importante em scripts antigos. Subcomandos e opções evoluem; a ajuda local é o contrato operacional do binário que realmente será executado.

Criando um template mínimo

Um template pode começar como um repositório Git comum:

meu-template-rust/
├── Cargo.toml
├── README.md
├── cargo-generate.toml
├── src/
│   └── main.rs
└── tests/
    └── smoke.rs

No conteúdo, variáveis usam a sintaxe suportada pelo mecanismo de template. Um Cargo.toml simples pode receber o nome normalizado do projeto:

[package]
name = "{{ project-name }}"
version = "0.1.0"
edition = "2024"

[dependencies]
anyhow = "1"

E o README pode preservar um título legível:

# {{ project-name }}

Projeto gerado a partir do template oficial da equipe.

Depois de publicar o repositório, gere uma aplicação de teste:

cargo generate \
  --git https://github.com/sua-org/meu-template-rust.git \
  --name servico-pedidos

cd servico-pedidos
cargo check
cargo test

Não considere o template pronto porque a renderização terminou. Ele está pronto quando o projeto resultante compila, passa nos testes e não mantém marcadores não substituídos.

Variáveis e escolhas do usuário

A principal vantagem sobre copiar uma pasta é permitir escolhas controladas. Um template pode perguntar, por exemplo:

  • nome do serviço;
  • crate binário ou workspace;
  • PostgreSQL ou SQLite;
  • inclusão de Docker;
  • provedor de CI;
  • licença;
  • porta local;
  • ativação de métricas.

Prefira perguntas sobre decisões que realmente mudam a estrutura. Não transforme cada dependência em uma opção. Se o usuário precisa responder vinte perguntas que ninguém entende, o template transferiu a complexidade em vez de reduzi-la.

Uma boa experiência oferece defaults seguros e um caminho principal. Por exemplo:

[template]
cargo_generate_version = ">=0.20"

[placeholders.database]
type = "string"
prompt = "Qual banco será usado?"
choices = ["postgres", "sqlite", "nenhum"]
default = "postgres"

[placeholders.include_docker]
type = "bool"
prompt = "Incluir Dockerfile?"
default = true

A sintaxe exata deve ser validada contra a versão homologada do cargo-generate. O princípio permanece: declare as entradas no arquivo de configuração, dê nomes claros e teste todas as combinações oficialmente suportadas.

Arquivos condicionais sem criar uma matriz impossível

Templates mais completos podem incluir ou remover arquivos conforme as respostas. Isso é útil para não entregar migration de PostgreSQL em um projeto que escolheu SQLite, por exemplo.

O risco é a explosão combinatória. Cinco opções booleanas independentes já produzem 32 combinações. Se só três delas são testadas, as demais viram caminhos aparentemente suportados, mas quebrados.

Use estas regras:

  1. mantenha poucas variantes;
  2. prefira escolhas mutuamente exclusivas quando representam a mesma camada;
  3. defina uma combinação padrão e trate-a como produto principal;
  4. teste cada combinação prometida;
  5. remova opções sem usuário real;
  6. documente incompatibilidades no prompt e no README.

Às vezes, dois templates pequenos — “API Axum” e “CLI” — são melhores que um template universal com dezenas de condições.

Templates para Axum e backend Rust

Um template de API profissional deve gerar uma aplicação pequena, não um framework interno inteiro. Uma estrutura pragmática pode ser:

src/
├── main.rs
├── app.rs
├── config.rs
├── error.rs
├── state.rs
└── routes/
    ├── mod.rs
    └── health.rs
tests/
└── health.rs

O projeto pode nascer com uma rota de saúde e desligamento gracioso, mas não precisa antecipar usuários, pagamentos, filas e dez padrões de domínio que talvez nunca existam.

O template também pode apontar para o tutorial de API REST com Axum e para o guia de deploy com Docker Compose e PostgreSQL. Assim, quem recebe a base entende como evoluí-la em vez de tratar o código gerado como uma caixa-preta.

Boas decisões para padronizar:

  • configuração validada na inicialização;
  • tracing antes de subir o servidor;
  • erro HTTP com formato estável;
  • timeout e limites básicos;
  • health check separado de prontidão para dependências;
  • testes que montam o Router sem abrir uma porta real;
  • toolchain, edition e MSRV coerentes com a política da equipe.

Para definir a versão mínima suportada, use a abordagem do guia de cargo-msrv, em vez de escolher um número arbitrário.

Workspaces e nomes derivados

Em workspaces, o nome informado pelo usuário pode aparecer em vários contextos:

  • nome do diretório: servico-pedidos;
  • nome do package Cargo: servico-pedidos;
  • identificador Rust: servico_pedidos;
  • título humano: Serviço de Pedidos;
  • nome de imagem: minha-org/servico-pedidos.

Não use a mesma transformação cegamente em todos os lugares. Um hífen permitido no package vira sublinhado ao importar o crate no código. Nomes para Docker ou Kubernetes podem ter outras restrições. Gere e teste valores derivados explicitamente.

Para uma arquitetura maior, consulte Cargo workspaces e monorepos. O template deve produzir manifests válidos, membros existentes e dependências internas com paths corretos.

Git, favoritos e templates locais

Durante o desenvolvimento do template, você não precisa publicar cada tentativa. Aponte para um diretório local:

cargo generate --path ../meu-template-rust --name teste-template

Isso encurta o ciclo de edição e validação. Quando o template estiver remoto, prefira uma referência versionada para usos críticos. Uma tag ou commit identifica exatamente o ponto de partida; acompanhar uma branch mutável é conveniente, mas reduz reprodutibilidade.

Se a equipe usa vários templates, favoritos evitam decorar URLs. Mantenha nomes orientados ao trabalho, como api-axum, cli-clap e lib-publica, em vez de nomes genéricos como template-1.

Depois da geração, verifique o estado do Git:

git status
git log --oneline -1

O objetivo costuma ser um novo repositório do produto, sem carregar o histórico completo do template. Confirme o comportamento da versão usada e a política da organização antes de empurrar o primeiro commit.

Como testar um template na CI

O repositório do template precisa de CI própria. Testar apenas os arquivos com cargo check dentro do template pode falhar porque eles ainda contêm placeholders. A validação correta gera projetos temporários e testa a saída.

Um roteiro conceitual:

set -euo pipefail

tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT

cargo generate \
  --path . \
  --name api-exemplo \
  --destination "$tmp" \
  --silent

cd "$tmp/api-exemplo"
cargo fmt --all -- --check
cargo check --all-targets
cargo clippy --all-targets -- -D warnings
cargo test

Se há variantes, execute uma matriz pequena e explícita. Também procure vazamentos de template:

if rg -n '\{\{[^}]+\}\}' .; then
  echo "Placeholder não substituído"
  exit 1
fi

Adicione git diff --check, valide YAML da CI e, quando houver Dockerfile, construa a imagem. Para acelerar builds repetidos, avalie sccache ou cargo-chef somente depois de o pipeline básico estar correto.

Segurança e supply chain

Um template executa uma forma de multiplicação: uma decisão ruim pode chegar a dezenas de repositórios. Revise com atenção:

  • ações de CI fixadas ou atualizadas por política;
  • permissões mínimas do workflow;
  • ausência de tokens, URLs privadas e credenciais de exemplo reais;
  • dependências necessárias, sem features amplas por conveniência;
  • licença e arquivos de governança coerentes;
  • .gitignore cobrindo segredos e artefatos;
  • política de atualização do template.

Não coloque .env preenchido. Gere .env.example com valores fictícios e falhe com mensagem clara quando uma variável obrigatória estiver ausente.

Combine a revisão com cargo-audit, cargo-deny e SBOM e, para dependências críticas, cargo-vet. Essas ferramentas não tornam o template seguro automaticamente, mas criam verificações repetíveis desde o primeiro commit.

Erros comuns

Transformar opinião em obrigação eterna

Um template registra o que a equipe considera bom hoje. Ele não deve impedir o projeto gerado de evoluir. Evite scripts que sobrescrevem decisões locais ou uma dependência permanente do repositório original sem necessidade.

Gerar código demais

Cem arquivos vazios parecem arquitetura, mas atrasam leitura e navegação. Gere um caminho vertical funcionando — por exemplo, health check com teste — e deixe o restante crescer conforme requisitos reais.

Não versionar mudanças incompatíveis

Se a estrutura, MSRV, edition ou contrato de configuração muda bastante, crie uma tag e notas de migração. Projetos antigos não são atualizados automaticamente só porque o template mudou.

Ignorar manutenção pós-geração

O template acelera o dia zero; não atualiza todos os consumidores sozinho. Use automação de dependências, documentação e, quando necessário, mudanças mecânicas separadas para manter a frota.

Esconder fundamentos de iniciantes

Para quem está aprendendo ownership, módulos e Cargo, um template corporativo pode atrapalhar. Comece com cargo new, construa uma versão manual e só depois compare com a estrutura gerada.

cargo-generate como projeto de portfólio

Criar um template bem mantido demonstra competências além da sintaxe: design de API interna, automação, documentação, CI, segurança e experiência de desenvolvimento.

Um bom projeto de portfólio pode oferecer um template de API com:

  • Axum, Tokio e Tower;
  • tracing e request ID;
  • configuração tipada;
  • endpoint de saúde;
  • erro JSON consistente;
  • testes de integração;
  • Dockerfile multi-stage;
  • CI com fmt, Clippy e testes;
  • duas escolhas no máximo, como PostgreSQL ou SQLite;
  • documentação explicando trade-offs.

Em entrevistas e vagas Rust, não diga apenas que “automatizou boilerplate”. Explique o que foi padronizado, quais opções foram recusadas, como a matriz é testada e como um serviço gerado pode divergir sem perder manutenção. Conecte esse trabalho aos projetos práticos para portfólio e à preparação para entrevista Rust backend.

Checklist para um template saudável

  • existe um responsável ou time mantenedor;
  • o objetivo e o público estão claros no README;
  • a combinação padrão gera um projeto compilável;
  • todas as variantes prometidas são testadas;
  • placeholders restantes fazem a CI falhar;
  • versões de toolchain e ferramentas seguem uma política;
  • não há credenciais nem endpoints privados embutidos;
  • o código gerado é pequeno o bastante para ser entendido;
  • CI, testes e observabilidade nascem funcionando;
  • tags ou commits permitem reproduzir uma geração antiga;
  • mudanças incompatíveis têm notas de migração;
  • existe um processo para remover decisões obsoletas.

Perguntas frequentes sobre cargo-generate

O que é cargo-generate?

É uma ferramenta para gerar projetos Rust a partir de templates locais ou repositórios Git. Ela substitui variáveis, coleta escolhas e prepara uma estrutura mais rica do que o crate mínimo criado pelo Cargo.

Qual é a diferença entre cargo new e cargo-generate?

cargo new é o começo oficial e mínimo para um crate. cargo-generate serve para repetir uma arquitetura personalizada, como workspace, API, CLI, CI e arquivos operacionais. Use a ferramenta mais simples que atende ao caso.

Como instalar e usar cargo-generate?

Instale com cargo install cargo-generate --locked, confirme com cargo generate --version e gere com cargo generate --git URL. Depois execute fmt, check, Clippy e testes no projeto criado.

Um template deve incluir Cargo.lock?

Aplicações e CLIs normalmente versionam Cargo.lock; bibliotecas publicadas geralmente seguem outra política. O template deve decidir pelo tipo de produto gerado e documentar a escolha.

Quando não vale usar cargo-generate?

Quando o projeto é pequeno, único ou educacional; quando cargo new resolve com poucas alterações; ou quando não existe capacidade para testar e manter o template. Copiar boilerplate desatualizado mais rápido não é produtividade.

Conclusão

cargo-generate é útil quando um time precisa transformar decisões repetidas em um ponto de partida versionado e verificável. Ele pode padronizar workspaces, APIs, CLIs, testes, CI, segurança e documentação, reduzindo o tempo entre a ideia e o primeiro build confiável.

O melhor template não é o que gera mais arquivos. É o que produz um projeto pequeno, compreensível, testado e fácil de alterar. Comece com uma única stack, ofereça poucos defaults, gere exemplos na CI e trate o repositório do template como um produto interno. Assim, o scaffold acelera a equipe sem virar uma arquitetura congelada.