Publicar uma crate é o passo final para compartilhar seu código com a comunidade Rust. Nesta aula, vamos explorar o processo completo, desde a preparação do seu projeto até o envio para o crates.io. Você entenderá a importância dos metadados no Cargo.toml, como aplicar versionamento semântico corretamente e como usar o comando cargo publish de forma eficaz.

Além disso, discutiremos boas práticas para manter sua crate saudável, como documentação adequada, testes e gerenciamento de versões. Ao final, você estará pronto para publicar sua primeira crate e contribuir com o ecossistema Rust.

crates.io

crates.io é o registro central de pacotes da linguagem Rust. Ele é mantido pela Rust Foundation e serve como o principal canal de distribuição de crates. Quando você publica uma crate, ela fica disponível para qualquer pessoa baixar e usar em seus projetos, seja via cargo add ou adicionando a dependência no Cargo.toml.

O crates.io oferece uma interface web para explorar crates, além de uma API que o Cargo utiliza para gerenciar downloads e publicações. É importante notar que, uma vez publicada, uma versão específica de uma crate não pode ser removida ou sobrescrita — você só pode publicar novas versões. Isso garante a integridade dos projetos que dependem dela.

Para começar, você precisa de uma conta no crates.io. O login é feito via GitHub, e depois você pode gerar um token de API que será usado pelo Cargo para autenticar as publicações. Vamos ver isso em detalhes na seção sobre cargo publish.

Metadados no Cargo.toml

O arquivo Cargo.toml é o coração do seu projeto Rust. Ele contém todas as informações necessárias para o Cargo gerenciar o projeto, incluindo metadados que serão usados pelo crates.io para exibir informações sobre sua crate. Esses metadados são essenciais para que os usuários entendam o propósito da sua crate, sua licença, e outros detalhes.

Os campos mais importantes são:

  • name: nome da crate (único no crates.io).
  • version: versão atual (usando versionamento semântico).
  • description: uma frase curta descrevendo o que a crate faz.
  • license: tipo de licença (ex.: MIT, Apache-2.0).
  • repository: URL do repositório de código (opcional, mas recomendado).
  • documentation: URL da documentação (se diferente do docs.rs).
  • keywords: lista de palavras-chave para busca.
  • categories: categorias no crates.io.

Exemplo de um Cargo.toml bem configurado:

[package]
name = "minha-crate"
version = "0.1.0"
edition = "2021"
description = "Uma crate de exemplo para fins didáticos"
license = "MIT"
repository = "https://github.com/seu-usuario/minha-crate"
documentation = "https://docs.rs/minha-crate"
keywords = ["exemplo", "didático"]
categories = ["algorithms"]

[dependencies]

Além desses, o Cargo também aceita campos como readme, homepage, exclude e include para controlar o que será empacotado. É importante preencher esses campos com cuidado, pois eles aparecem na página da crate e influenciam a confiança dos usuários.

Versionamento semântico

O versionamento semântico (SemVer) é um padrão para atribuir números de versão que comunicam o tipo de mudanças em uma release. Ele segue o formato MAJOR.MINOR.PATCH:

  • MAJOR: incrementado quando há mudanças incompatíveis na API.
  • MINOR: incrementado quando novas funcionalidades são adicionadas de forma compatível.
  • PATCH: incrementado para correções de bugs compatíveis.

No Rust, o Cargo segue o SemVer por padrão. Ao publicar uma nova versão, você deve atualizar o campo version no Cargo.toml de acordo com as mudanças feitas. Isso é crucial porque o Cargo usa o SemVer para resolver dependências: ele assume que versões com o mesmo MAJOR são compatíveis.

Por exemplo, se você corrige um bug sem alterar a API, incremente o PATCH (0.1.1). Se adicionar uma nova função, incremente o MINOR (0.2.0). Se fizer uma mudança que quebra a API, incremente o MAJOR (1.0.0).

Além disso, antes de publicar a versão 1.0.0, você pode usar a convenção 0.x.y para indicar que a API ainda é instável. Muitas crates começam com 0.1.0 e evoluem até atingir a estabilidade.

O Cargo também oferece o comando cargo bump (via crate externa) para facilitar o incremento de versão, mas você pode editar manualmente. Lembre-se de que cada versão publicada é imutável, então escolha com cuidado.

cargo publish

O comando cargo publish é responsável por empacotar sua crate e enviá-la ao crates.io. Antes de publicar, é fundamental garantir que o projeto esteja bem testado e documentado, pois a publicação é irreversível para aquela versão.

O fluxo básico é:

  1. Registrar-se no crates.io e autenticar via GitHub.
  2. Gerar um token de API em https://crates.io/settings/tokens.
  3. Fazer login no Cargo com o token: cargo login <TOKEN>.
  4. Verificar se o pacote está correto com cargo package (opcional).
  5. Executar cargo publish.

Exemplo de uso:

cargo login abcdef1234567890
teste local: cargo package --list
cargo publish

O comando cargo package cria um arquivo .crate com o conteúdo do projeto, respeitando as regras de inclusão/exclusão definidas no Cargo.toml. Ele também valida se os metadados estão completos. É uma boa prática executá-lo antes de publicar para verificar se tudo está em ordem.

Depois de publicar, o Cargo exibirá uma mensagem de sucesso e o crates.io atualizará a página da crate. Você pode verificar em https://crates.io.

Para publicar uma nova versão, basta alterar a versão no Cargo.toml e executar cargo publish novamente. Lembre-se de que o nome da crate deve ser único; se já existir, você precisará escolher outro.

Boas práticas e observações finais

Antes de publicar, garanta que sua crate tenha boa documentação (doc comments), testes abrangentes e um README.md informativo. O docs.rs gera automaticamente a documentação a partir dos comentários, então invista neles.

Também é recomendado configurar integração contínua (CI) com GitHub Actions para testar em múltiplas plataformas. Isso aumenta a confiança na qualidade da crate.

Por fim, lembre-se de que publicar uma crate é uma responsabilidade: você estará fornecendo código para outros desenvolvedores. Mantenha sua crate atualizada, responda a issues e considere o feedback da comunidade.

Referências

Exercícios

  1. Explique por que uma versão de crate publicada não pode ser removida do crates.io. Qual é o impacto disso para os desenvolvedores?
  2. ✓ Resposta: As versões são imutáveis para garantir que projetos que dependem de uma versão específica continuem funcionando. Se uma versão fosse removida, builds que dependem dela quebrariam. Isso dá confiança aos usuários de que suas dependências não desaparecerão.
  3. Dado o seguinte Cargo.toml, identifique os metadados obrigatórios que estão faltando:
    [package]
    name = "exemplo"
    version = "0.1.0"
    
  4. ✓ Resposta: Faltam description e license. O Cargo exige esses campos para publicar. Outros como repository são opcionais, mas recomendados.
  5. Se você fez uma mudança que quebra a API da sua crate (por exemplo, renomeou uma função pública), qual versão você deve publicar? Dê um exemplo de número de versão.
  6. ✓ Resposta: Você deve incrementar o número MAJOR. Por exemplo, se a versão atual é 1.2.3, a nova versão seria 2.0.0.
  7. Escreva o comando para fazer login no crates.io com um token fictício (ex.: "seu-token-aqui") e depois publicar a crate.
  8. ✓ Resposta:
    cargo login seu-token-aqui
    cargo publish
    
  9. Qual é a finalidade do comando cargo package --list? Por que é útil antes de publicar?
  10. ✓ Resposta: Ele lista os arquivos que serão incluídos no pacote .crate. Isso permite verificar se não há arquivos indesejados (como segredos) e se todos os arquivos necessários estão presentes antes de publicar.