Skip to content

Commit 2a5b693

Browse files
committed
refactor: Remove release system, focus on split/sync
BREAKING CHANGE: Removed `cargo rail release` commands cargo-rail now focuses exclusively on what it does uniquely well: splitting crates from monorepos and bidirectional sync. Release automation is better handled by existing specialized tools. **Removed:** - `cargo rail release plan` - `cargo rail release prepare` - `cargo rail release publish` - `cargo rail release finalize` - Release-related dependencies (git-cliff-core, cargo-semver-checks, etc.) - ~114 transitive dependencies (29% reduction: 394→280 crates) **Rationale:** 1. Split/sync is cargo-rail's unique value proposition 2. cargo-release and release-plz already solve releases excellently 3. Split repos should have independent release lifecycles 4. Simpler codebase = easier to maintain and audit 5. Significantly reduced supply chain attack surface **Migration Path:** Use cargo-release or release-plz for publishing: - Monorepo-only crates: `cargo release --workspace` - Split crates: Sync first, then `cd split-repo && cargo release` **Changes:** - Removed entire `commands/release/` module (13 files) - Removed release command from CLI - Removed config.publish field (was only for release filtering) - Removed 10 release integration tests - Updated README with new focused positioning - Added "Publishing Workflow" section recommending existing tools **Metrics:** - Dependencies: 394 → 280 unique crates (-29%) - Tests: All 53 tests passing (19 integration + 34 unit) - Warnings: Zero compiler + zero clippy - Commands: 6 core commands (init, split, sync, doctor, status, mappings) Closes #TBD
1 parent 95f1e87 commit 2a5b693

File tree

23 files changed

+490
-6210
lines changed

23 files changed

+490
-6210
lines changed

Cargo.lock

Lines changed: 427 additions & 3208 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 63 additions & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
**Split Rust crates from monorepos, keep them in sync**
44

5-
Split Rust crates from Cargo workspaces into standalone repos with full git history. Bidirectional sync keeps monorepo and split repos in line. Release automation with semver checks and topological publishing.
5+
Split Rust crates from Cargo workspaces into standalone repos with full git history. Bidirectional sync keeps monorepo and split repos in line.
66

77
[![Crates.io](https://img.shields.io/crates/v/cargo-rail.svg)](https://crates.io/crates/cargo-rail)
88
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/loadingalias/cargo-rail/blob/main/LICENSE)
@@ -12,27 +12,24 @@ Split Rust crates from Cargo workspaces into standalone repos with full git hist
1212
## Status: Production Ready (v0.1)
1313

1414
**Split & Sync:** ✅ Production-ready
15-
**Release Commands:** ✅ Complete (`plan`, `prepare`, `publish`, `finalize`)
1615
**Documentation:** ✅ Complete
1716
**CI Coverage:** ✅ 4 platforms (Linux/Windows x86_64/ARM64) + macOS local
1817

19-
All features stable. Ready for v1.0 release.
18+
All features stable. Focused on split/sync only - use cargo-release or release-plz for publishing.
2019

2120
---
2221

2322
## Why cargo-rail?
2423

25-
| Feature | cargo-rail | cargo-workspaces | release-plz | git-subtree | Copybara |
26-
|---------|------------|------------------|-------------|-------------|----------|
27-
| Split crates | Full history ||| One-way | Complex |
28-
| Bidirectional sync ||||||
29-
| Cargo-aware ||||||
30-
| Release automation || Basic ||||
31-
| Semver checks ||||||
32-
| Dry-run by default ||| Partial |||
33-
| Setup | One TOML | Easy | Easy | Complex | Very complex |
24+
| Feature | cargo-rail | git-subtree | Copybara |
25+
|---------|------------|-------------|----------|
26+
| Split crates | Full history | One-way | Complex |
27+
| Bidirectional sync ||||
28+
| Cargo-aware transforms ||||
29+
| Dry-run by default ||||
30+
| Setup | One TOML | Complex | Very complex |
3431

35-
**cargo-rail = cargo-workspaces + release-plz + git-subtree**
32+
**cargo-rail = git-subtree + cargo transforms + bidirectional sync**
3633

3734
---
3835

@@ -49,15 +46,6 @@ All features stable. Ready for v1.0 release.
4946
- Conflict resolution (ours, theirs, manual, union)
5047
- Two modes: single crate → repo, or multiple crates → combined repo
5148

52-
**Release Automation:**
53-
54-
- Semver enforcement with breaking change detection (cargo-semver-checks)
55-
- Topological publishing (dependencies first)
56-
- Changelog generation from conventional commits (git-cliff)
57-
- Tag management across monorepo and split repos
58-
- Parallel analysis with progress indicators
59-
- Dry-run by default with colorized diffs
60-
6149
---
6250

6351
## Installation
@@ -149,54 +137,50 @@ my-project/
149137

150138
---
151139

152-
## Modes Explained
153-
154-
### Single Mode
140+
## Workflow Example: 25-Crate Monorepo
155141

156-
- **One crate → One repo**
157-
- Use when: Publishing independent crates to crates.io
158-
- Example: Split `crates/http-client``http-client` standalone repo
142+
**Scenario:** 5 proprietary crates, 20 OSS (5 split to separate repos, 15 stay in monorepo)
159143

160-
### Combined Mode
144+
### Development (Monorepo)
161145

162-
- **Multiple crates → One repo**
163-
- Use when: Related crates that should live together
164-
- Example: Split `crates/{client,server,common}``my-project` workspace repo
165-
- Maintains workspace structure in split repo
166-
- All crates keep their workspace dependencies
146+
```bash
147+
cd monorepo/
148+
# ... make changes to crates/my-oss-lib ...
149+
git commit -am "feat: Add feature"
167150

168-
---
151+
# Sync to split repo
152+
cargo rail sync my-oss-lib --apply
153+
```
169154

170-
## Sync Workflow
155+
### Publishing
171156

172-
### Monorepo → Split Repo
157+
**Option 1: Monorepo-only crates** (20 crates)
158+
```bash
159+
cd monorepo/
160+
cargo release --workspace # or release-plz
161+
```
173162

163+
**Option 2: Split crates** (5 crates)
174164
```bash
175-
cd your-workspace/
176-
# Make changes in crates/my-crate/
177-
git commit -am "feat: Add feature"
165+
# Ensure synced
166+
cargo rail sync my-oss-lib --apply
178167

179-
# Sync to split repo (pushes automatically)
180-
cargo rail sync my-crate --apply
168+
# Publish from split repo
169+
cd ../my-oss-lib-split/
170+
cargo release
171+
# Contributors see a normal standalone crate
181172
```
182173

183-
### Split Repo → Monorepo
174+
### External Contributions
184175

185176
```bash
186-
cd my-crate-split/
187-
# Make changes
188-
git commit -am "fix: Bug fix"
189-
git push origin main
190-
191-
cd ../your-workspace/
192-
# Sync from split repo (creates PR branch)
193-
cargo rail sync my-crate --apply
194-
# Creates branch: rail/sync/my-crate/2025-11-11-143022
195-
# Review and merge PR manually
177+
# PR comes into split repo
178+
cd ../monorepo/
179+
cargo rail sync my-oss-lib --apply
180+
# Creates PR branch: rail/sync/my-oss-lib/1763010755
181+
# Review and merge manually
196182
```
197183

198-
**Security:** Split→mono syncs NEVER commit directly to main. Always creates PR branch for review.
199-
200184
---
201185

202186
## Commands
@@ -211,12 +195,6 @@ cargo rail sync --all --apply # Sync all configured splits
211195
cargo rail doctor # Run health checks
212196
cargo rail status # Show configured splits
213197
cargo rail mappings <name> # Inspect git-notes mappings
214-
215-
# Release commands
216-
cargo rail release plan # Preview releases
217-
cargo rail release prepare --apply # Update versions, changelogs
218-
cargo rail release publish --apply # Publish to crates.io
219-
cargo rail release finalize --apply # Create tags, sync to splits
220198
```
221199

222200
---
@@ -235,13 +213,6 @@ require_signed_commits = false
235213
pr_branch_pattern = "rail/sync/{crate}/{timestamp}"
236214
protected_branches = ["main", "master"]
237215

238-
[release]
239-
strategy = "conventional" # or "manual"
240-
tag_format = "{name}@v{version}"
241-
publish_delay = 30 # seconds between dependent publishes
242-
create_github_releases = true
243-
auto_sync_split_repos = true
244-
245216
# Single mode example
246217
[[splits]]
247218
name = "http-client"
@@ -303,36 +274,13 @@ cargo rail sync my-crate --apply --conflict=union # combine both (risky)
303274
│ │ │ │ │ (standalone) │
304275
└──────────┘ └──────────┘ └─────────────────┘
305276
│ │ │
306-
publish │ publish │ publish
277+
cargo release │ cargo release │ cargo release
307278
↓ ↓ ↓
308279
┌────────────────────────────────────────────────┐
309280
│ crates.io registry │
310281
└────────────────────────────────────────────────┘
311282
```
312283

313-
### Split Modes
314-
315-
**Single Mode:**
316-
317-
```
318-
Monorepo Split Repo
319-
crates/my-crate/ → my-crate/
320-
├── src/ ├── src/
321-
├── Cargo.toml ├── Cargo.toml (transformed)
322-
└── README.md └── README.md
323-
```
324-
325-
**Combined Mode:**
326-
327-
```
328-
Monorepo Split Repo
329-
crates/ → my-project/
330-
├── tool-a/ ├── tool-a/
331-
├── tool-b/ ├── tool-b/
332-
└── tool-common/ ├── tool-common/
333-
└── Cargo.toml (workspace)
334-
```
335-
336284
### Sync Flow
337285

338286
```
@@ -357,65 +305,6 @@ SPLIT → MONOREPO (PR Branch - Security)
357305
└──────────────────────────────────────────────┘
358306
```
359307

360-
### Release Flow
361-
362-
```
363-
┌────────────┐
364-
│ PLAN │ Analyze commits, detect API changes
365-
└──────┬─────┘
366-
367-
368-
┌────────────┐
369-
│ PREPARE │ Bump versions, generate changelogs
370-
└──────┬─────┘
371-
372-
373-
┌────────────┐
374-
│ PUBLISH │ Publish to crates.io (topological order)
375-
└──────┬─────┘
376-
377-
378-
┌────────────┐
379-
│ FINALIZE │ Create tags, sync to split repos
380-
└────────────┘
381-
```
382-
383-
### Key Concepts
384-
385-
**Git-Notes Mapping:**
386-
387-
```
388-
refs/notes/rail/{split-name}
389-
390-
monorepo_commit_sha → split_commit_sha
391-
abc123def456... → 789abc012def...
392-
```
393-
394-
**Transform Pipeline:**
395-
396-
```
397-
Monorepo Cargo.toml Split Repo Cargo.toml
398-
[dependencies] → [dependencies]
399-
my-core = { path = "../my-core" } my-core = "0.1.0"
400-
401-
Split Repo Cargo.toml Monorepo Cargo.toml
402-
[dependencies] → [dependencies]
403-
my-core = "0.1.0" my-core = { path = "../my-core" }
404-
```
405-
406-
**Topological Publishing:**
407-
408-
```
409-
Dependency Graph:
410-
my-common (no deps)
411-
412-
my-core (depends on my-common)
413-
414-
my-client (depends on my-core)
415-
416-
Publish Order: my-common → my-core → my-client
417-
```
418-
419308
---
420309

421310
## Security Model
@@ -470,29 +359,26 @@ jobs:
470359
env: { SSH_PRIVATE_KEY: '${{ secrets.DEPLOY_KEY }}' }
471360
```
472361
473-
### Release on Tag
362+
---
474363
475-
`.github/workflows/rail-release.yml`:
364+
## Publishing Workflow
476365
477-
```yaml
478-
name: Release
479-
on:
480-
push:
481-
tags: ['v*']
366+
cargo-rail focuses on split/sync. Use existing tools for releases:
482367
483-
jobs:
484-
release:
485-
runs-on: ubuntu-latest
486-
steps:
487-
- uses: actions/checkout@v4
488-
- uses: dtolnay/rust-toolchain@stable
489-
- run: cargo install cargo-rail
490-
- run: |
491-
cargo rail release prepare --apply
492-
cargo rail release publish --apply --yes
493-
cargo rail release finalize --apply
494-
env:
495-
CARGO_REGISTRY_TOKEN: '${{ secrets.CARGO_TOKEN }}'
368+
**Recommended:**
369+
- [cargo-release](https://github.com/crate-ci/cargo-release) - Simple, battle-tested
370+
- [release-plz](https://github.com/MarcoIeni/release-plz) - Automated releases from CI
371+
- [git-cliff](https://github.com/orhun/git-cliff) - Changelog generation
372+
373+
```bash
374+
# Monorepo-only crates
375+
cd monorepo/
376+
cargo release --workspace
377+
378+
# Split crates
379+
cargo rail sync my-crate --apply # Ensure synced
380+
cd ../my-crate-split/
381+
cargo release # Publish from split repo
496382
```
497383

498384
---
@@ -501,7 +387,6 @@ jobs:
501387

502388
- [USER_GUIDE.md](docs/USER_GUIDE.md) - Complete walkthrough
503389
- [SECURITY.md](docs/SECURITY.md) - Threat model and mitigations
504-
- [RELEASE_GUIDE.md](docs/RELEASE_GUIDE.md) - Release workflow
505390
- [E2E_TESTING_SETUP.md](E2E_TESTING_SETUP.md) - End-to-end testing guide
506391
- [STATUS.md](STATUS.md) - Development status
507392

@@ -536,36 +421,11 @@ cargo rail sync my-crate --apply
536421

537422
## Comparison
538423

539-
**vs cargo-workspaces:** cargo-rail adds split/sync + release (complete workflow)
540-
**vs release-plz:** cargo-rail adds split/sync to release automation
541424
**vs git-subtree:** cargo-rail is bidirectional + Cargo-aware
542425
**vs Copybara:** cargo-rail is simpler (one TOML vs Starlark)
543426
**vs git-filter-repo:** cargo-rail preserves monorepo (non-destructive)
544-
545-
---
546-
547-
## Roadmap
548-
549-
### v1.0 (Ready for Release)
550-
551-
- ✅ Split & sync (single and combined modes)
552-
- ✅ Release automation
553-
- Semver checking (cargo-semver-checks)
554-
- Conventional commits parsing
555-
- Changelog generation (git-cliff)
556-
- Topological publishing
557-
- Tag management
558-
- ✅ Complete documentation
559-
- ✅ CI coverage (6 platforms)
560-
561-
### v1.1+
562-
563-
- Watch mode (`cargo rail watch`)
564-
- Performance optimizations (parallel sync)
565-
- Homebrew formula
566-
- CI templates (GitHub + GitLab)
567-
568-
See [STATUS.md](https://github.com/loadingalias/cargo-rail/blob/main/STATUS.md) for details.
427+
**vs cargo-workspaces:** cargo-rail adds split/sync
428+
**vs release-plz:** cargo-rail adds split/sync (use release-plz for releases!)
569429

570430
---
571431

@@ -589,7 +449,6 @@ MIT - see [LICENSE](https://github.com/loadingalias/cargo-rail/blob/main/LICENSE
589449

590450
- Inspired by Google's Copybara and Meta's Sapling
591451
- Built on [gitoxide](https://github.com/Byron/gitoxide) (pure Rust git)
592-
- Semver checking via [cargo-semver-checks](https://github.com/obi1kenobi/cargo-semver-checks)
593452

594453
---
595454

@@ -610,8 +469,11 @@ A: cargo-rail never commits directly to monorepo main. All syncs create PR branc
610469
**Q: Can I sync multiple splits at once?**
611470
A: Yes: `cargo rail sync --all --apply`
612471

472+
**Q: How do I publish crates?**
473+
A: Use cargo-release or release-plz. cargo-rail focuses on split/sync only.
474+
613475
**Q: Large monorepos (100+ crates)?**
614-
A: v1.0 focuses on 5-50 crates. Larger workspaces need performance tuning (v1.2).
476+
A: Current focus is 5-50 crates. Larger workspaces may need performance tuning.
615477

616478
---
617479

0 commit comments

Comments
 (0)