Cargo Ferramentas Essenciais para Produção | Rust Brasil

Ferramentas essenciais do Cargo para Rust: cargo-watch, cargo-chef, cargo-audit, cargo-nextest e mais. Guia completo em português.

Introdução

O Cargo é o gerenciador de pacotes e build system do Rust, mas seu poder vai muito além de cargo build e cargo test. O ecossistema de subcomandos e ferramentas do Cargo oferece tudo que você precisa para um workflow de desenvolvimento e produção profissional.

Neste guia, vamos explorar as ferramentas mais importantes que todo desenvolvedor Rust deveria conhecer: desde hot-reload durante o desenvolvimento até auditoria de segurança, testes rápidos, builds Docker otimizados e publicação de crates.

Instalação Rápida de Todas as Ferramentas

# Desenvolvimento
cargo install cargo-watch
cargo install cargo-expand

# Testes
cargo install cargo-nextest --locked

# Segurança e compliance
cargo install cargo-audit
cargo install cargo-deny --locked

# Publicação
cargo install cargo-release --locked

# Docker
cargo install cargo-chef --locked

cargo-watch: Hot Reload para Desenvolvimento

O cargo-watch monitora mudanças nos arquivos e re-executa comandos automaticamente — similar ao nodemon do Node.js.

Instalação

cargo install cargo-watch

Uso Básico

# Recompilar automaticamente ao salvar
cargo watch -x build

# Rodar testes automaticamente
cargo watch -x test

# Compilar e executar
cargo watch -x run

# Verificar (mais rápido que build)
cargo watch -x check

# Encadear comandos: check -> test -> run
cargo watch -x check -x test -x run

Uso Avançado

# Ignorar diretórios
cargo watch -i "*.log" -i "data/*" -x run

# Executar comando shell customizado
cargo watch -s "cargo test && echo 'Testes OK!'"

# Watch em diretório específico
cargo watch -w src -w tests -x test

# Limpar antes de cada build
cargo watch -c -x run

# Com variáveis de ambiente
cargo watch -x 'run -- --porta 3000'

Integração com Axum/Actix para desenvolvimento web:

# Hot-reload do servidor
cargo watch -x run

# Ou com cargo-run e argumentos
cargo watch -x 'run -- serve --port 8080'

Para quem desenvolve APIs com Axum, o cargo-watch é indispensável para produtividade.

cargo-expand: Visualizar Expansão de Macros

O cargo-expand mostra o código gerado por macros procedurais — essencial para debugar derives como serde::Serialize, clap::Parser e outros.

Instalação

cargo install cargo-expand
# Requer o nightly toolchain
rustup install nightly

Uso

# Expandir todo o crate
cargo expand

# Expandir um módulo específico
cargo expand models

# Expandir uma função específica
cargo expand main

# Expandir com cores
cargo expand --theme=dracula

Exemplo Prático

Dado o código:

use serde::{Serialize, Deserialize};

#[derive(Debug, Serialize, Deserialize)]
struct Usuario {
    nome: String,
    idade: u32,
}

O cargo expand mostra toda a implementação gerada pelo #[derive(Serialize)], incluindo o impl Serialize for Usuario.

Isso é extremamente útil para entender o que Serde, Clap e thiserror geram por trás dos derives.

cargo-nextest: Testes Mais Rápidos

O cargo-nextest é um test runner moderno que substitui cargo test com execução significativamente mais rápida e melhor output.

Instalação

cargo install cargo-nextest --locked

Uso Básico

# Rodar todos os testes
cargo nextest run

# Testes com filtro
cargo nextest run nome_do_teste

# Listar testes sem executar
cargo nextest list

# Testes com retry automático para flaky tests
cargo nextest run --retries 2

# Testes com output detalhado em caso de falha
cargo nextest run --failure-output=immediate

Performance

O cargo-nextest executa cada teste em um processo separado e usa paralelismo agressivo:

Métricacargo testcargo nextest
Execução paralelaPor threadPor processo
Tempo (100 testes)~15s~5s
IsolamentoCompartilhadoPor processo
Output em falhaMisturadoLimpo e isolado
Retry de flakyNãoSim

Configuração (.config/nextest.toml)

[store]
dir = "target/nextest"

[profile.default]
retries = 1
fail-fast = true
slow-timeout = { period = "60s", terminate-after = 2 }

[profile.ci]
retries = 3
fail-fast = false

[profile.default.junit]
path = "target/nextest/results.xml"
# Usar perfil de CI
cargo nextest run --profile ci

cargo-audit: Auditoria de Segurança

O cargo-audit verifica suas dependências contra o RustSec Advisory Database para encontrar vulnerabilidades conhecidas.

Instalação

cargo install cargo-audit

Uso

# Verificar vulnerabilidades
cargo audit

# Gerar relatório JSON
cargo audit --json

# Verificar também dependências vendored
cargo audit --deny warnings

# Ignorar advisory específico
cargo audit --ignore RUSTSEC-2024-0001

Saída de exemplo

Crate:     chrono
Version:   0.4.23
Title:     Potential segfault in localtime_r invocations
Date:      2024-01-01
ID:        RUSTSEC-2024-0001
URL:       https://rustsec.org/advisories/RUSTSEC-2024-0001
Solution:  Upgrade to >=0.4.32

warning: 1 allowed warning found

Integração com CI (GitHub Actions)

# .github/workflows/security.yml
name: Security Audit
on:
  push:
    paths:
      - '**/Cargo.toml'
      - '**/Cargo.lock'
  schedule:
    - cron: '0 0 * * *'  # Diariamente

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: rustsec/audit-check@v2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

cargo-deny: Compliance e Políticas de Dependências

O cargo-deny vai além da segurança — ele permite definir políticas completas para suas dependências: licenças, fontes, versões duplicadas e advisories.

Instalação

cargo install cargo-deny --locked

Configuração (deny.toml)

# deny.toml
[advisories]
vulnerability = "deny"
unmaintained = "warn"
yanked = "warn"
notice = "warn"

[licenses]
unlicensed = "deny"
allow = [
    "MIT",
    "Apache-2.0",
    "BSD-2-Clause",
    "BSD-3-Clause",
    "ISC",
    "Unicode-DFS-2016",
]
copyleft = "deny"

[bans]
multiple-versions = "warn"
wildcards = "deny"
deny = [
    # Crates proibidos
    { name = "openssl", wrappers = ["openssl-sys"] },
]

[sources]
unknown-registry = "deny"
unknown-git = "deny"
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
allow-git = []

Uso

# Verificar tudo
cargo deny check

# Verificar apenas licenças
cargo deny check licenses

# Verificar apenas advisories
cargo deny check advisories

# Verificar dependências duplicadas
cargo deny check bans

# Gerar template de configuração
cargo deny init

Saída de exemplo

error[L002]: openssl-sys 0.9.85 is dual licensed under OpenSSL, which is not in the allow list
  ┌─ /path/to/Cargo.lock
  │
4 │ openssl-sys 0.9.85
  │ ^^^^^^^^^^^^^^^^^ a]

warning[B003]: found 2 duplicate versions of crate `syn`
  ┌─ /path/to/Cargo.lock
  │
  │ syn 1.0.109 vs 2.0.40

cargo-release: Publicação Automatizada

O cargo-release automatiza o processo de bump de versão, tag git, publicação no crates.io e push para o repositório.

Instalação

cargo install cargo-release --locked

Uso

# Dry run (ver o que aconteceria)
cargo release patch --dry-run

# Bump de patch (0.1.0 -> 0.1.1)
cargo release patch

# Bump de minor (0.1.0 -> 0.2.0)
cargo release minor

# Bump de major (0.1.0 -> 1.0.0)
cargo release major

# Release sem publicar no crates.io
cargo release --no-publish patch

# Com tag customizada
cargo release --tag-prefix "v" patch

Configuração (release.toml)

# release.toml
pre-release-commit-message = "chore: release {{version}}"
tag-message = "Release {{version}}"
tag-prefix = "v"
publish = true
push = true
push-remote = "origin"
shared-version = true

# Atualizar CHANGELOG automaticamente
pre-release-replacements = [
    { file = "CHANGELOG.md", search = "## \\[Unreleased\\]", replace = "## [Unreleased]\n\n## [{{version}}] - {{date}}" },
]

Workflow de Release

# 1. Verificar que tudo está ok
cargo test
cargo clippy
cargo audit

# 2. Ver o que o release faria
cargo release patch --dry-run

# 3. Executar o release
cargo release patch --execute

cargo-chef: Builds Docker Otimizados

O cargo-chef otimiza drasticamente os builds Docker de projetos Rust, aproveitando o cache de layers para dependências.

Instalação

cargo install cargo-chef --locked

Dockerfile Otimizado

# Etapa 1: Planejar (cacheável)
FROM rust:1.83-slim AS planner
WORKDIR /app
RUN cargo install cargo-chef --locked
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

# Etapa 2: Compilar dependências (cacheável)
FROM rust:1.83-slim AS builder
WORKDIR /app
RUN cargo install cargo-chef --locked
COPY --from=planner /app/recipe.json recipe.json
# Isso compila APENAS as dependências — fica em cache!
RUN cargo chef cook --release --recipe-path recipe.json

# Etapa 3: Compilar aplicação
COPY . .
RUN cargo build --release

# Etapa 4: Runtime mínimo
FROM debian:bookworm-slim AS runtime
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/meu-app /usr/local/bin/
ENTRYPOINT ["/usr/local/bin/meu-app"]

Comparação de Tempos de Build

CenárioSem cargo-chefCom cargo-chef
Primeira build~10 min~10 min
Mudança no código~10 min~1 min
Mudança em dependência~10 min~8 min

A diferença é dramática: após o primeiro build, mudanças no código da aplicação são reconstruídas em ~1 minuto ao invés de ~10 minutos, pois as dependências ficam em cache.

Outras Ferramentas Úteis

cargo-clippy (incluso no Rust)

Linter oficial com centenas de regras:

# Rodar clippy
cargo clippy

# Clippy com tratamento estrito
cargo clippy -- -D warnings

# Fix automático
cargo clippy --fix

cargo-fmt (incluso no Rust)

Formatador oficial:

# Formatar código
cargo fmt

# Verificar formatação (para CI)
cargo fmt --check

cargo-outdated

Verificar dependências desatualizadas:

cargo install cargo-outdated
cargo outdated

cargo-bloat

Analisar o tamanho do binário:

cargo install cargo-bloat
cargo bloat --release
cargo bloat --release --crates

cargo-udeps

Encontrar dependências não utilizadas:

cargo install cargo-udeps --locked
cargo +nightly udeps

Workflow Completo para Produção

Script de CI/CD

#!/bin/bash
set -euo pipefail

echo "=== Formatação ==="
cargo fmt --check

echo "=== Linting ==="
cargo clippy -- -D warnings

echo "=== Auditoria de segurança ==="
cargo audit

echo "=== Políticas de dependências ==="
cargo deny check

echo "=== Testes ==="
cargo nextest run --profile ci

echo "=== Build release ==="
cargo build --release

echo "=== Tudo OK! ==="

GitHub Actions Completo

name: CI
on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy, rustfmt
      - uses: Swatinem/rust-cache@v2

      - name: Formato
        run: cargo fmt --check

      - name: Clippy
        run: cargo clippy -- -D warnings

      - name: Testes
        run: cargo install cargo-nextest --locked && cargo nextest run

      - name: Auditoria
        run: cargo install cargo-audit && cargo audit

Tabela Resumo

FerramentaCategoriaComando Principal
cargo-watchDesenvolvimentocargo watch -x run
cargo-expandDebug de macroscargo expand
cargo-nextestTestescargo nextest run
cargo-auditSegurançacargo audit
cargo-denyCompliancecargo deny check
cargo-releasePublicaçãocargo release patch
cargo-chefDockerMulti-stage Dockerfile
cargo-clippyLintingcargo clippy
cargo-fmtFormataçãocargo fmt
cargo-bloatAnálise de tamanhocargo bloat --release

Conclusão

O ecossistema de ferramentas do Cargo é um dos maiores diferenciais do Rust para uso em produção. Com essas ferramentas, você tem tudo necessário para: desenvolvimento produtivo com hot-reload, testes rápidos e isolados, auditoria de segurança automatizada, compliance de licenças, builds Docker otimizados e processo de release automatizado.

Incorporar essas ferramentas no seu workflow desde o início do projeto economiza tempo e previne problemas que seriam muito mais custosos de resolver depois.

Veja Também