Package
Which package does this affect? [x] cli [ ] action [ ] schema
Problem / Motivation
In `src/monorepo.rs`, `run_release_logic` iterates over `config.packages` sequentially (line 438: `for (pkg_idx, pkg) in config.packages.iter().enumerate()`). For each package it:
- Calls `crate::git::find_highest_semver_tag` (walks all tags via `tag_foreach`).
- Calls `get_commits_since_last_stable_tag` / `get_commits_since_last_tag` (revwalks the entire commit history from HEAD).
- Calls `read_version` (file I/O + parsing per format).
These are independent per-package: no shared mutable state, no inter-package ordering until the cascade phase that runs afterwards. On a 200-package monorepo (see `Fixtures/fixtures/examples/large-monorepo.json`) the wall time is dominated by the per-package revwalk, which is embarrassingly parallel.
Benchmarks (`Benchmarks` repo, fixture `mono-large-ferrflow-binary-check`) currently have absolute thresholds of 2000ms for check / 500ms for version on the large monorepo — there's headroom to claim a 4-8× speedup on multi-core CI runners.
Proposed solution
- Add `rayon = "1"` to `cli` feature deps.
- Extract the per-package analysis loop into a pure function: `(pkg, &config, &repo_root, &all_tags) -> PackagePlan { name, current, next, bump, commits, tag }`.
- Wrap with `config.packages.par_iter().map(...).collect::<Result<Vec<_>>>()`.
- Keep the write/commit/tag/hook side-effect phase sequential — it must remain deterministic.
`git2` repository handles are not Send, so each rayon thread opens its own `Repository` (cheap — discover only). Pre-compute `all_tags` once on the main thread before fanout, so the parallel work doesn't repeat `collect_all_tags`.
Alternatives considered
- `tokio` async — `git2` is sync, no benefit.
- Don't parallelize — fine for repos with <10 packages, but the benchmark fixture sized at 200 packages is unrealistic to keep serial.
Additional context
Severity: P2. Closes / aligns with #417 (wire benchmarks for regression tracking) — once parallelisation lands the benchmark numbers become the gate against future regressions.
Package
Which package does this affect? [x] cli [ ] action [ ] schema
Problem / Motivation
In `src/monorepo.rs`, `run_release_logic` iterates over `config.packages` sequentially (line 438: `for (pkg_idx, pkg) in config.packages.iter().enumerate()`). For each package it:
These are independent per-package: no shared mutable state, no inter-package ordering until the cascade phase that runs afterwards. On a 200-package monorepo (see `Fixtures/fixtures/examples/large-monorepo.json`) the wall time is dominated by the per-package revwalk, which is embarrassingly parallel.
Benchmarks (`Benchmarks` repo, fixture `mono-large-ferrflow-binary-check`) currently have absolute thresholds of 2000ms for check / 500ms for version on the large monorepo — there's headroom to claim a 4-8× speedup on multi-core CI runners.
Proposed solution
`git2` repository handles are not Send, so each rayon thread opens its own `Repository` (cheap — discover only). Pre-compute `all_tags` once on the main thread before fanout, so the parallel work doesn't repeat `collect_all_tags`.
Alternatives considered
Additional context
Severity: P2. Closes / aligns with #417 (wire benchmarks for regression tracking) — once parallelisation lands the benchmark numbers become the gate against future regressions.