Release Automation Modernization History¶
Context: This document preserves the history of a three-phase refactoring effort (NovβDec 2025) that replaced three overlapping, 1,100-line-plus monolithic release scripts with a modular library architecture and a single canonical
scripts/bin/releasecommand. For the current system, see docs/systems/release-automation.md.
Background: Why the Refactoring Was Needed¶
Three scripts handled releases with heavily overlapping responsibilities:
| Script | Size | Responsibility |
|---|---|---|
gem-publish.sh |
700+ lines | Everything: version bump, changelog, build, publish, GitHub release |
release.sh |
290+ lines | Duplicate of most of the above |
build.sh |
180+ lines | Subset of both |
Problems: Contributors didn't know which script to use. Version validation, git operations, gem building, and GitHub release creation were each implemented 2β3 times. Error handling patterns were inconsistent. The 700-line gem-publish.sh embedded 200 lines of changelog logic inline.
Solution: Replace the three scripts with a modular library approach: shared libraries in scripts/lib/ sourced by a single canonical scripts/bin/release command.
Phase 1 β Library Extraction (November 25, 2025)¶
Outcome: Extracted 1,100+ lines of monolithic code into 6 focused libraries (~995 lines total, well-organized).
scripts/lib/
βββ common.sh (165 lines) β logging, error handling, dry-run wrapper, confirmation prompts
βββ validation.sh (120 lines) β git repo, clean directory, dependencies (git/ruby/gem/bundle/jq)
βββ version.sh (155 lines) β read/calculate/validate/write semantic versions
βββ git.sh (165 lines) β tag detection, commit history, commit/tag/push operations
βββ changelog.sh (230 lines) β conventional commit parsing, categorization, CHANGELOG.md writes
βββ gem.sh (160 lines) β gem build, RubyGems publish, GitHub release creation
Test suite created in parallel: 6 test files under scripts/test/lib/, covering 60+ assertions across all libraries.
Phase 2 β Simplified Commands & Deprecation Wrappers (January 27, 2025)¶
Outcome: Two new canonical commands; three old scripts converted to deprecation wrappers.
scripts/release (200 lines) β main release orchestrator implementing the 10-step workflow:
./scripts/release patch # Full patch release
./scripts/release patch --dry-run # Preview without changes
./scripts/release patch --skip-publish --no-github-release # Build and test only
--dry-run, --skip-tests, --skip-publish, --no-github-release, --non-interactive.
scripts/build (80 lines) β focused gem builder (replacement for build.sh).
Deprecation wrappers: gem-publish.sh, release.sh, and build.sh were converted to stubs that display a 3-second warning and redirect to the new commands, passing all arguments through. Original scripts preserved as *.legacy files.
Phase 3 β Documentation & Testing (November 25, 2025)¶
Outcome: Comprehensive documentation updates and validation confirming the new system works end-to-end.
Documentation updated:
- CONTRIBUTING.md β added Bash 4.0+ requirement, replaced old make release-* commands with scripts/release, documented all flags and the 10-step workflow
- README.md β added System Requirements and Release Management sections
- TROUBLESHOOTING.md (created, 700+ lines) β 7 sections covering Bash version issues, Git, RubyGems, changelog, Docker, test suite, performance; includes diagnostic commands, timing benchmarks, and a bug report template
Validation: All commands tested in --dry-run mode. Build, version bump, changelog generation, git tagging, and gem publication each confirmed functional. The complete 10-step release workflow was traced end-to-end.
Current canonical location: scripts/bin/release (moved to bin/ subdir in a subsequent cleanup). See docs/systems/release-automation.md for the current reference.