Skip to content

Latest commit

 

History

History
479 lines (337 loc) · 18.5 KB

File metadata and controls

479 lines (337 loc) · 18.5 KB

novalyn Task Breakdown (Parity Port of @unjs/changelogen)

Purpose: Actionable, ordered task list to implement the Rust parity version (no generic templating; fixed layout). Mirrors JS behavior while adapting to both Cargo and npm packaging via NAPI-RS.
Reference Specs: parity spec (sections indicated as §), JS source inventory.


Legend

  • Unstarted
  • [~] In progress
  • Done
  • ⚠ Needs decision
  • ⏩ Can be parallelized
  • 🧪 Testing-focused
  • 🔁 Iterative / revisit after benchmarks

0. Meta / Project Initialization

  1. Create repository scaffolding
    • Files: Cargo.toml, .gitignore, LICENSE (MIT), README stub, tasks.md (this), parity spec file.
  2. Configure MSRV (1.89.0) via CI + rust-toolchain.toml.
  3. Add base dependencies (no unused): git2, semver, clap, anyhow, thiserror, serde, serde_json, toml_edit, tracing, tracing-subscriber, rayon, jiff, reqwest (http requests), demand (prompting, kind of like huh? in go), dashmap (use if need hashmaps), git-conventional. For npm packaging: napi and napi-derive.
  4. Dev deps: insta, assert_fs, tempfile, proptest, divan, cargo-deny, nextest.
  5. Set up CI workflow skeleton (Linux only first, then all OS).

1. Configuration Layer (§5, §6, §15)

  1. Implement defaults map exactly matching JS config.ts (types + emojis + semver).
  2. Support config file novalyn.toml.
  3. Support fallback [package.metadata.novalyn] in Cargo.toml.
  4. Implement environment token resolution precedence (NOVALYN_TOKENS_GITHUB > GITHUB_TOKEN > GH_TOKEN).
  5. Implement overlay merge order: defaults < file(s) < CLI overrides.
  6. Support disabling a type via boolean false (TOML loader logic).
  7. Validate newVersion (semver parse).
  8. Warn on unknown keys (collect & log).
  9. Expose ResolvedConfig with normalized paths, resolved repo data (placeholder until repo module ready).

🧪 Tests:

  • Default config equality snapshot.
  • Override precedence (CLI wins).
  • Boolean disabling of type.
  • Token env override test.

2. Repo & Provider Resolution (§3.5, §5.1.4, §9)

  1. Implement remote URL parsing (GitHub/GitLab/Bitbucket patterns).
  2. Infer provider + domain from origin; fallback to config override.
  3. Implement reference URL mapping spec (commit/issue/pull).
  4. Implement compare link function (provider differences).
  5. Add formatting helpers: format_reference, format_compare_link (implemented + tests; integrate during rendering phase).

🧪 Tests:

  • Parse SSH style URL.
  • Parse HTTPS URL with .git suffix.
  • Compare link generation per provider.

3. Git Layer (§7)

  1. Implement repo detection + error if not a git repo.
  2. Implement last tag discovery (semver tags; accept both vX.Y.Z and X.Y.Z; prefer latest by commit date).
  3. Implement current ref (tag or branch HEAD).
  4. Commit enumeration between (from, to].
  5. Provide RawCommit struct (id, short_id, summary, body, author, timestamp).
  6. Dirty working tree detection.
  7. Utility: add & commit, create annotated/signed tag (shell fallback for signed).

🧪 Tests:

  • No tags scenario.
  • Single tag detection.
  • Dirty tree detection.

4. Parsing & Classification (§7.4–7.7)

  1. Implement conventional header parsing: type, optional scope, optional !, description (case-insensitive type).
  2. Manual fallback if git-conventional crate unavailable.
  3. Implement breaking footer detection (BREAKING CHANGE: / BREAKING-CHANGE:).
  4. Implement issue / PR reference scanning (#\d+).
  5. Implement Co-authored-by detection accumulating authors.
  6. Scope mapping via config.scopeMap.
  7. Normalize type to lowercase (§ commands/default.ts behavior).
  8. Filter commits: remove disabled types; filter chore(deps) unless breaking (mirror JS logic).

🧪 Tests:

  • Header with scope + bang.
  • Footer-only breaking.
  • Multiple issue references.
  • Co-authored-by accumulation.
  • chore(deps) filtered when not breaking.

5. Semver Inference & Version Bump (§4, §8)

  1. Determine major/minor/patch flags using type semver + breaking flag.
  2. Pre-1.0 adjustment: major→minor, minor→patch.
  3. [~] Default to "patch" if zero bump-worthy changes (JS parity) – adjusted to no version bump when zero commits (idempotent rerun); revisit for parity decision.
  4. Apply explicit newVersion override if provided after inference.
  5. [⚠] Implement suffix logic (optional; deferred to backlog).
  6. Implement Cargo.toml version bump via toml_edit (preserve formatting).

🧪 Tests:

  • Major inference via breaking.
  • Minor inference via feat only.
  • Patch inference via fix only.
  • 0.x adjustments.
  • Explicit newVersion override.
  • Idempotent (same version returns false result). (Covered via override/empty commit test producing patch bump.)

6. Interpolation (§6, §10)

  1. Implement simple token replacement for commitMessage/tagMessage/tagBody.
  2. Support tokens: {{newVersion}}, {{previousVersion}}, {{date}}.
  3. Unknown tokens remain as-is.
  4. Date format: YYYY-MM-DD (UTC).

🧪 Tests:

  • All tokens replaced.
  • Unknown token retention.
  • Date stable formatting. (explicit test interpolation_date_format)

7. Authors Aggregation (§8, §13)

  1. Aggregate primary + co-authors.
  2. Deduplicate (name+email).
  3. Exclude authors (exact match list).
  4. hideAuthorEmail support.
  5. noAuthors flag suppression.
  6. Preserve first-seen order.

🧪 Tests:

  • Exclusion logic.
  • hideAuthorEmail formatting.
  • Dedup.

8. Rendering (Markdown) (§2, §9)

  1. Section ordering = order of active types in config.
  2. Include only non-empty sections.
  3. Commit line formatting with or without scope.
  4. Append references (linked if provider resolved).
  5. Add compare link (if previous tag exists).
  6. Contributors section conditionally.
  7. Consistent trailing newline.
  8. Deterministic ordering: chronological ensured; tie-break test added.
  9. Provide function render_release_block.

🧪 Tests:

  • Snapshot standard release block.
  • Empty sections trimmed (implicit via non-empty sections logic; add explicit snapshot later).
  • Compare link presence (covered indirectly in render logic; add explicit test later).
  • Contributors ordering (implicit insertion order; dedicated test pending).

9. Changelog File Handling (§15, §19, §32)

  1. Read existing file if present; else bootstrap "# Changelog".
  2. Locate first release header; prepend new block above it.
  3. Idempotence check: if same version already at top and identical body, skip write.
  4. Provide write_or_update_changelog (diff summary pending -> backlog note).

🧪 Tests:

  • Prepend first release.
  • Subsequent release insertion.
  • Idempotent rerun no duplication.

10. Release Pipeline (§11, §27)

  1. Orchestrate steps: config load → git range → parse → classify → bump → render → write → tag (GitHub sync pending).
  2. Dry run support (skip writes/tag).
  3. Exit code mapping (0 success, 3 no-change).
  4. Summary output (basic version + commit count; tag implicit; enhancement backlog).
  5. Respect clean flag (implemented).

🧪 Tests:

  • Dry run leaves files unchanged.
  • Exit code 3 scenario (no-change path) with idempotent version.
  • Signed tag attempt (simulate annotated path success).

11. GitHub Release Sync (§12, §23)

  1. Implement GET release by tag; create or update. (basic happy path)
  2. Fallback manual URL when token absent or error.
  3. [~] Redact token in logs. (token never logged; explicit redaction still to add if future logging)
  4. Provide status struct to caller.
  5. Optionally --github subcommand to resync existing tag with current body.

🧪 Tests (network mock or feature-gated):

  • Manual fallback without token.
  • Update path after create.

12. CLI Design (§14)

  1. Implement show (print inferred next version).
  2. Implement generate (print block; optional --write).
  3. Implement release (full pipeline minus GitHub sync).
  4. Implement github (sync only) if maintained.
  5. Global flags: implemented --from, --to, --new-version, --sign (placeholder), --no-authors, --exclude-author, --cwd, --dry-run, --clean, --output, -v/--verbose, --yes (with confirmation prompts).
  6. Verbosity flags or RUST_LOG integration (tracing subscriber added).
  7. Helpful --help docs per subcommand (clap derived; test added).

🧪 Tests:

  • CLI argument parsing snapshot (help snapshot).
  • Unknown subcommand error.

12.5. NAPI-RS Integration for npm Publishing

80.1. [ ] Add napi and napi-derive dependencies conditionally via feature flag. 80.2. [ ] Create NAPI bindings module exposing core functionality. 80.3. [ ] Implement JavaScript-compatible API surface (async where needed). 80.4. [ ] Add package.json with proper npm metadata and binary configuration. 80.5. [ ] Set up NAPI-RS build pipeline for cross-platform binaries. 80.6. [ ] Create TypeScript definitions for the npm package. 80.7. [ ] Add npm-specific documentation and examples.

🧪 Tests:

  • NAPI bindings compile and expose expected API.
  • npm package installation and basic usage.
  • Cross-platform binary compatibility.

13. Parallel Parsing (§17)

  1. Implement threshold env override & CLI override (optional).
  2. Use rayon for parse/classify only when commit_count >= threshold.
  3. Maintain original index for stable ordering.
  4. Provide debug logs indicating mode.

🧪 Tests:

  • Output identical sequential vs parallel (snapshot diff).
  • Force parallel with small set (env var) still identical.

14. Logging & Telemetry (§18)

  1. Integrate tracing subscriber (env filter).
  2. Add spans: collect_commits, parse_classify, infer_version, render, write, tag (github_sync to add on invocation path).
  3. Debug-level per-commit classification log.
  4. Provide minimal JSON log format stub (optional backlog).

🧪 Tests:

  • Smoke log initialization (no panic).
  • Verbose toggle effect.

15. Error Handling (§18, §21)

  1. Define Error enum (Config, Git, Network, IO, Semantic).
  2. Map to exit codes.
  3. Wrap CLI main with error -> stderr formatted line.
  4. Avoid panics outside unrecoverable invariants.

🧪 Tests:

  • Config parse failure case.
  • No git repo detection.

16. Authors & Contributors Edge Enhancements

  1. Normalize unicode (NFC) for consistent grouping.
  2. Provide optional aliasing (fully implemented with GitHub integration for email->handle mapping, enabled by default).

17. Benchmarks (§22, §33)

  1. Benchmark synthetic commit generation utility.
  2. Implement parse_seq_vs_parallel benchmark (using divan).
  3. Implement render_block benchmark (vary commit counts).
  4. Implement version_inference benchmark.
  5. Document baseline results.
  6. Evaluate dashmap effect; remove if <5% improvement (then: update Cargo.toml).

18. Documentation (§22, §29)

  1. README: parity statement, quick start, differences vs JS (available via both Cargo and npm).
  2. CONTRIBUTING: dev setup, MSRV, tests, benchmarks, release instructions.
  3. PERF docs: initial benchmark table.
  4. PARITY_SPEC inclusion & cross-link tasks.md.
  5. Changelog bootstrapped by tool itself for first release.

19. Quality Gates (§24, §28, §34)

  1. Clippy: deny(warnings).
  2. cargo-deny: license & advisories clean (config added; check pending install).
  3. No unwrap() outside tests (or justify).
  4. Determinism test repeated run identical output.
  5. Validate no leftover TODO markers for MVP (or track in backlog list).
  6. Document and enforce dev workflow (fmt, clippy, nextest) (see Section 25).

20. CI Expansion

  1. Add matrix (linux, macOS, windows).
  2. Add MSRV job.
  3. Add cache (actions-rs or dtolnay/rust-toolchain + Swatinem/rust-cache).
  4. Add test coverage (cargo-tarpaulin).
  5. Optional scheduled dependency audit.

21. Release Preparation

  1. Ensure tool self-generates initial CHANGELOG.md via release --dry-run.
  2. Tag v0.1.0 (manual first).
  3. Publish crate (cargo publish) – optional if scope private initially.
  4. Publish npm package (npm publish) via NAPI-RS build.
  5. Verify install instructions (cargo install and npm install).
  6. Announce parity & solicit feedback before adding new features.

22. Backlog (Not in MVP)

  • Workspace multi-crate support.
  • JSON export mode.
  • Pre-release channels.
  • Template customization extension (if user demand).
  • Git hosting expansions beyond basic provider inference logic.
  • Hook/plugin architecture.

23. Dependency Audit / Pruning Pass

  1. After benchmarks: remove dashmap if not beneficial.
  2. Evaluate need for reqwest until GitHub sync matured.
  3. Confirm no accidental heavy transitive crates (document compile times).

24. Final Verification Checklist (All Must Pass)

  • Matches JS output for a sampled repository (diff = empty).
  • Parallel vs sequential identical.
  • Signed tag path error messaging clear (if GPG absent).
  • New version bump logic conforms to 0.x rules & explicit override.
  • Idempotent rerun no duplication.
  • Contributors section correctness (exclusions, email hiding).
  • Compare link correct for GitHub & GitLab test remotes.
  • All tests green on all CI platforms.
  • No extraneous dependencies (review completed).

Suggested Work Streams (Parallelization)

A. Config + Repo + Interpolation (Tasks 6–19, 41–44)
B. Git + Parsing + Classification (20–34)
C. Semver + Cargo Bump (35–40)
D. Rendering + Changelog (51–63)
E. Release Pipeline + CLI (64–80)
F. GitHub Sync (69–73)
G. Parallelization + Benchmarks (81–84, 95–100)
H. Docs + QA + CI (101–115, 106–110, 111–115)


Milestone Gates

Milestone 1 (Core Parse): Tasks 6–34 complete, basic CLI show/generate prints block.
Milestone 2 (Versioning): Tasks 35–44 integrated; show command reports version.
Milestone 3 (Changelog): Tasks 51–63; generate updates file.
Milestone 4 (Release Pipeline): Tasks 64–80; release end-to-end (no GitHub).
Milestone 5 (GitHub Sync + Authors Polish): Tasks 45–50, 69–73.
Milestone 6 (Performance & Parallel): Tasks 81–84, 95–100 done, dashmap decision.
Milestone 7 (Docs & CI & QA): Tasks 101–115, 106–110, 111–115.
Milestone 8 (Release v0.1.0): Tasks 116–120 + final checklist.


Risk Mitigation Notes

  • Divergent Output: Keep golden snapshot from JS tool early; diff after each milestone.
  • Ordering Drift: Preserve original commit index; assert in test.
  • Semver Edge Drift: Build matrix comparing JS vs Rust inference using exported commit JSON fixtures.
  • Performance Regression: Store baseline benchmark results in PERF doc; compare in CI (optional threshold assertion).
  • Scope Creep: Any new feature must enter backlog; not merged into MVP branches.

Backlog Capture Mechanism

Add new potential features to a BACKLOG.md with: ID, description, rationale, requested-by, complexity estimate.


25. Developer Workflow / Quality Convenience

Guidelines (non-functional tasks, but enforceable via CI/hooks):

A. Pre-commit local checklist

  • cargo fmt --all (format code)
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo nextest run
  • cargo test --doc (doc tests separately if any)
  • cargo deny check (optional fast path)

B. Optional git hook (.git/hooks/pre-commit example) – add later to repo docs:

#!/usr/bin/env bash
set -euo pipefail
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo nextest run

C. CI Enhancements (tie to tasks 106–111, 111–115):

  • Add clippy & fmt check steps before tests.
  • Cache target to speed nextest.
  • Future: coverage (llvm-cov) gate.

D. Fast feedback loop:

  • Use cargo watch -x 'clippy -- -D warnings' -x 'nextest run' for iterative dev.

E. Panics policy:

  • Outside tests: avoid unwrap/expect; map errors. (Tied to task 108).

F. Pending automation tasks:

  • Add justfile with common recipes (just test, just lint).
  • Add CONTRIBUTING.md referencing this section.

(End of tasks.md)