`releaser` is a single-binary Go tool for GitFlow-based release automation. It targets Conventional Commits, versioned release branches (`release/X.Y`), and GitLab / GitHub release creation.
- **No error handling for impossible paths** — trust internal invariants; only validate at system boundaries.
- **No abstractions ahead of need** — three similar lines beats a premature helper.
## Test coverage
**100% per-package statement coverage is required** across all packages. Run:
```bash
go test ./... -cover
```
Every package must show `coverage: 100.0% of statements`.
Strategies used in this project:
- **Error path injection**: override `var absPath`, `var gitAllCommits`, etc. to return injected errors.
- **Filesystem tricks**: `os.Mkdir` where a file is expected (invisible to go-git dirty check; fails os.WriteFile/os.ReadFile); `os.Chmod(..., 0444)` to make files read-only.
- **Null byte paths**: `"path\x00name"` causes `os.Stat` to return `EINVAL` (not `ErrNotExist`), useful for testing stat-error paths that differ from file-not-found.
- **In-memory git repos**: use go-git `PlainInit` + local bare remote for push tests.
- **Direct function calls**: call unexported helpers (e.g. `printVerboseConfig`) directly with crafted inputs to cover branches that are dead via normal CLI flow.
## Fuzzing
**Every package that parses free-form text or reads/writes arbitrary file content must have at least one fuzz test.** Run the full seed corpus with:
```bash
go test -run='^Fuzz' ./...
```
All seed cases must pass. The table below is authoritative — keep it in sync when adding packages or parsers:
| Package | Fuzz target(s) | Why |
|---------|---------------|-----|
| `internal/branch` | `FuzzParse` | parses branch name strings |
Packages **not** requiring fuzz tests (no free-form text parsing): `internal/config` (yaml.v3 handles parsing), `internal/ghclient` (HTTP client, no text parsing), `internal/gitutil` (git operations), `internal/version` (typed inputs only), `cmd` (CLI orchestration). When adding a new package, check whether it parses text or rewrites files — if yes, add a row above.
- Include a realistic happy-path input as the first seed.
- Include empty string, binary/non-UTF-8 bytes (`"\x00\xff"`), and inputs that stress known branches (e.g. existing `## [version]` heading for changelog).
- The fuzz body must never assert on return values — only verify no panic.
**Every change that adds, changes, or removes a feature, flag, or config key must update all of the following in the same commit:**
-`README.md` — features list, usage examples, option tables, version badge
-`CHANGELOG.md` — new dated `## [X.Y.Z]` entry (see `/release` skill for format)
-`ROADMAP.md` — mark shipped items `✓`, add a "Shipped in vX.Y.Z" note, drop outdated caveats
- Hugo docs under `docs/content/` (`installation.md`, `usage.md`, `configuration.md`, `ci-integration.md`, `changelog.md`) — whichever pages describe the changed behavior
Treat these as one unit: a PR that changes CLI behavior or config but leaves any of the above stale is incomplete. `docs/content/changelog.md` only needs an entry for tagged (minor/major) releases, matching the pattern already in that file — patch-only releases are covered by the root `CHANGELOG.md` but not duplicated there.