README.md

# EasyPublish

A complete release tool for Hex packages. Updates version numbers, runs pre-release checks, updates changelog, commits, tags, pushes, creates GitHub release, and publishes to Hex.

## Installation

Add `easy_publish` to your list of dependencies in `mix.exs` as a dev-only dependency:

```elixir
def deps do
  [
    {:easy_publish, "~> 0.1", only: :dev, runtime: false}
  ]
end
```

## Usage

Perform a full release:

```bash
# Bump patch version (0.1.0 -> 0.1.1)
mix easy_publish.release patch

# Bump minor version (0.1.0 -> 0.2.0)
mix easy_publish.release minor

# Bump major version (0.1.0 -> 1.0.0)
mix easy_publish.release major

# Release current version as-is (for initial release)
mix easy_publish.release current

# Set explicit version
mix easy_publish.release 2.0.0
```

Run checks only (no changes made):

```bash
mix easy_publish.release patch --dry-run
```

## Release Flow

### Phase 1: Version Updates

Updates version in all relevant files:
- `mix.exs` - updates `@version` attribute
- `README.md` - updates dependency version (e.g., `{:my_package, "~> 0.2"}`)

### Phase 2: Pre-release Checks

1. Git working directory is clean
2. On correct branch (default: `main`)
3. Git is up to date with remote
4. Tests pass (`mix test`)
5. Code is formatted (`mix format --check-formatted`)
6. Credo passes (if installed)
7. Dialyzer passes (if installed)
8. **UNRELEASED section exists in changelog**
9. `mix hex.build` succeeds (validates package)

### Phase 3: Release

1. Updates changelog: replaces `## UNRELEASED` with `## X.Y.Z - YYYY-MM-DD`
2. Commits all version changes (mix.exs, README.md, CHANGELOG.md)
3. Creates git tag `vX.Y.Z`
4. Pushes commit and tag to remote
5. Creates GitHub release (if `gh` CLI available)
6. Publishes to Hex

## Changelog Format

Your `CHANGELOG.md` should have an UNRELEASED section:

```markdown
# Changelog

## UNRELEASED

- Added new feature
- Fixed bug

## 0.1.0 - 2024-01-15

- Initial release
```

When you run `mix easy_publish.release minor` for version 0.2.0, it becomes:

```markdown
# Changelog

## 0.2.0 - 2024-01-20

- Added new feature
- Fixed bug

## 0.1.0 - 2024-01-15

- Initial release
```

## Options

| Flag | Description |
|------|-------------|
| `--dry-run` | Only run checks, don't make any changes |
| `--skip-tests` | Skip running tests |
| `--skip-format` | Skip format check |
| `--skip-credo` | Skip credo analysis |
| `--skip-dialyzer` | Skip dialyzer |
| `--skip-changelog` | Skip changelog check |
| `--skip-git` | Skip all git checks |
| `--skip-hex-dry-run` | Skip hex.build validation |
| `--skip-github-release` | Skip GitHub release creation |
| `--branch NAME` | Required branch name (default: "main") |
| `--changelog-entry CONTENT` | Add a changelog entry and skip UNRELEASED check |

### Quick releases with `--changelog-entry`

For quick releases where you don't want to manually edit the changelog first:

```bash
# Add a changelog entry and release in one command
mix easy_publish.release patch --changelog-entry "Fixed authentication bug"

# Multiple changes can be separated by newlines
mix easy_publish.release minor --changelog-entry "Added user profiles
Fixed memory leak
Updated dependencies"
```

This will:
1. Add the entry to the UNRELEASED section (creating it if needed)
2. Skip the UNRELEASED section check
3. Proceed with the normal release flow

## Configuration

Configure defaults in your `config/config.exs`:

```elixir
config :easy_publish,
  branch: "main",
  changelog_file: "CHANGELOG.md",
  skip_github_release: false,
  skip_tests: false,
  skip_format: false,
  skip_credo: false,
  skip_dialyzer: false,
  skip_changelog: false,
  skip_git: false,
  skip_hex_dry_run: false
```

CLI flags always override configuration.

### Example configurations

**CI-friendly config** (skip slow checks locally, run them in CI):

```elixir
# config/dev.exs
config :easy_publish,
  skip_dialyzer: true,
  skip_credo: true
```

**Non-GitHub project** (skip GitHub release creation):

```elixir
config :easy_publish,
  skip_github_release: true
```

**Custom branch workflow**:

```elixir
config :easy_publish,
  branch: "develop"
```

### CLI examples

```bash
# Full release with all checks
mix easy_publish.release patch

# Quick release skipping slow checks
mix easy_publish.release patch --skip-dialyzer --skip-credo

# Dry run to validate everything first
mix easy_publish.release minor --dry-run

# Release from a feature branch (not recommended for production)
mix easy_publish.release patch --branch feature/my-branch --skip-git

# Initial release of a new package
mix easy_publish.release current

# Quick bugfix release
mix easy_publish.release patch --changelog-entry "Fixed crash on startup"
```

## GitHub Release

GitHub releases are created automatically using the `gh` CLI if:
- `gh` CLI is installed
- The repository is hosted on GitHub
- `--skip-github-release` is not set

If `gh` is not installed or the repo is not on GitHub, this step is silently skipped.

To install `gh`:
- macOS: `brew install gh`
- Linux: See https://github.com/cli/cli#installation

## License

MIT