# Releasing i-self
How to cut a new release and publish to crates.io.
## One-time setup (per maintainer machine)
```bash
# Get a crates.io API token from https://crates.io/me
cargo login
```
You also need:
- Push access to the GitHub repo
- A clean working tree (`git status` shows nothing)
## Cut a release
### 1. Verify the release is buildable end-to-end
```bash
# Locks us to the toolchain we ship against, not whatever's `latest`
cargo +1.88.0 build --release --locked
# Full unit + integration suite
cargo test --bin i-self
cargo test --test share_cycle
# Network-touching tests (opt-in; needs internet for OSV)
cargo test -- --ignored osv_live
```
If any of those fail, **stop**. Fix the failure or yank the offending
change before tagging.
### 2. Update version + CHANGELOG
- Bump `version` in `Cargo.toml` (semver: bug fix → patch, additive →
minor, breaking → major).
- Add a `## [X.Y.Z] - YYYY-MM-DD` section at the top of `CHANGELOG.md`.
Note breaking changes loudly under their own subheading.
- Commit:
```bash
git commit -am "Release X.Y.Z"
```
### 3. Tag and push
```bash
git tag -a vX.Y.Z -m "Release X.Y.Z"
git push origin main vX.Y.Z
```
### 4. Dry-run the publish
```bash
cargo publish --dry-run
```
This validates the package tarball without uploading. Expected
warnings:
- Workspace-related notes are fine since we're a single-crate repo.
- "no upload" message at the end confirms it's dry-run.
If it complains about:
- **missing license file** → the `LICENSE` file at repo root is what
satisfies `license = "MIT"` in `Cargo.toml`. Don't remove it.
- **missing `description`/`license`** → unset metadata field. Look at
the `[package]` block.
- **dependency not on crates.io** → no current crate uses a path or git
dep, so this would mean a regression.
- **package too large** → check `cargo package --list` and add patterns
to the `exclude` list in `Cargo.toml`.
### 5. Publish
```bash
cargo publish
```
This is irreversible. crates.io doesn't allow re-publishing the same
version, only yanking (which hides it from the resolver but doesn't
delete it). If you tagged `vX.Y.Z` and then realize a fix is needed,
bump to `X.Y.Z+1` and re-tag rather than yanking.
### 6. Create the GitHub release
```bash
gh release create vX.Y.Z --notes-file <(awk '/^## /{f=!f; if (f) {print; next}}; f' CHANGELOG.md)
```
(That `awk` snippet extracts the most recent section from CHANGELOG.md.)
## Naming and ownership
The crate name `i-self` was reserved on crates.io with this initial
publish. Future maintainers are added with:
```bash
cargo owner --add <github-username>
```
## What if the crate name is taken?
Run `cargo search i-self` before the first publish. If the name is
unavailable, options:
- Rename the crate (update `name` in `Cargo.toml`, every README/docs
reference, the `[[bin]]` block, and the `git tag` convention).
- Pick a derivative: `i-self-cli`, `iself`, `dev-companion`.
## After publish
- Users can now run `cargo install i-self`.
- `docs.rs` will auto-build documentation from the published source —
no manual step needed.
- Update `README.md` if its install section still says "clone this repo
and `cargo build --release`" — point at `cargo install i-self`
instead.