Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Release

on:
push:
tags:
- "v*"

env:
CARGO_TERM_COLOR: always

jobs:
publish:
name: Publish to crates.io
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2

- name: Validate tag version matches Cargo.toml
run: |
TAG_VERSION="${GITHUB_REF_NAME#v}"
CARGO_VERSION=$(cargo metadata --no-deps --format-version 1 | python -c 'import json,sys;print(next(p["version"] for p in json.load(sys.stdin)["packages"] if p["name"]=="ripdiff"))')
if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
echo "Tag version ($TAG_VERSION) does not match Cargo.toml version ($CARGO_VERSION)"
exit 1
fi

- name: Package check
run: cargo package --allow-dirty

- name: Publish crate
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish --locked

- name: Generate release notes
run: |
{
echo "## ripdiff $GITHUB_REF_NAME"
echo
echo "Published to crates.io from tag \\`$GITHUB_REF_NAME\\`."
echo
echo "Install with:"
echo "\\`\\`\\`bash"
echo "cargo install ripdiff"
echo "\\`\\`\\`"
} > release-notes.md

- name: Create GitHub release
uses: softprops/action-gh-release@v2
with:
body_path: release-notes.md
14 changes: 14 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@
name = "ripdiff"
version = "0.1.0"
edition = "2021"
rust-version = "1.85"
default-run = "ripdiff"
description = "Terminal UI for watching and reviewing agent progress"
license = "MIT"
repository = "https://github.com/martinabeleda/ripdiff"
homepage = "https://github.com/martinabeleda/ripdiff"
documentation = "https://docs.rs/ripdiff"
readme = "README.md"
keywords = ["git", "diff", "tui", "review", "agent"]
categories = ["command-line-utilities", "development-tools"]
include = ["src/**", "Cargo.toml", "README.md", "LICENSE"]

[[bin]]
name = "ripdiff"
path = "src/main.rs"

[[bin]]
name = "rd"
path = "src/main.rs"

[dependencies]
ratatui = "0.29"
crossterm = "0.28"
Expand Down
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,35 @@
░░░░░
```

A terminal UI for navigating git diffs, designed for a tmux panel workflow where you monitor AI agent changes on one side while working on the other.
A terminal UI for watching and reviewing agent progress, designed for a tmux panel workflow where you monitor agent changes on one side while working on the other.

Uses [difftastic](https://difftastic.wilfred.me/) for structural, syntax-aware diffs with ANSI color output via an in-process Rust dependency.

## Install

### Install from crates.io

```bash
cargo install ripdiff
```

This installs `ripdiff` into `~/.cargo/bin/`.

### Install from source (local checkout)

```bash
cargo install --path .
```

This puts `ripdiff` in `~/.cargo/bin/`.
For best results, install difftastic:

```bash
cargo install difftastic
```

## Releasing

Maintainer release instructions live in [RELEASING.md](/home/mabeleda/Development/ripdiff/RELEASING.md).

## Usage

Expand Down
79 changes: 79 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Releasing

This document describes the maintainer release process for `ripdiff`.

## Versioning

`ripdiff` follows [Semantic Versioning](https://semver.org/) (`MAJOR.MINOR.PATCH`):

- `PATCH` for bug fixes and internal improvements.
- `MINOR` for backwards-compatible features.
- `MAJOR` for breaking changes.

## Release Workflow

Releases are driven by git tags.

The GitHub Actions workflow in [.github/workflows/release.yml](/home/mabeleda/Development/ripdiff/.github/workflows/release.yml#L1) runs when a tag matching `v*` is pushed. It:

1. Checks that the tag version matches `Cargo.toml`.
2. Verifies the crate can be packaged.
3. Publishes the crate to crates.io.
4. Creates a GitHub release for the tag.

To publish from CI, the repository must have a `CARGO_REGISTRY_TOKEN` secret containing a crates.io API token.

## Recommended Process

Use [`cargo-release`](https://github.com/crate-ci/cargo-release) to bump the crate version and create the matching tag in one step.

Releases should only be cut from `main`. This keeps each published version tied to the reviewed, canonical branch state and avoids accidentally releasing from an unmerged branch or local-only commit. The repository's `cargo-release` configuration enforces this with `allow-branch = ["main"]`.

Install it once:

```bash
cargo install cargo-release
```

Preview a release:

```bash
cargo release patch
```

Run a release:

```bash
cargo release patch --execute
```

Replace `patch` with `minor` or `major` as needed.

With the repository configured for `cargo-release`, the executed command should:

1. Update `Cargo.toml` to the next version.
2. Create a release commit.
3. Create a matching tag like `v0.1.1`.
4. Push the commit and tag to `origin`.

After the tag is pushed, GitHub Actions performs the actual crates.io publish and creates the GitHub release.

## Maintainer Checklist

1. Ensure CI is green locally or on `main`:
```bash
cargo fmt
cargo clippy --all-targets --all-features
cargo test
cargo build
```
2. Run a dry run:
```bash
cargo release patch
```
3. Execute the release:
```bash
cargo release patch --execute
```
4. Verify the GitHub Actions release workflow succeeds.
5. Verify the new version appears on crates.io.
12 changes: 12 additions & 0 deletions release.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
allow-branch = ["main"]
consolidate-commits = true

tag-name = "v{{version}}"
tag-message = "ripdiff {{version}}"

pre-release-commit-message = "release: {{version}}"
push-remote = "origin"

publish = false
push = true
tag = true
Loading