- Designed trunk-based development workflow with branch protection - Added workflow validation job to prevent main branch breaks - Integrated act (GitHub Actions runner) for local Gitea workflow testing - Created unified CI/CD script interface (scripts/cicd.sh) - Added YAML lint configuration with practical limits (400 chars) - Organized all CI/CD scripts under scripts/cicd/ directory - Confirmed Gitea/GitHub Actions compatibility via local testing - Updated ADR 0017 with implementation details and test results - Enhanced documentation with local development workflow See ADR-0017 for complete trunk-based development workflow documentation. See ADR-0016 for CI/CD pipeline design.
11 KiB
14. Version Management and Release Lifecycle
Date: 2026-04-05 Status: ✅ Proposed Authors: Arcodange Team Decision Date: 2026-04-05 Implementation Status: Partial (version package created, need to implement full lifecycle)
Context
As DanceLessonsCoach matures, we need a robust version management and release lifecycle system to:
- Track versions consistently across code, documentation, and deployments
- Automate version bumping with clear semantic versioning rules
- Manage releases through git tags and changelog integration
- Provide runtime version info for debugging and support
- Support CI/CD pipelines with automated version management
Decision Drivers
- Consistency: Single source of truth for version information
- Automation: Reduce manual errors in version management
- Traceability: Link versions to git commits and builds
- Semantic Versioning: Follow industry standards (SemVer 2.0.0)
- Runtime Visibility: Expose version info in running applications
- Release Management: Support proper release tagging and changelog generation
- CI/CD Integration: Work seamlessly with automated build pipelines
Decision
We will implement a comprehensive version management system with the following components:
1. Version Package (pkg/version)
Purpose: Centralized version information with runtime access
package version
var (
Version = "1.0.0" // Semantic version
Commit = "" // Git commit hash
Date = "" // Build date
GoVersion = runtime.Version()
)
func Info() string
func Short() string
func Full() string
Implementation Status: ✅ Completed
2. Build-Time Version Injection
Approach: Use Go ldflags to inject version information during build
Timezone Convention: All timestamps use UTC for consistency
# Build command with version injection
go build \
-ldflags="\
-X 'DanceLessonsCoach/pkg/version.Version=1.0.0' \
-X 'DanceLessonsCoach/pkg/version.Commit=abc123' \
-X 'DanceLessonsCoach/pkg/version.Date=2026-04-05T10:00:00Z' # UTC format
" \
./cmd/server
Rationale for UTC:
- Consistent across all build environments
- Eliminates timezone ambiguity
- Follows ISO 8601 international standard
- Sortable and comparable
- CI/CD friendly
Script: scripts/build-with-version.sh ✅ Created
3. VERSION File
Purpose: Source of truth for version numbers
# VERSION file format
MAJOR=1
MINOR=0
PATCH=0
PRERELEASE="" # alpha.1, beta.2, rc.1, etc.
Status: ✅ Created
4. Version Bump Script
Purpose: Automated version increment following SemVer rules
# Usage: ./scripts/version-bump.sh [major|minor|patch|pre|release]
./scripts/version-bump.sh patch # 1.0.0 → 1.0.1
./scripts/version-bump.sh minor # 1.0.1 → 1.1.0
./scripts/version-bump.sh major # 1.1.0 → 2.0.0
./scripts/version-bump.sh pre # 2.0.0 → 2.0.0-alpha.1
./scripts/version-bump.sh release # 2.0.0-alpha.1 → 2.0.0
Status: 🟡 Partial (basic script created, needs refinement)
5. Command-Line Version Flag
Implementation: Add --version flag to all binaries
# Check version
dance-lessons-coach --version
# Output:
DanceLessonsCoach Version Information:
Version: 1.0.0
Commit: abc1234
Built: 2026-04-05T10:00:00+0000
Go: go1.26.1
Status: ✅ Completed
6. Git Tag Integration
Workflow:
# 1. Bump version
./scripts/version-bump.sh minor
# 2. Update CHANGELOG
# (Manual or automated process)
# 3. Commit changes
git commit -m "📖 chore: bump version to 1.1.0"
# 4. Create annotated tag
git tag -a v1.1.0 -m "Release 1.1.0"
# 5. Push with tags
git push origin main --tags
Status: 🟡 Planned
7. Release Lifecycle
Development Phase
graph LR
A[Feature Branch] --> B[PR to main]
B --> C[Auto-build with dev version]
C --> D[Deploy to dev/staging]
Release Phase
graph LR
A[Bump version] --> B[Update CHANGELOG]
B --> C[Create git tag]
C --> D[Build release binaries]
D --> E[Push to GitHub Releases]
E --> F[Deploy to production]
8. Semantic Versioning Rules
| Version Part | When to Increment | Example Changes |
|---|---|---|
| MAJOR | Breaking changes, major features | Database schema changes, API breaking changes |
| MINOR | Backwards-compatible features | New API endpoints, new functionality |
| PATCH | Backwards-compatible fixes | Bug fixes, performance improvements |
| PRERELEASE | Pre-release versions | alpha.1, beta.2, rc.1 |
9. Version Information Flow
graph TD
A[VERSION file] -->|source| B[Build Script]
B -->|ldflags| C[Compiled Binary]
C -->|runtime| D[Version Command]
C -->|runtime| E[API Response]
C -->|runtime| F[Logs/Metrics]
Implementation Plan
Phase 1: Core Version Management ✅ (Completed)
- Create
pkg/versionpackage - Add version variables with ldflags support
- Create VERSION file
- Add
--versionflag to server - Create basic build script
Phase 2: Version Bumping Automation 🟡 (In Progress)
- Complete version-bump.sh script
- Add pre-release version support
- Add validation and safety checks
- Create version validation script
Phase 3: Release Lifecycle 🟡 (Planned)
- Create release preparation script
- Automate CHANGELOG updates
- Add git tag creation script
- Create GitHub release script
- Add release notes generation
Phase 4: CI/CD Integration 🟡 (Planned)
- Add version info to CI builds
- Automate version bumping in CI
- Add version validation to PR checks
- Create release pipeline
- Add version to Docker images
Rationale
Why This Approach?
- Standard Compliance: Follows Semantic Versioning 2.0.0
- Go Idiomatic: Uses Go's ldflags for build-time injection
- Single Source of Truth: VERSION file as canonical source
- Runtime Visibility: Version info available in running apps
- Automation Friendly: Scripts for CI/CD integration
- Traceability: Links builds to git commits
- Extensible: Can add more metadata as needed
Alternatives Considered
Option 1: Hardcoded Version in main.go
- ❌ Rejected: Manual updates, error-prone, no automation
- Issue: Version scattered across multiple files
Option 2: Git Tags Only
- ❌ Rejected: No runtime access, requires git in production
- Issue: Can't access version in running containers
Option 3: External Version File (JSON/YAML)
- ❌ Rejected: More complex, requires parsing
- Issue: Overkill for simple version management
Option 4: Build System Plugins
- ❌ Rejected: Too complex, vendor lock-in
- Issue: Not portable across build systems
Pros and Cons of Chosen Approach
✅ Advantages
- Simple: Easy to understand and maintain
- Portable: Works with any build system
- Runtime Access: Version available in running apps
- Automatable: Scripts for CI/CD integration
- Extensible: Can add more metadata easily
- Standard: Follows SemVer and Go conventions
❌ Disadvantages
- Manual Bumping: Still requires manual version bumps
- Script Maintenance: Need to maintain bash scripts
- Learning Curve: Team needs to learn the workflow
- Error Potential: Manual processes can have errors
Validation
Does this meet our requirements?
- ✅ Consistency: Single VERSION file as source of truth
- ✅ Automation: Scripts for version bumping and building
- ✅ Traceability: Git commit linked to builds
- ✅ Semantic Versioning: Follows SemVer 2.0.0 standards
- ✅ Runtime Visibility: Version available via
--versionflag - ✅ CI/CD Integration: Scripts designed for pipeline use
- ✅ Extensibility: Can add more metadata as needed
What's still needed?
- ❌ Full automation: Complete CI/CD pipeline integration
- ❌ Release automation: Git tag and release creation scripts
- ❌ Changelog automation: Automated changelog updates
- ❌ Validation: Comprehensive version validation
Future Enhancements
Short-Term (Next 3 Months)
- Complete version-bump.sh with all features
- Add release preparation script
- Automate CHANGELOG updates
- Add git tag integration
- Create validation scripts
Medium-Term (3-6 Months)
- CI/CD pipeline integration
- Automated release notes
- Docker image versioning
- Version API endpoint
- Metrics and monitoring
Long-Term (6-12 Months)
- Automated version bumping based on commit messages
- Monorepo version management
- Dependency version tracking
- Security vulnerability tracking
- Deprecation policies
Migration Plan
From Current State
- Replace hardcoded version in main.go with VERSION file
- Update build scripts to use new version system
- Add version command to all binaries
- Document workflow for team
- Train team on new version management
For Existing Deployments
- Gradual rollout: Update version info on next deploy
- Backward compatibility: Keep old version formats temporarily
- Monitoring: Track version adoption
- Documentation: Update all docs with new version info
Success Metrics
- 100% of builds include proper version information
- 0 manual version errors in releases
- All team members can bump versions correctly
- CI/CD pipeline handles versioning automatically
- Release process is documented and followed
- Version visibility in production environments
References
Appendix: Version Management Commands
Check Current Version
# From VERSION file
source VERSION && echo "$MAJOR.$MINOR.$PATCH${PRERELEASE:+-$PRERELEASE}"
# From built binary
./bin/server --version
Bump Version
# Patch version (bug fixes)
./scripts/version-bump.sh patch
# Minor version (new features)
./scripts/version-bump.sh minor
# Major version (breaking changes)
./scripts/version-bump.sh major
# Pre-release version
./scripts/version-bump.sh pre
# Release from pre-release
./scripts/version-bump.sh release
Build with Version
# Development build
./scripts/build-with-version.sh bin/server-dev
# Release build
go build -o bin/server \
-ldflags="\
-X 'DanceLessonsCoach/pkg/version.Version=1.0.0' \
-X 'DanceLessonsCoach/pkg/version.Commit=$(git rev-parse --short HEAD)' \
-X 'DanceLessonsCoach/pkg/version.Date=$(date +%Y-%m-%dT%H:%M:%S%z)' \
" \
./cmd/server
Create Release
# 1. Bump version
./scripts/version-bump.sh minor
# 2. Update CHANGELOG
# Edit AGENT_CHANGELOG.md
# 3. Commit version bump
git commit -m "📖 chore: bump version to 1.1.0"
# 4. Create annotated tag
git tag -a v1.1.0 -m "Release 1.1.0"
# 5. Push with tags
git push origin main --tags
Status: Proposed
Next Review: 2026-04-12
Implementation Owner: Arcodange Team
Approvers Needed: @gabrielradureau