# Packaging Guide
This guide covers how to package and distribute stout through various package managers.
## Overview
stout is distributed through multiple channels:
| GitHub Releases | Binary downloads | All users |
| curl installer | Automated install | Quick setup |
| Homebrew | `brew install` | macOS/Linux users |
| AUR | `yay -S stout` | Arch Linux users |
| Nix | `nix run` | NixOS users |
| crates.io | `cargo install` | Rust developers |
## GitHub Releases
### Automated Release Process
When a tag is pushed (e.g., `v0.1.0`), the release workflow:
1. **Builds binaries** for all platforms:
- `x86_64-unknown-linux-gnu` (Linux x86_64, glibc)
- `x86_64-unknown-linux-musl` (Linux x86_64, musl)
- `aarch64-unknown-linux-gnu` (Linux ARM64)
- `x86_64-apple-darwin` (macOS Intel)
- `aarch64-apple-darwin` (macOS Apple Silicon)
2. **Creates archives** and checksums:
- `stout-<target>.tar.gz`
- `stout-<target>.tar.gz.sha256`
3. **Publishes release** with all artifacts
### Creating a Release
```bash
# 1. Update version
# Edit Cargo.toml files to bump version
# 2. Commit changes
git add -A
git commit -m "Release v0.2.0"
# 3. Create tag
git tag v0.2.0
# 4. Push (triggers release workflow)
git push origin main --tags
```
## curl Installer
The `install.sh` script provides one-command installation:
```bash
### How It Works
1. Detects OS (`linux`/`darwin`) and architecture (`x86_64`/`aarch64`)
2. Fetches latest version from GitHub API
3. Downloads appropriate binary and checksum
4. Verifies SHA256 checksum
5. Installs to `~/.local/bin` or `/usr/local/bin`
6. Adds to PATH if needed
### Environment Variables
| `STOUT_INSTALL_DIR` | Installation directory | `~/.local/bin` |
| `STOUT_VERSION` | Specific version | Latest |
| `STOUT_NO_MODIFY_PATH` | Skip PATH modification | 0 |
## Homebrew
### Tap Setup
1. Create `neul-labs/homebrew-tap` repository
2. Add `Formula/stout.rb`
3. Users install via `brew install neul-labs/tap/stout`
### Formula Structure
```ruby
class Stout < Formula
desc "Fast, Rust-based Homebrew-compatible package manager"
homepage "https://github.com/neul-labs/stout"
version "0.1.0"
license "MIT"
on_macos do
on_arm do
url "https://github.com/.../stout-aarch64-apple-darwin.tar.gz"
sha256 "..."
end
on_intel do
url "https://github.com/.../stout-x86_64-apple-darwin.tar.gz"
sha256 "..."
end
end
on_linux do
# Similar structure
end
def install
bin.install "stout"
generate_completions_from_executable(bin/"stout", "completions")
end
test do
assert_match "stout #{version}", shell_output("#{bin}/stout --version")
end
end
```
### Updating After Release
```bash
cd packaging/homebrew
./update-formula.sh 0.2.0
# Copy to tap repo and push
```
## Arch User Repository (AUR)
### Packages
- `stout` - Build from source
- `stout-bin` - Pre-built binary
### Publishing to AUR
```bash
# Clone AUR repo
git clone ssh://aur@aur.archlinux.org/stout.git
# Update PKGBUILD
cd stout
vim PKGBUILD # Update version, checksums
# Generate .SRCINFO
makepkg --printsrcinfo > .SRCINFO
# Commit and push
git add PKGBUILD .SRCINFO
git commit -m "Update to 0.2.0"
git push
```
### Testing Locally
```bash
# Build package
makepkg -f
# Install
makepkg -si
# Check with namcap
namcap PKGBUILD
namcap stout-0.2.0-1-x86_64.pkg.tar.zst
```
## Nix
### Flake Usage
```bash
# Run without installing
nix run github:neul-labs/stout
# Install to profile
nix profile install github:neul-labs/stout
# Development shell
nix develop github:neul-labs/stout
```
### Adding to nixpkgs
Submit PR to nixpkgs with package in `pkgs/by-name/br/stout/package.nix`.
## crates.io
### Publishing
The release workflow automatically publishes to crates.io after creating the GitHub release.
Crates are published in dependency order:
1. `stout-index`
2. `stout-state`
3. `stout-resolve`
4. `stout-fetch`
5. `stout-install`
6. `stout`
### Manual Publishing
```bash
# Login (one-time)
cargo login
# Publish in order
cargo publish -p stout-index
cargo publish -p stout-state
cargo publish -p stout-resolve
cargo publish -p stout-fetch
cargo publish -p stout-install
cargo publish
```
### Requirements
Each crate's `Cargo.toml` must have:
- `version` - Semantic version
- `description` - Short description
- `license` - License identifier
- `repository` - GitHub URL
- `readme` - README file path (optional)
## Version Management
### Versioning Strategy
We use [Semantic Versioning](https://semver.org/):
- **MAJOR**: Breaking changes
- **MINOR**: New features, backward compatible
- **PATCH**: Bug fixes, backward compatible
### Updating Versions
All `Cargo.toml` files must have matching versions:
```bash
# Use cargo-edit for batch updates
cargo install cargo-edit
cargo set-version 0.2.0
```
Or manually update each:
- `Cargo.toml` (root)
- `crates/stout-index/Cargo.toml`
- `crates/stout-state/Cargo.toml`
- `crates/stout-resolve/Cargo.toml`
- `crates/stout-fetch/Cargo.toml`
- `crates/stout-install/Cargo.toml`
## Secrets Required
GitHub repository secrets needed for automated releases:
| `GITHUB_TOKEN` | Auto-provided, release creation |
| `CARGO_REGISTRY_TOKEN` | crates.io publishing |
| `TAP_GITHUB_TOKEN` | Homebrew tap updates (optional) |
### Setting Up Secrets
1. **CARGO_REGISTRY_TOKEN**:
- Go to https://crates.io/settings/tokens
- Create new token with publish scope
- Add to GitHub repo secrets
2. **TAP_GITHUB_TOKEN** (optional):
- Create PAT with `repo` scope
- Add to GitHub repo secrets
## Troubleshooting
### crates.io Publish Fails
- Check version not already published
- Ensure all dependencies are published
- Wait 30s between publishes for indexing
### Homebrew Formula Issues
```bash
# Audit formula
brew audit --strict stout
# Test installation
brew install --build-from-source ./stout.rb
brew test stout
```
### AUR Build Fails
```bash
# Build in clean chroot
extra-x86_64-build
# Check dependencies
namcap PKGBUILD
```