diff --git a/.github/workflows/cargo-deny.yml b/.github/workflows/cargo-deny.yml new file mode 100644 index 0000000..c0ad92d --- /dev/null +++ b/.github/workflows/cargo-deny.yml @@ -0,0 +1,31 @@ +name: cargo-deny + +on: + pull_request: + paths: + - "**/Cargo.toml" + - "Cargo.lock" + - "deny.toml" + - ".github/workflows/cargo-deny.yml" + push: + branches: [main] + paths: + - "**/Cargo.toml" + - "Cargo.lock" + - "deny.toml" + schedule: + # Roda semanalmente para pegar advisories novas mesmo sem mudanças. + - cron: "23 5 * * 1" # segunda 05:23 UTC + +jobs: + check: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v2 + with: + # `check all` = advisories + licenses + bans + sources. + command: check all + arguments: --workspace diff --git a/.github/workflows/cargo-machete.yml b/.github/workflows/cargo-machete.yml new file mode 100644 index 0000000..27d4317 --- /dev/null +++ b/.github/workflows/cargo-machete.yml @@ -0,0 +1,20 @@ +name: cargo-machete + +on: + pull_request: + paths: + - "**/Cargo.toml" + - "**/Cargo.lock" + - "**/*.rs" + - ".github/workflows/cargo-machete.yml" + schedule: + # Cron semanal para pegar deps removidas/órfãs no ecossistema. + - cron: "17 6 * * 1" + +jobs: + machete: + name: Find unused dependencies + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: bnjbvr/cargo-machete@main diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 0000000..0eb270d --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,35 @@ +name: commitlint + +on: + pull_request: + types: [opened, edited, reopened, synchronize] + push: + branches: [main] + +permissions: + contents: read + +jobs: + cog-check: + name: Conventional Commits (cocogitto) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # cog precisa histórico completo + - name: Install cocogitto + # cargo-binstall pega binary release oficial direto do GitHub releases. + # Mais confiável que install.sh (que retornou 404 em 2026-05). + uses: taiki-e/install-action@v2 + with: + tool: cocogitto + - name: Validate commit history + # Em PR: valida só os commits da PR (from-latest-tag = false). + # Em push para main: cog check valida tudo desde o último tag. + run: | + if [ "${{ github.event_name }}" = "pull_request" ]; then + git fetch origin ${{ github.base_ref }} + cog check origin/${{ github.base_ref }}..HEAD + else + cog check + fi diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml new file mode 100644 index 0000000..19b69d9 --- /dev/null +++ b/.github/workflows/release-plz.yml @@ -0,0 +1,51 @@ +name: release-plz + +on: + push: + branches: [main] + # workflow_dispatch permite trigger manual via UI ("Run workflow") — útil + # para forçar release após hot-fix. + workflow_dispatch: + +permissions: + pull-requests: write + contents: write + +jobs: + release-plz-release: + name: release-plz / release + runs-on: ubuntu-latest + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + - uses: dtolnay/rust-toolchain@stable + - uses: release-plz/action@v0.5 + with: + command: release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + + release-plz-pr: + name: release-plz / release-pr + runs-on: ubuntu-latest + if: github.event_name == 'push' + concurrency: + # Cancela release-pr anterior se um novo push chegar — evita PRs duplicados. + group: release-plz-${{ github.ref }} + cancel-in-progress: false + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + - uses: dtolnay/rust-toolchain@stable + - uses: release-plz/action@v0.5 + with: + command: release-pr + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..7948798 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,61 @@ +name: tests + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + nextest: + name: cargo nextest (${{ matrix.crate }} / features=${{ matrix.features }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + # Rodamos por crate para isolar falhas e respeitar a regra "nunca workspace + # build inteiro de uma vez" (CLAUDE.md). nextest é mais rápido por design + # (parallelism + retry). + matrix: + include: + - crate: serverust-macros + features: "" + - crate: serverust-core + features: "" + - crate: serverust-telemetry + features: "" + - crate: serverust-events + features: "" + - crate: serverust-events + features: "sqs in-memory" + - crate: serverust-events + features: "kafka" + - crate: serverust-events + features: "asyncapi sqs" + - crate: serverust-lambda + features: "" + - crate: serverust-cli + features: "" + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + # Cache key inclui matrix para isolar caches por crate+features. + shared-key: "tests-${{ matrix.crate }}-${{ matrix.features }}" + - name: Install librdkafka build deps (kafka feature) + if: contains(matrix.features, 'kafka') + # libcurl4-openssl-dev: rdkafka-sys >=4.10 requer curl/curl.h em build. + run: sudo apt-get update && sudo apt-get install -y cmake build-essential libssl-dev libsasl2-dev libcurl4-openssl-dev + - name: Install cargo-nextest + uses: taiki-e/install-action@v2 + with: + tool: cargo-nextest + - name: Run tests + run: | + if [ -z "${{ matrix.features }}" ]; then + cargo nextest run -p ${{ matrix.crate }} + else + cargo nextest run -p ${{ matrix.crate }} --features "${{ matrix.features }}" + fi diff --git a/CLAUDE.md b/CLAUDE.md index 635c42c..2469428 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,14 +24,44 @@ Estas propriedades são compromissos públicos. Violá-las exige uma nova ADR ap ## Processo de Release -1. Incrementar versão em `Cargo.toml` (workspace `version`). -2. Atualizar `CHANGELOG.md` — mover items de `[Unreleased]` para a nova versão com data. -3. Rodar `scripts/quality_changelog.sh` — deve passar. -4. Rodar `scripts/benchmark_ci.sh` — registrar saída em `docs/product/metrics/history.json`. -5. Rodar `scripts/benchmark_competitive.sh` — atualizar `docs/product/competitors/release-competitive-log.md`. -6. Criar tag git: `git tag -s v -m "Release v"`. -7. Publicar crates na ordem: `serverust-macros` → `serverust-core` → `serverust-telemetry` → `serverust-lambda` → `serverust-cli`. -8. Confirmar que CI passou **com a tag** (histórico: v0.1.1 e v0.1.2 foram publicadas sem tag — não repetir). +A partir de v0.4: **per-crate independent versioning** (estilo tokio/axum). Tag por crate `-vX.Y.Z`. Pré-v0.4 usava workspace-wide unified versioning. + +### Fluxo recomendado (release-plz, automatizado via CI) + +[`release-plz`](https://release-plz.dev) é Rust-native, dispara automaticamente: + +1. Merge commits seguindo Conventional Commits (`feat:`, `fix:`, `chore:`) no `main`. +2. release-plz abre Release PR com bump per-crate + CHANGELOG via git-cliff + cargo-semver-checks. +3. Merge do Release PR → `cargo publish` (ordem certa) + git tags `-v` + GitHub Release. + +Configs: +- `release-plz.toml` — quais crates publicar, política de tags. +- `cliff.toml` — template CHANGELOG. +- `cog.toml` — Conventional Commits via cocogitto. +- `.github/workflows/release-plz.yml` — CI workflow. + +Pré-flight: secret `CARGO_REGISTRY_TOKEN` (gere em https://crates.io/me). + +Trigger manual: Actions → release-plz → "Run workflow". + +### Fluxo manual (alternativa) + +1. Incrementar `version` no(s) `Cargo.toml` do(s) crate(s) afetado(s). +2. Atualizar refs path-deps internas (`version = "X.Y.Z"`). +3. Mover items de `[Unreleased]` para nova versão com data no `CHANGELOG.md`. +4. Rodar `scripts/quality_changelog.sh` — deve passar. +5. Rodar `scripts/benchmark_ci.sh` + `scripts/metrics_append.sh `. +6. Rodar `scripts/benchmark_competitive.sh` (atualiza `release-competitive-log.md`). +7. Criar tag git assinada: `git tag -s -v -m "Release v"` (per-crate) ou `git tag -s v` (workspace). +8. Publicar (Cargo 1.90+): `cargo publish --workspace` resolve ordem. Ou sequencial: `serverust-macros` → `serverust-core` → `serverust-telemetry` → `serverust-events` → `serverust-lambda` → `serverust-cli`. +9. Confirmar que CI passou **com a tag** (histórico: v0.1.1 e v0.1.2 foram publicadas sem tag — não repetir). + +### Pré-flight obrigatório + +- SSH signing configurado (`gpg.format = ssh`, `user.signingkey = ~/.ssh/id_*.pub`, `tag.gpgsign = true`). +- Public key adicionada como **Signing key** em GitHub settings. +- `cargo login` configurado. +- `cargo deny check` verde (CI: `.github/workflows/cargo-deny.yml`). Referência canônica: [`docs/development/release-checklist.md`](docs/development/release-checklist.md). diff --git a/Cargo.lock b/Cargo.lock index d7ce67a..1aa8c1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2687,7 +2687,7 @@ dependencies = [ [[package]] name = "serverust-cli" -version = "0.1.6" +version = "0.3.0" dependencies = [ "anyhow", "aws-config", diff --git a/Cargo.toml b/Cargo.toml index aa6c1eb..a0db3ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,10 @@ documentation = "https://docs.rs/serverust-core" readme = "README.md" keywords = ["lambda", "serverless", "aws", "framework", "api"] categories = ["web-programming", "web-programming::http-server", "asynchronous"] + +[profile.dev] +debug = "line-tables-only" +split-debuginfo = "unpacked" + +[profile.dev.package."*"] +debug = false diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..6caebc2 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,57 @@ +# Configuração do git-cliff (https://git-cliff.org). +# +# Usado pelo release-plz para gerar CHANGELOG.md a partir de Conventional Commits. +# Também pode ser rodado standalone: `git cliff -o CHANGELOG.md` + +[changelog] +header = """ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +""" +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [Unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | upper_first }} + {% for commit in commits %} + - {% if commit.breaking %}[**BREAKING**] {% endif %}{{ commit.message | upper_first }} ({{ commit.id | truncate(length=7, end="") }})\ + {% endfor %} +{% endfor %} +""" +trim = true +footer = """ +[unreleased]: https://github.com/JaimeJunr/serverust/compare/{{ previous.version }}...HEAD +""" + +[git] +conventional_commits = true +filter_unconventional = true +split_commits = false +commit_parsers = [ + { message = "^feat", group = "Added" }, + { message = "^fix", group = "Fixed" }, + { message = "^perf", group = "Performance" }, + { message = "^doc", group = "Documentation" }, + { message = "^refactor", group = "Refactor" }, + { message = "^test", group = "Tests" }, + { message = "^build", group = "Build" }, + { message = "^ci", group = "CI" }, + { message = "^chore\\(release\\)", skip = true }, + { message = "^chore", group = "Chore" }, + { message = "^revert", group = "Revert" }, +] +protect_breaking_commits = true +filter_commits = false +tag_pattern = "^[a-z-]+-v[0-9]+\\.[0-9]+\\.[0-9]+$" +skip_tags = "v0.1.0|v0.2.0" # tags legadas pré-per-crate +ignore_tags = "" +topo_order = false +sort_commits = "newest" diff --git a/cog.toml b/cog.toml new file mode 100644 index 0000000..b7d27c9 --- /dev/null +++ b/cog.toml @@ -0,0 +1,48 @@ +# Configuração do cocogitto (https://docs.cocogitto.io). +# +# cocogitto é o linter de Conventional Commits Rust-native. +# Usado pelo lefthook (commit-msg hook) e pelo CI (.github/workflows/commitlint.yml). +# +# Validar histórico: cog check +# Validar próximo commit message: cog verify "feat(scope): message" + +# ─── Chaves globais (devem vir ANTES de qualquer [table]) ────────────────── + +# Política do tag — bate com release-plz. +tag_prefix = "" + +# Permite merge commits e revert commits sem enforcement estrito. +ignore_merge_commits = true + +# Branch base. cog check valida histórico contra a branch atual. +branch_whitelist = ["main", "release-plz/*", "ralph/*", "ci/*", "chore/*", "fix/*", "feat/*", "docs/*"] + +# Hooks pós-bump (vazio = sem hooks customizados). +post_bump_hooks = [] + +# Scopes recomendados (monorepo). Lista vazia = qualquer scope aceito; +# descomente para enforcement estrito. +# scopes = ["core", "macros", "events", "telemetry", "lambda", "cli", "examples", "docs", "ci"] + +# ─── Tipos de commit ─────────────────────────────────────────────────────── +# Conventional Commits v1.0 + Angular convention. +[commit_types] +feat = { changelog_title = "Features" } +fix = { changelog_title = "Bug Fixes" } +perf = { changelog_title = "Performance" } +refactor = { changelog_title = "Refactoring" } +docs = { changelog_title = "Documentation" } +test = { changelog_title = "Tests" } +build = { changelog_title = "Build System" } +ci = { changelog_title = "Continuous Integration" } +chore = { changelog_title = "Chores" } +revert = { changelog_title = "Reverts" } +style = { changelog_title = "Style" } + +# ─── Changelog (usado pelo `cog changelog`) ──────────────────────────────── +[changelog] +authors = [] +template = "remote" +remote = "github.com" +repository = "serverust" +owner = "JaimeJunr" diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..ad1adcb --- /dev/null +++ b/deny.toml @@ -0,0 +1,68 @@ +# Configuração para `cargo-deny` (https://crates.io/crates/cargo-deny). +# +# Verifica licenças, advisories de segurança, fontes confiáveis e bans de deps. +# Rodar: cargo deny check +# CI: .github/workflows/cargo-deny.yml + +[graph] +all-features = true +no-default-features = false + +[advisories] +version = 2 +# Falha em advisories abertas no rustsec.org. +yanked = "deny" +# Ignores com justificativa explícita. Cada entrada deve ter comentário sobre +# (a) por que não dá pra atualizar, (b) qual o impacto real no contexto, +# (c) quando podemos remover. +ignore = [ + # rustls-webpki 0.101.7 (transitive via aws-smithy-http-client → AWS SDK). + # Impacto: TLS para AWS endpoints (DynamoDB, SQS, etc.). Risco real baixo + # porque a CA chain é a AWS Trust Services (controlada), não user-supplied. + # Remover quando aws-sdk-rust subir para rustls 0.23 (acompanhar + # https://github.com/awslabs/aws-sdk-rust/issues — atualmente pin 0.21). + "RUSTSEC-2026-0098", # name constraints for URI names incorretas + "RUSTSEC-2026-0099", # wildcard name em name constraints + "RUSTSEC-2026-0104", # reachable panic em CRL parsing +] + +[licenses] +version = 2 +# Allowlist baseada em SPDX. Restritivo de propósito — uma license nova só +# entra com PR explícito justificando. +allow = [ + "MIT", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-2-Clause", + "BSD-3-Clause", + "ISC", + "Unicode-DFS-2016", + "Unicode-3.0", + "CC0-1.0", + "Zlib", + "MPL-2.0", # weak copyleft, compatível com Apache/MIT + "0BSD", +] +# License que não constam no SPDX mas são triviais para crates comuns. +exceptions = [] +# Crates com declaração ambígua mas conhecidas como OK. Vazio por agora. +private = { ignore = true } + +[bans] +multiple-versions = "warn" +wildcards = "deny" +# Path-deps em crates `publish = false` (examples internos) são tratadas como +# wildcards pelo cargo-deny. Como os examples nunca vão pra crates.io, opt-in: +allow-wildcard-paths = true +highlight = "all" +# Permitir versões duplicadas comuns no ecossistema (futures, syn, etc.) sem +# encher de noise. Cada novo allow exige justificativa em PR. +skip = [] +skip-tree = [] + +[sources] +unknown-registry = "deny" +unknown-git = "deny" +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +allow-git = [] diff --git a/docs/development/release-checklist.md b/docs/development/release-checklist.md index 264dd48..410e12a 100644 --- a/docs/development/release-checklist.md +++ b/docs/development/release-checklist.md @@ -2,6 +2,8 @@ Checklist obrigatório para toda release. Referência canônica linkada em CLAUDE.md. +A partir de v0.4: **per-crate independent versioning** (estilo tokio/axum). Cada crate ganha tag próprio `-vX.Y.Z`. Pré-v0.4 usava workspace-wide unified versioning. + --- ## Antes do Release @@ -10,19 +12,28 @@ Checklist obrigatório para toda release. Referência canônica linkada em CLAUD - [ ] `cargo test -p serverust-core` passa - [ ] `cargo test -p serverust-macros` passa - [ ] `cargo test -p serverust-telemetry` passa -- [ ] `cargo test -p serverust-events` passa +- [ ] `cargo test -p serverust-events` passa (com features `sqs in-memory` para cobertura completa) - [ ] `cargo test -p serverust-lambda` passa - [ ] `scripts/quality_fmt.sh` passa - [ ] `scripts/quality_lint.sh` passa - [ ] `scripts/quality_complexity.sh` passa - [ ] `scripts/quality_cycles.sh` passa - [ ] `scripts/quality_changelog.sh` passa (versão em Cargo.toml tem entrada em CHANGELOG.md) -- [ ] `scripts/quality_hello_world.sh` passa (hello-world sem deps Kafka/DynamoDB) +- [ ] `scripts/quality_hello_world.sh` passa (hello-world sem deps Kafka/DynamoDB/SQS) +- [ ] `cargo deny check` passa (CI: `.github/workflows/cargo-deny.yml`) ## Versão e Changelog -- [ ] Incrementar `version` em `Cargo.toml` workspace -- [ ] Mover itens de `[Unreleased]` para nova versão com data em CHANGELOG.md +### Decisão: workspace-wide vs per-crate + +- **Per-crate** (default a partir de v0.4): bump apenas o(s) crate(s) que mudaram. Tag `serverust-events-v0.3.1`. +- **Workspace-wide** (legado v0.1.x..v0.3.x): bump `workspace.package.version` em `Cargo.toml`. Tag `v0.3.0`. + +### Etapas + +- [ ] Incrementar `version` no(s) `Cargo.toml` do(s) crate(s) afetado(s) +- [ ] Atualizar refs path-deps internas para a nova versão (ex: `serverust-events` depende de `serverust-telemetry = "X.Y.Z"`) +- [ ] Mover itens de `[Unreleased]` para nova versão com data em `CHANGELOG.md` - [ ] `scripts/quality_changelog.sh` verde ## Benchmarks e Métricas @@ -42,19 +53,72 @@ Checklist obrigatório para toda release. Referência canônica linkada em CLAUD - [ ] Versões de Rocket/Loco/actix-web/axum re-validadas nas releases oficiais - [ ] Tabela comparativa do README atualizada se necessário -- [ ] `docs/product/competitors/rocket.md`, `loco.md`, `actix.md` com seção "Kafka & Event Sources" atualizada +- [ ] `docs/product/competitors/rocket.md`, `loco.md`, `actix.md` com seção atualizada ## Publicação -- [ ] Tag git criada: `git tag -s v -m "Release v"` -- [ ] Publicar crates na ordem: - 1. `cargo publish -p serverust-macros` - 2. `cargo publish -p serverust-core` - 3. `cargo publish -p serverust-telemetry` - 4. `cargo publish -p serverust-lambda` - 5. `cargo publish -p serverust-events` - 6. `cargo publish -p serverust-cli` -- [ ] CI passou com a tag (verificar GitHub Actions) +### Opção A — `release-plz` (recomendado, automatizado via CI) + +[`release-plz`](https://release-plz.dev) é Rust-native (inspirado pelo Google `release-please` mas otimizado pra Rust). Roda automaticamente em CI: + +1. **Você merge commits** no `main` seguindo Conventional Commits (`feat:`, `fix:`, `chore:`). +2. **release-plz abre um Release PR** com bump de versão (per-crate, baseado nos commits) + CHANGELOG atualizado via git-cliff + breaking changes detectadas via cargo-semver-checks. +3. **Você mergea o Release PR** → release-plz dispara `cargo publish` (na ordem certa) + cria git tags `-v` + abre GitHub Release. + +Configuração: +- `release-plz.toml` na raiz — quais crates publicar, política de tags. +- `cliff.toml` na raiz — template do CHANGELOG. +- `.github/workflows/release-plz.yml` — CI workflow. +- Secret `CARGO_REGISTRY_TOKEN` no environment GitHub (gere em https://crates.io/me). + +Trigger manual: vá em Actions → release-plz → "Run workflow". + +### Opção B — `cargo publish --workspace` (manual, Cargo 1.90+) + +A partir de Cargo 1.90 (Nov 2025) o `cargo publish` aceita `--workspace` e resolve ordem de dependência sozinho: + +```bash +cargo publish --workspace # publica TODOS os crates do workspace +cargo publish -p serverust-macros -p serverust-core # subset selecionado +``` + +Use quando precisar de publish ad-hoc sem passar por release-plz. Pré-requisito: versões já bumpadas e commit feito. + +### Opção C — Manual sequencial (legado v0.3.x) + +```bash +git tag -s v -m "Release v" + +cargo publish -p serverust-macros +cargo publish -p serverust-core +cargo publish -p serverust-telemetry +cargo publish -p serverust-events +cargo publish -p serverust-lambda +cargo publish -p serverust-cli + +git push origin v +``` + +### Depois do publish + +- [ ] CI passou **com a tag** (`git push origin ` dispara workflow no commit do tag) +- [ ] Verificar página do crate em https://crates.io/crates/ +- [ ] Documentação publicada em https://docs.rs/ (geração automática ~10 min) +- [ ] Anúncio de release em GitHub Releases (opcional, `gh release create`) + +--- + +## Pré-flight obrigatório (Cargo + assinatura) + +- Cargo 1.90+ (para `cargo publish --workspace`). Verificar: `cargo --version`. +- SSH signing configurado para tags assinados: + ```bash + git config --global gpg.format ssh + git config --global user.signingkey ~/.ssh/id_.pub + git config --global tag.gpgsign true + ``` +- Public key adicionada como **Signing key** em https://github.com/settings/ssh/new (diferente de Authentication key). +- `cargo login` configurado (token em `~/.cargo/credentials.toml`). --- diff --git a/docs/product/roadmap.md b/docs/product/roadmap.md index 3c1efc7..e1910b9 100644 --- a/docs/product/roadmap.md +++ b/docs/product/roadmap.md @@ -100,6 +100,7 @@ Inspiração: SST, AWS SAM, Encore.ts, Cargo Lambda. Pesquisa em `docs/research/ - gRPC via tonic adapter - Suporte a outros brokers: RabbitMQ (`serverust-rabbitmq`), NATS (`serverust-nats`) — `Broker` trait já está pronta - Suporte a outros providers serverless (GCP Cloud Run, Azure Functions) +- **Remover ignores de RUSTSEC em `deny.toml`** quando `aws-sdk-rust` subir para `rustls 0.23+`: RUSTSEC-2026-0098, 0099, 0104 (rustls-webpki 0.101.7 transitive via aws-smithy-http-client). Acompanhar https://github.com/awslabs/aws-sdk-rust/issues. --- diff --git a/examples/baselines/axum-raw-kafka/Cargo.toml b/examples/baselines/axum-raw-kafka/Cargo.toml index 8b038bb..6fb5f8a 100644 --- a/examples/baselines/axum-raw-kafka/Cargo.toml +++ b/examples/baselines/axum-raw-kafka/Cargo.toml @@ -26,3 +26,8 @@ serde_json = "1" base64 = "0.22" tokio = { version = "1", features = ["macros", "rt-multi-thread"] } thiserror = "1" + +# cargo-machete false positives: rdkafka-sys é peer-dep pinned do rdkafka; +# thiserror é usado via #[derive(Error)] que machete não rastreia. +[package.metadata.cargo-machete] +ignored = ["rdkafka-sys", "thiserror"] diff --git a/examples/funds-api/Cargo.toml b/examples/funds-api/Cargo.toml index fa46f69..a3f1fc5 100644 --- a/examples/funds-api/Cargo.toml +++ b/examples/funds-api/Cargo.toml @@ -3,6 +3,7 @@ name = "funds-api" version = "0.1.0" edition = "2024" rust-version = "1.85" +publish = false [[bin]] name = "funds-api" diff --git a/examples/hello-world/Cargo.toml b/examples/hello-world/Cargo.toml index 7fbfdbc..2101194 100644 --- a/examples/hello-world/Cargo.toml +++ b/examples/hello-world/Cargo.toml @@ -3,6 +3,7 @@ name = "hello-world" version = "0.1.0" edition = "2024" rust-version = "1.85" +publish = false [[bin]] name = "hello-world" diff --git a/examples/todo-api/Cargo.toml b/examples/todo-api/Cargo.toml index 69cd90a..8322738 100644 --- a/examples/todo-api/Cargo.toml +++ b/examples/todo-api/Cargo.toml @@ -3,6 +3,7 @@ name = "todo-api" version = "0.1.0" edition = "2024" rust-version = "1.85" +publish = false [[bin]] name = "todo-api" diff --git a/lefthook.yml b/lefthook.yml index 0389ea1..9c6f8af 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -11,6 +11,18 @@ pre-commit: run: ./scripts/quality_cycles.sh hello_world: run: ./scripts/quality_hello_world.sh + machete: + # Detecta deps não-usadas (cargo-machete). Skip silencioso se a tool + # não estiver instalada — sem força instalação compulsória. + run: command -v cargo-machete >/dev/null 2>&1 && cargo machete || echo "[skip] cargo-machete ausente (cargo install cargo-machete)" + +# Valida commit message contra Conventional Commits via cocogitto (cog.toml). +commit-msg: + commands: + cog-verify: + # Skip silencioso se cog não estiver instalado. Instalação: + # curl https://raw.githubusercontent.com/cocogitto/cocogitto/main/install.sh | bash + run: command -v cog >/dev/null 2>&1 && cog verify --file {1} || echo "[skip] cocogitto ausente" pre-push: parallel: false diff --git a/release-plz.toml b/release-plz.toml new file mode 100644 index 0000000..99c0437 --- /dev/null +++ b/release-plz.toml @@ -0,0 +1,83 @@ +# Configuração do release-plz (https://release-plz.dev). +# +# release-plz roda em CI (.github/workflows/release-plz.yml) e: +# 1. Compara local com crates.io para descobrir o que precisa de release +# 2. Abre Release PR com bump de versão + CHANGELOG atualizado + tag annotation +# 3. Quando o Release PR é mergeado, dispara cargo publish + git tag + GitHub Release +# +# Tags geradas: `-v` (per-crate, estilo tokio/axum). +# CHANGELOG: gerado por git-cliff (config em cliff.toml). +# Breaking changes: detectadas por cargo-semver-checks integrado. + +[workspace] +# Conventional Commits opcionais — release-plz usa para bump automático +# (feat = minor, fix = patch, feat!/BREAKING CHANGE = major). +changelog_config = "cliff.toml" + +# Habilita cargo-semver-checks para detectar breaking changes em código que +# o autor marcou como `fix:` sem `!:` — protege contra patch release acidental. +semver_check = true + +# Cria GitHub Releases para cada tag. Body = changelog do crate. +git_release_enable = true +git_release_type = "auto" # prerelease se versão tem -alpha/-beta/-rc + +# Tag pattern por crate — encaixa com release-plz workflow. +git_tag_name = "{{ package }}-v{{ version }}" + +# Comentário no Release PR explicando o que mudou por crate. +pr_branch_prefix = "release-plz/" +pr_labels = ["release"] +pr_name = "chore: release" + +# Atualizações de dependências internas no workspace — bump dependentes quando +# o crate dependente recebe minor/patch (mantém path-deps consistentes). +dependencies_update = true + +# Crates publicáveis. Listados explicitamente para evitar publicar examples/ +# por engano. release-plz só toca o que está listado. +[[package]] +name = "serverust-macros" +publish = true +publish_features = [] + +[[package]] +name = "serverust-core" +publish = true + +[[package]] +name = "serverust-telemetry" +publish = true + +[[package]] +name = "serverust-events" +publish = true + +[[package]] +name = "serverust-lambda" +publish = true + +[[package]] +name = "serverust-cli" +publish = true + +# Crates internas que NÃO devem ser publicadas (examples, baselines). +[[package]] +name = "hello-world" +publish = false +release = false + +[[package]] +name = "funds-api" +publish = false +release = false + +[[package]] +name = "todo-api" +publish = false +release = false + +[[package]] +name = "kafka-wallet" +publish = false +release = false diff --git a/serverust-cli/Cargo.toml b/serverust-cli/Cargo.toml index 881b7c4..cc47fdd 100644 --- a/serverust-cli/Cargo.toml +++ b/serverust-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serverust-cli" -version = "0.1.6" +version = "0.3.0" edition.workspace = true rust-version.workspace = true authors.workspace = true diff --git a/serverust-events/Cargo.toml b/serverust-events/Cargo.toml index 8b58ceb..ea2a649 100644 --- a/serverust-events/Cargo.toml +++ b/serverust-events/Cargo.toml @@ -150,3 +150,8 @@ required-features = ["sqs"] [[test]] name = "sqs_observability" required-features = ["sqs"] + +# cargo-machete false positives: aws-config é ativado por features que machete +# não enumera; pin-project-lite é usado em codegen das macros Tower. +[package.metadata.cargo-machete] +ignored = ["aws-config", "pin-project-lite"] diff --git a/serverust-telemetry/Cargo.toml b/serverust-telemetry/Cargo.toml index 34b4e69..c988554 100644 --- a/serverust-telemetry/Cargo.toml +++ b/serverust-telemetry/Cargo.toml @@ -54,3 +54,8 @@ dynamodb = ["dep:aws-sdk-dynamodb", "dep:aws-config"] tokio = { version = "1", features = ["macros", "rt-multi-thread"] } tower = { version = "0.5", features = ["util"] } serverust-macros = { path = "../serverust-macros", version = "0.3.0" } + +# cargo-machete false positives: aws-config e tracing-opentelemetry são ativados +# por features (otel/dynamodb) que machete não enumera por padrão. +[package.metadata.cargo-machete] +ignored = ["aws-config", "tracing-opentelemetry"]