changelog generator & diff tool stormlightlabs.github.io/git-storm/
changelog changeset markdown golang git
at main 587 lines 13 kB view raw view rendered
1--- 2title: Testing Workflow 3updated: 2025-11-08 4version: 3 5--- 6 7"Ride the lightning." 8 9This document provides a comprehensive testing workflow for the `storm` changelog manager. 10All tests should be run within this repository to validate functionality against real Git 11history. 12 13## Setup 14 15```bash 16# Build the CLI 17task build 18``` 19 20## Non-TTY Environment Handling 21 22Storm automatically detects whether it's running in an interactive terminal (TTY) or a 23non-interactive environment (CI pipelines, scripts, pipes). Commands gracefully degrade 24or provide helpful error messages. 25 26### TTY Detection 27 28The CLI checks for: 29 30- Terminal availability on stdin/stdout 31- Common CI environment variables (GITHUB_ACTIONS, GITLAB_CI, CIRCLECI, etc.) 32 33### Command Behavior 34 35#### `generate --interactive` 36 37**Interactive (TTY):** Launches TUI for commit selection 38**Non-Interactive:** Returns error with suggestion to use non-interactive mode 39 40```bash 41# CI/Non-TTY 42storm generate HEAD~5 HEAD --interactive 43# Error: flag '--interactive' requires an interactive terminal (detected GitHub Actions environment) 44``` 45 46**Workaround:** 47 48```bash 49# Use without --interactive flag for automatic processing 50storm generate HEAD~5 HEAD 51``` 52 53#### `unreleased review` 54 55**Interactive (TTY):** Launches TUI for reviewing entries 56**Non-Interactive:** Returns error with alternatives 57 58```bash 59# CI/Non-TTY 60storm unreleased review 61# Error: command 'storm unreleased review' requires an interactive terminal (detected CI environment) 62# 63# Alternatives: 64# - Use 'storm unreleased list' to view entries in plain text 65# - Use 'storm unreleased list --json' for JSON output 66``` 67 68#### `diff` 69 70**Interactive (TTY):** Launches TUI for navigating diffs 71**Non-Interactive:** Outputs plain text diff to stdout 72 73```bash 74# CI/Non-TTY - automatically outputs plain text 75storm diff HEAD~1 HEAD 76# === File 1/3 === 77# --- HEAD~1:file.go 78# +++ HEAD:file.go 79# [plain text diff output] 80``` 81 82### Testing Non-TTY Behavior 83 84#### Simulate CI environment 85 86```bash 87CI=true storm unreleased review 88# Should error with CI-friendly message 89``` 90 91#### Pipe output 92 93```bash 94storm diff HEAD~1 HEAD | less 95# Should output plain text diff (not TUI) 96``` 97 98#### Redirect to file 99 100```bash 101storm diff HEAD~1 HEAD > changes.diff 102# Should write plain text to file 103``` 104 105**Expected Behaviors:** 106 107- Clear error messages indicating TTY requirement 108- Suggestions for alternative commands 109- CI system name detection (e.g., "detected GitHub Actions environment") 110- Automatic fallback to plain text for `diff` command 111- No ANSI escape codes in piped/redirected output 112 113## Core Workflow 114 115### Manual Entry Creation (`unreleased add`) 116 117Create entries manually without linking to commits. 118 119#### Basic entry creation 120 121```bash 122storm unreleased add --type added --summary "Test manual entry" 123``` 124 125**Expected:** 126 127- Creates `.changes/<timestamp>-test-manual-entry.md` 128- File contains YAML frontmatter with type and summary 129- Styled success message displays created file path 130 131#### Entry with scope 132 133```bash 134storm unreleased add --type fixed --scope api --summary "Fix authentication bug" 135``` 136 137**Expected:** 138 139- Includes `scope: api` in frontmatter 140- Filename slugifies to `...-fix-authentication-bug.md` 141 142#### Collision handling 143 144```bash 145# Run same command twice rapidly 146storm unreleased add --type added --summary "Duplicate test" 147storm unreleased add --type added --summary "Duplicate test" 148``` 149 150**Expected:** 151 152- Two different files created (second has `-1` suffix) 153- Both files exist and are readable 154 155**Edge Cases:** 156 157- Invalid type (should error with helpful message) 158- Missing required flags (should error) 159- Very long summary (should truncate to 50 chars) 160- Special characters in summary (should slugify correctly) 161- Empty summary (should error) 162 163### Commit-Linked Entry Creation (`unreleased partial`) 164 165Create entries linked to specific commits with auto-detection. 166 167#### Basic partial from commit 168 169```bash 170# Use a recent commit hash 171storm unreleased partial HEAD 172``` 173 174**Expected:** 175 176- Auto-detects type from conventional commit format 177- Creates `.changes/<sha7>.<type>.md` 178- Includes `commit_hash` in frontmatter 179- Shows styled success message 180 181#### Override auto-detection 182 183```bash 184storm unreleased partial HEAD~1 --type fixed --summary "Custom summary" 185``` 186 187**Expected:** 188 189- Uses provided type instead of auto-detected 190- Uses custom summary 191- Preserves commit hash in frontmatter 192 193#### Non-conventional commit 194 195```bash 196# Try a commit without conventional format 197storm unreleased partial <old-commit> 198``` 199 200**Expected:** 201 202- Error message: "could not auto-detect change type" 203- Suggests using `--type` flag 204 205#### Duplicate prevention 206 207```bash 208storm unreleased partial HEAD 209storm unreleased partial HEAD # Run again 210``` 211 212**Expected:** 213 214- Second command fails with "file already exists" error 215 216**Edge Cases:** 217 218- Invalid commit ref (should error) 219- Merge commit (should handle gracefully) 220- Initial commit with no parent (should work) 221- Commit with multi-line message (should parse correctly) 222- Commit with breaking change marker (should set `breaking: true`) 223 224### Listing Entries (`unreleased list`) 225 226Display all unreleased changes. 227 228#### Text output 229 230```bash 231storm unreleased list 232``` 233 234**Expected:** 235 236- Color-coded type labels ([added], [fixed], etc.) 237- Shows scope if present 238- Displays filename 239- Shows breaking change indicator if applicable 240- Empty state message if no entries 241 242#### JSON output 243 244```bash 245storm unreleased list --json 246``` 247 248**Expected:** 249 250- Valid JSON array 251- Each entry has type, scope, summary, filename 252- Can be piped to `jq` for processing 253 254**Edge Cases:** 255 256- Empty `.changes/` directory 257- Malformed YAML in entry file 258- Mixed entry types (manual + partial) 259 260### Generating Entries from Git History (`generate`) 261 262Scan commit ranges and create changelog entries. 263 264#### Range generation 265 266```bash 267# Generate from last 5 commits 268storm generate HEAD~5 HEAD 269``` 270 271**Expected:** 272 273- Lists N commits found 274- Creates entries for conventional commits 275- Skips non-conventional commits 276- Shows created count and skipped count 277- Uses diff-based deduplication 278 279#### Interactive selection 280 281```bash 282storm generate HEAD~10 HEAD --interactive 283``` 284 285**Expected:** 286 287- Launches TUI with commit list 288- Shows parsed metadata (type, scope, summary) 289- Allows selection/deselection 290- Creates only selected entries 291- Handles cancellation (Ctrl+C) 292- Errors gracefully in non-TTY with helpful message 293 294#### Since tag 295 296```bash 297storm generate --since v0.1.0 298``` 299 300**Expected:** 301 302- Generates entries from v0.1.0 to HEAD 303- Auto-detects tag as starting point 304 305#### Deduplication 306 307```bash 308storm generate HEAD~3 HEAD 309storm generate HEAD~3 HEAD # Run again 310``` 311 312**Expected:** 313 314- First run creates N entries 315- Second run shows "Skipped N duplicates" 316- No duplicate files created 317 318#### Rebased commits 319 320```bash 321# Simulate rebase by checking metadata 322storm generate <range-with-rebased-commits> 323``` 324 325**Expected:** 326 327- Detects same diff, different commit hash 328- Updates metadata with new commit hash 329- Shows "Updated N rebased commits" 330 331**Edge Cases:** 332 333- No commits in range (should show "No commits found") 334- Range with only merge commits 335- Range with revert commits (should skip) 336- Commits with `[nochanges]` marker (should skip) 337- Non-existent refs (should error) 338 339### Reviewing Entries (`unreleased review`) 340 341Interactive TUI for reviewing unreleased changes. 342 343#### Basic review 344 345```bash 346storm unreleased review 347``` 348 349**Expected:** 350 351- Launches TUI with list of entries 352- Shows entry details on selection 353- Keyboard navigation works (j/k or arrows) 354- Can mark entries with actions: 355 - Press `x` to mark for deletion 356 - Press `e` to mark for editing 357 - Press `space` to keep (undo marks) 358- Action indicators shown: [✓] keep, [✗] delete, [✎] edit 359- Footer shows action counts 360- Exit with q or ESC to cancel, Enter to confirm 361 362#### Deleting entries 363 364```bash 365storm unreleased review 366# Press 'x' on unwanted entries, then Enter to confirm 367``` 368 369**Expected:** 370 371- Entries marked with [✗] are deleted from `.changes/` 372- Shows "Deleted: `<filename>`" for each removed entry 373- Final count: "Review completed: N deleted, M edited" 374- Files are permanently removed 375 376#### Editing entries 377 378```bash 379storm unreleased review 380# Press 'e' on an entry, then Enter to confirm 381``` 382 383**Expected:** 384 385- Launches inline editor TUI for each marked entry 386- Editor shows: 387 - Type (cycle with Ctrl+T through: added, changed, fixed, removed, security) 388 - Scope (text input field) 389 - Summary (text input field) 390 - Breaking change status 391- Navigate fields with Tab/Shift+Tab 392- Save with Enter or Ctrl+S 393- Cancel with Esc (skips editing that entry) 394- Shows "Updated: `<filename>`" for saved changes 395- CommitHash and DiffHash preserved 396 397#### Review workflow 398 399```bash 400# Full workflow: mark multiple actions 401storm unreleased review 402# 1. Navigate with j/k 403# 2. Mark first entry with 'x' (delete) 404# 3. Mark second entry with 'e' (edit) 405# 4. Mark third entry with 'x' (delete) 406# 5. Press Enter to confirm 407``` 408 409**Expected:** 410 411- All delete actions processed first 412- Then edit TUI launched for each edit action 413- Can cancel individual edits with Esc 414- Final summary shows both delete and edit counts 415- If no actions marked, shows "No changes requested" 416 417**Edge Cases:** 418 419- Empty changes directory (should show message, not crash) 420- Corrupted entry file (should handle gracefully) 421- Non-TTY environment (detects and errors with alternatives) 422- CI environment (detects CI system name in error message) 423- Cancel review (Esc/q) - no changes applied 424- Delete file that no longer exists (should error gracefully) 425- Edit with empty fields (fields preserve original if empty) 426 427### CI Validation (`check`) 428 429Validate that commits have changelog entries. 430 431#### All commits documented 432 433```bash 434# After running generate for a range 435storm check HEAD~5 HEAD 436``` 437 438**Expected:** 439 440- Shows "✓ All commits have changelog entries" 441- Exit code 0 442 443#### Missing entries 444 445```bash 446# Create new commits without entries 447git commit --allow-empty -m "feat: undocumented feature" 448storm check HEAD~1 HEAD 449``` 450 451**Expected:** 452 453- Shows "✗ N commits missing changelog entries" 454- Lists missing commit SHAs and subjects 455- Suggests commands to fix 456- Exit code 1 457 458#### Skip markers 459 460```bash 461git commit --allow-empty -m "chore: update deps [nochanges]" 462storm check HEAD~1 HEAD 463``` 464 465**Expected:** 466 467- Skips commit with marker 468- Shows "Skipped N commits with [nochanges] marker" 469- Exit code 0 470 471#### Since tag 472 473```bash 474storm check --since v0.1.0 475``` 476 477**Expected:** 478 479- Checks all commits since tag 480- Reports missing entries 481 482**Edge Cases:** 483 484- Empty commit range (should succeed with 0 checks) 485- Range with all skipped commits 486- Invalid tag/ref (should error) 487 488### Release Generation (`release`) 489 490Promote unreleased changes to CHANGELOG. 491 492#### Basic release 493 494```bash 495storm release --version 1.2.0 496``` 497 498**Expected:** 499 500- Creates/updates CHANGELOG.md 501- Adds version header with date 502- Groups entries by type (Added, Changed, Fixed, etc.) 503- Maintains Keep a Changelog format 504- Preserves existing changelog content 505 506#### Dry run 507 508```bash 509storm release --version 1.2.0 --dry-run 510``` 511 512**Expected:** 513 514- Shows preview of changes 515- No files modified 516- Styled output shows what would be written 517 518#### Clear changes 519 520```bash 521storm release --version 1.2.0 --clear-changes 522``` 523 524**Expected:** 525 526- Moves entries from `.changes/` to CHANGELOG 527- Deletes `.changes/*.md` files after release 528- Keeps `.changes/data/` metadata 529 530#### Git tagging 531 532```bash 533storm release --version 1.2.0 --tag 534``` 535 536**Expected:** 537 538- Creates annotated Git tag `v1.2.0` 539- Includes release notes in tag message 540- Validates tag doesn't exist 541 542**Edge Cases:** 543 544- No unreleased entries (should warn) 545- Existing version in CHANGELOG (should append) 546- Malformed CHANGELOG.md (should handle) 547- Tag already exists (should error) 548- Custom date format with `--date` 549 550### Diff Viewing (`diff`) 551 552Display inline diffs between refs. 553 554#### Basic diff 555 556```bash 557storm diff HEAD~1 HEAD 558``` 559 560**Expected:** 561 562- TTY: Launches interactive TUI with navigation 563- Non-TTY: Outputs plain text diff to stdout 564- Shows diff with syntax highlighting (TTY only) 565- Iceberg theme colors (TTY only) 566- Context lines displayed 567- File headers shown 568 569#### File filtering 570 571```bash 572storm diff HEAD~1 HEAD -- "*.go" 573``` 574 575**Expected:** 576 577- Shows only Go file changes 578- Respects glob patterns 579 580**Edge Cases:** 581 582- No changes between refs 583- Binary files (should indicate) 584- Large diffs (should handle gracefully) 585- Non-TTY environment (automatic plain text output) 586- Piped output (plain text format) 587- Redirected to file (plain text format)