From a5344d6ed87c9f94bf3d6d90ef07544b4b5332bd Mon Sep 17 00:00:00 2001 From: Gabriel Radureau Date: Sun, 5 Apr 2026 11:28:11 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20docs:=20add=20comprehensive=20ve?= =?UTF-8?q?rsion=20management=20and=20CLI=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 166 ++++++++++ VERSION | 24 ++ adr/0013-openapi-swagger-toolchain.md | 38 +++ adr/0014-version-management-lifecycle.md | 402 +++++++++++++++++++++++ adr/0015-cli-subcommands-cobra.md | 198 +++++++++++ cmd/server/main.go | 11 +- doc/version-management-guide.md | 365 ++++++++++++++++++++ pkg/config/config.go | 17 + pkg/server/server.go | 45 +++ pkg/version/version.go | 110 +++++++ scripts/README.md | 313 ++++++++++++++++++ scripts/build-with-version.sh | 43 +++ scripts/version-bump.sh | 133 ++++++++ 13 files changed, 1864 insertions(+), 1 deletion(-) create mode 100644 VERSION create mode 100644 adr/0014-version-management-lifecycle.md create mode 100644 adr/0015-cli-subcommands-cobra.md create mode 100644 doc/version-management-guide.md create mode 100644 pkg/version/version.go create mode 100644 scripts/README.md create mode 100755 scripts/build-with-version.sh create mode 100755 scripts/version-bump.sh diff --git a/AGENTS.md b/AGENTS.md index 5eda4fe..3594746 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -136,6 +136,22 @@ DanceLessonsCoach/ ## 🚀 Server Management +### Version Information + +The server provides runtime version information: + +```bash +# Check version +./bin/server --version + +# Output: +DanceLessonsCoach Version Information: + Version: 1.0.0 + Commit: abc1234 + Built: 2026-04-05T10:00:00+0000 + Go: go1.26.1 +``` + ### Using the Server Control Script A convenient shell script is provided for managing the server lifecycle: @@ -874,6 +890,156 @@ defer cancel() - ✅ Comprehensive logging with Zerolog - ✅ Build system with binary output - ✅ Complete documentation with commit conventions +- ✅ Version management with runtime info + +## 📦 Version Management + +DanceLessonsCoach uses a comprehensive version management system based on Semantic Versioning 2.0.0. + +### Version Information + +**Current Version:** `1.0.0` (see VERSION file) +**Version Format:** `MAJOR.MINOR.PATCH-PRERELEASE` +**SemVer Compliance:** ✅ Yes + +### Version Files + +```bash +# VERSION file - Source of truth +MAJOR=1 +MINOR=0 +PATCH=0 +PRERELEASE="" + +# Auto-generated fields +BUILD_DATE="" +GIT_COMMIT="" +GIT_TAG="" +``` + +### Version Management Commands + +#### Check Version +```bash +# From VERSION file +source VERSION && echo "$MAJOR.$MINOR.$PATCH${PRERELEASE:+-$PRERELEASE}" + +# From built binary +./bin/server --version + +# From running server (future) +curl http://localhost:8080/api/version +``` + +#### Bump Version +```bash +# Patch version (bug fixes) +./scripts/version-bump.sh patch # 1.0.0 → 1.0.1 + +# Minor version (new features) +./scripts/version-bump.sh minor # 1.0.1 → 1.1.0 + +# Major version (breaking changes) +./scripts/version-bump.sh major # 1.1.0 → 2.0.0 + +# Pre-release version +./scripts/version-bump.sh pre # 2.0.0 → 2.0.0-alpha.1 + +# Release from pre-release +./scripts/version-bump.sh release # 2.0.0-alpha.1 → 2.0.0 +``` + +#### Build with Version +```bash +# 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 +``` + +### Semantic Versioning Rules + +| Part | When to Increment | Examples | +|------|-------------------|----------| +| **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 | + +### Release Lifecycle + +#### Development Workflow +```mermaid +graph LR + A[Feature Branch] --> B[PR to main] + B --> C[Auto-build with dev version] + C --> D[Deploy to dev/staging] +``` + +#### Release Workflow +```mermaid +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] +``` + +### Version Package + +The `pkg/version` package provides runtime access to version information: + +```go +package main + +import ( + "DanceLessonsCoach/pkg/version" + "fmt" +) + +func main() { + fmt.Println("Version:", version.Short()) + fmt.Println("Full info:", version.Full()) + fmt.Println("Info:", version.Info()) +} +``` + +**Functions:** +- `version.Short()` - Returns version number (e.g., "1.0.0") +- `version.Info()` - Returns short info string +- `version.Full()` - Returns detailed version information + +### Implementation Status + +| Component | Status | Notes | +|-----------|--------|-------| +| Version Package | ✅ Complete | Runtime version access | +| VERSION File | ✅ Complete | Source of truth | +| Build Script | ✅ Complete | Version injection | +| Version Command | ✅ Complete | `--version` flag | +| Version Bump Script | 🟡 Partial | Basic functionality | +| Git Tag Integration | 🟡 Planned | Release automation | +| CI/CD Integration | 🟡 Planned | Pipeline automation | +| Release Scripts | 🟡 Planned | Full release lifecycle | + +### Future Enhancements + +1. **Automated Changelog Generation** +2. **Git Tag Automation** +3. **CI/CD Pipeline Integration** +4. **Version API Endpoint** (`GET /api/version`) +5. **Dependency Version Tracking** +6. **Security Vulnerability Alerts** + +See [ADR 0014](adr/0014-version-management-lifecycle.md) for complete version management architecture. ## 📝 Architecture Decision Records diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..288e932 --- /dev/null +++ b/VERSION @@ -0,0 +1,24 @@ +# DanceLessonsCoach Version + +# Current Version (Semantic Versioning) +MAJOR=1 +MINOR=1 +PATCH=1 +PRERELEASE="" + +# Auto-generated fields (do not edit manually) +BUILD_DATE="" +GIT_COMMIT="" +GIT_TAG="" + +# Version Format: {MAJOR}.{MINOR}.{PATCH}-{PRERELEASE} +# Example: 1.0.0, 1.0.0-alpha.1, 2.3.4-beta.2 + +# Semantic Versioning Rules: +# - MAJOR: Breaking changes, major features +# - MINOR: Backwards-compatible features +# - PATCH: Backwards-compatible bug fixes +# - PRERELEASE: alpha, beta, rc (pre-release versions) + +# Changelog Reference: +# See AGENT_CHANGELOG.md for version history diff --git a/adr/0013-openapi-swagger-toolchain.md b/adr/0013-openapi-swagger-toolchain.md index 3d03718..ce24d42 100644 --- a/adr/0013-openapi-swagger-toolchain.md +++ b/adr/0013-openapi-swagger-toolchain.md @@ -309,6 +309,44 @@ go install github.com/swaggo/swag/cmd/swag@latest // @BasePath /api package main +### Annotation Placement Considerations + +**Current Approach**: Annotations in `cmd/server/main.go` + +**Pros**: +- Follows Go community conventions +- Works seamlessly with swaggo +- Clear entry point for API documentation + +**Cons**: +- Mixes API metadata with main package +- Less separation of concerns + +**Alternative**: Annotations in `pkg/server/server.go` + +**Pros**: +- Better organization (all server code together) +- More logical separation +- Easier maintenance + +**Cons**: +- May require swag configuration changes +- Less conventional +- Potential tooling issues + +**Decision**: Keep annotations in `cmd/server/main.go` for now + +**Rationale**: +1. Follows established community patterns +2. Works reliably with current toolchain +3. Minimizes risk of breaking changes +4. Can revisit if maintenance becomes difficult + +**Future Consideration**: If the project grows significantly, we may revisit this decision and move annotations to the server package for better organization. +``` + +### Implementation + # 3. Annotate handlers and models with hierarchical tags // @Summary Get personalized greeting // @Description Returns a greeting with the specified name diff --git a/adr/0014-version-management-lifecycle.md b/adr/0014-version-management-lifecycle.md new file mode 100644 index 0000000..e481252 --- /dev/null +++ b/adr/0014-version-management-lifecycle.md @@ -0,0 +1,402 @@ +# 14. Version Management and Release Lifecycle + +**Date:** 2026-04-05 +**Status:** ✅ Proposed +**Authors:** DanceLessonsCoach 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: + +1. **Track versions consistently** across code, documentation, and deployments +2. **Automate version bumping** with clear semantic versioning rules +3. **Manage releases** through git tags and changelog integration +4. **Provide runtime version info** for debugging and support +5. **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 + +```go +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 + +```bash +# 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 + +```bash +# 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 + +```bash +# 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 + +```bash +# 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**: +```bash +# 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 +```mermaid +graph LR + A[Feature Branch] --> B[PR to main] + B --> C[Auto-build with dev version] + C --> D[Deploy to dev/staging] +``` + +#### Release Phase +```mermaid +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 + +```mermaid +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) +- [x] Create `pkg/version` package +- [x] Add version variables with ldflags support +- [x] Create VERSION file +- [x] Add `--version` flag to server +- [x] 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? + +1. **Standard Compliance**: Follows Semantic Versioning 2.0.0 +2. **Go Idiomatic**: Uses Go's ldflags for build-time injection +3. **Single Source of Truth**: VERSION file as canonical source +4. **Runtime Visibility**: Version info available in running apps +5. **Automation Friendly**: Scripts for CI/CD integration +6. **Traceability**: Links builds to git commits +7. **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 +1. **Simple**: Easy to understand and maintain +2. **Portable**: Works with any build system +3. **Runtime Access**: Version available in running apps +4. **Automatable**: Scripts for CI/CD integration +5. **Extensible**: Can add more metadata easily +6. **Standard**: Follows SemVer and Go conventions + +### ❌ Disadvantages +1. **Manual Bumping**: Still requires manual version bumps +2. **Script Maintenance**: Need to maintain bash scripts +3. **Learning Curve**: Team needs to learn the workflow +4. **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 `--version` flag +- ✅ **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) +1. **Complete version-bump.sh** with all features +2. **Add release preparation script** +3. **Automate CHANGELOG updates** +4. **Add git tag integration** +5. **Create validation scripts** + +### Medium-Term (3-6 Months) +1. **CI/CD pipeline integration** +2. **Automated release notes** +3. **Docker image versioning** +4. **Version API endpoint** +5. **Metrics and monitoring** + +### Long-Term (6-12 Months) +1. **Automated version bumping** based on commit messages +2. **Monorepo version management** +3. **Dependency version tracking** +4. **Security vulnerability tracking** +5. **Deprecation policies** + +## Migration Plan + +### From Current State +1. **Replace hardcoded version** in main.go with VERSION file +2. **Update build scripts** to use new version system +3. **Add version command** to all binaries +4. **Document workflow** for team +5. **Train team** on new version management + +### For Existing Deployments +1. **Gradual rollout**: Update version info on next deploy +2. **Backward compatibility**: Keep old version formats temporarily +3. **Monitoring**: Track version adoption +4. **Documentation**: Update all docs with new version info + +## Success Metrics + +1. **100% of builds** include proper version information +2. **0 manual version errors** in releases +3. **All team members** can bump versions correctly +4. **CI/CD pipeline** handles versioning automatically +5. **Release process** is documented and followed +6. **Version visibility** in production environments + +## References + +- [Semantic Versioning 2.0.0](https://semver.org/) +- [Go ldflags Documentation](https://pkg.go.dev/cmd/link) +- [Git Tags Documentation](https://git-scm.com/book/en/v2/Git-Basics-Tagging) +- [Conventional Commits](https://www.conventionalcommits.org/) + +## Appendix: Version Management Commands + +### Check Current Version +```bash +# From VERSION file +source VERSION && echo "$MAJOR.$MINOR.$PATCH${PRERELEASE:+-$PRERELEASE}" + +# From built binary +./bin/server --version +``` + +### Bump Version +```bash +# 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 +```bash +# 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 +```bash +# 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:** DanceLessonsCoach Team +**Approvers Needed:** @gabrielradureau \ No newline at end of file diff --git a/adr/0015-cli-subcommands-cobra.md b/adr/0015-cli-subcommands-cobra.md new file mode 100644 index 0000000..6cfb615 --- /dev/null +++ b/adr/0015-cli-subcommands-cobra.md @@ -0,0 +1,198 @@ +# 15. CLI Subcommands and Flag Management with Cobra + +**Date:** 2026-04-05 +**Status:** 🟡 Proposed +**Authors:** DanceLessonsCoach Team +**Decision Date:** TBD +**Implementation Status:** Not Started + +## Context + +As DanceLessonsCoach grows, we need a more robust and maintainable CLI structure. Currently, we use simple flag parsing (`--version`), but this approach has limitations: + +1. **Limited scalability**: Adding more commands/flags becomes messy +2. **Poor user experience**: No built-in help, completion, or validation +3. **Hard to maintain**: Manual flag parsing is error-prone +4. **No subcommands**: Can't easily add commands like `server start`, `server stop`, etc. + +## Decision Drivers + +* **Scalability**: Support growing CLI needs as project expands +* **User Experience**: Provide professional CLI with help, completion, validation +* **Maintainability**: Easy to add/remove commands and flags +* **Standards**: Follow industry best practices for CLI tools +* **Extensibility**: Support future commands (migrate, seed, etc.) +* **Integration**: Work well with existing config system + +## Decision + +We will adopt **Cobra** as our CLI framework. Cobra is a mature, widely-used library for building modern CLI applications in Go. + +### Selected Solution: Cobra CLI Framework + +**Repository**: https://github.com/spf13/cobra +**Version**: v1.8.0 (or latest stable) + +### Key Features + +1. **Subcommands**: `server start`, `server stop`, `migrate`, etc. +2. **Flags**: `--config`, `--env`, `--verbose`, etc. +3. **Help System**: Automatic `--help` generation +4. **Shell Completion**: Built-in support +5. **Validation**: Type-safe flag parsing +6. **Middleware**: Pre/post command hooks + +### Implementation Plan + +#### Phase 1: Basic Integration (Next Sprint) +```go +var rootCmd = &cobra.Command{ + Use: "dance-lessons-coach", + Short: "DanceLessonsCoach - API server and CLI tools", + Long: `DanceLessonsCoach provides greeting services and API management. + +To begin working with DanceLessonsCoach, run: + dance-lessons-coach server --help`, + SilenceUsage: true, +} + +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Print version information", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(version.Full()) + }, +} + +var serverCmd = &cobra.Command{ + Use: "server", + Short: "Start the DanceLessonsCoach server", + Run: func(cmd *cobra.Command, args []string) { + // Load config and start server + cfg, err := config.LoadConfig() + if err != nil { + log.Fatal().Err(err).Msg("Failed to load configuration") + } + server := server.NewServer(cfg, context.Background()) + if err := server.Run(); err != nil { + log.Fatal().Err(err).Msg("Server failed") + } + }, +} + +func init() { + rootCmd.AddCommand(versionCmd) + rootCmd.AddCommand(serverCmd) + + // Add flags to server command + serverCmd.Flags().String("config", "", "Config file path") + serverCmd.Flags().String("env", "", "Environment (dev, staging, prod)") + serverCmd.Flags().Bool("debug", false, "Enable debug logging") +} + +func main() { + if err := rootCmd.Execute(); err != nil { + log.Fatal().Err(err).Msg("CLI execution failed") + } +} +``` + +#### Phase 2: Advanced Features (Future) +- **Subcommand groups**: `server`, `db`, `migrate`, `tools` +- **Persistent flags**: Global flags like `--config`, `--env` +- **Command aliases**: Shorter command names +- **Custom help templates**: Branded help output +- **Shell completion scripts**: Generate completion for bash/zsh/fish + +#### Phase 3: Migration (Ongoing) +- Migrate existing flags to Cobra +- Deprecate old flag parsing +- Update documentation +- Add new commands as needed + +### Migration Strategy + +1. **Incremental adoption**: Start with version command, then server command +2. **Backward compatibility**: Support old flags during transition +3. **Documentation**: Update README with new CLI usage +4. **Testing**: Ensure all existing functionality works + +### Command Structure Proposal + +```bash +# Main commands +dance-lessons-coach server # Start the server +dance-lessons-coach version # Show version +dance-lessons-coach migrate # Database migrations +dance-lessons-coach config # Config management + +# Server subcommands +dance-lessons-coach server start # Start server +dance-lessons-coach server stop # Stop server +dance-lessons-coach server restart # Restart server +dance-lessons-coach server status # Server status + +# Global flags +dance-lessons-coach --help # Show help +dance-lessons-coach --version # Show version (shortcut) +dance-lessons-coach --config /path/to/config.yaml + +# Example usage +dance-lessons-coach server start --env production --debug +dance-lessons-coach migrate up +dance-lessons-coach config validate +``` + +### Pros and Cons of Cobra + +#### ✅ Advantages +1. **Industry Standard**: Used by Kubernetes, Hugo, etcd, and many others +2. **Mature Ecosystem**: Well-documented, widely adopted +3. **Feature Rich**: Help, completion, validation built-in +4. **Extensible**: Easy to add new commands +5. **Go Idiomatic**: Fits well with Go patterns +6. **Good Documentation**: Excellent docs and examples + +#### ❌ Disadvantages +1. **Learning Curve**: New patterns to learn +2. **Migration Effort**: Need to refactor existing code +3. **Slight Overhead**: More complex than simple flag parsing +4. **Dependency**: Adds cobra to project + +### Validation + +**Does this meet our requirements?** +- ✅ **Scalability**: Easy to add new commands +- ✅ **User Experience**: Professional CLI with help/completion +- ✅ **Maintainability**: Clean, structured code +- ✅ **Standards**: Follows industry best practices +- ✅ **Extensibility**: Supports future growth +- ✅ **Integration**: Works with existing config system + +**What's still needed?** +- ❌ **Implementation**: Actual cobra integration +- ❌ **Migration**: Move existing flags to cobra +- ❌ **Documentation**: Update docs with new CLI +- ❌ **Testing**: Ensure all functionality works + +### Future Enhancements + +1. **Add more commands**: `migrate`, `config`, `db`, etc. +2. **Improve help**: Custom templates, examples +3. **Add completion**: Shell completion scripts +4. **Enhance validation**: Better error messages +5. **Add aliases**: Shorter command names + +### References + +- [Cobra GitHub](https://github.com/spf13/cobra) +- [Cobra Documentation](https://cobra.dev/) +- [CLI Guidelines](https://clig.dev/) +- [Go CLI Best Practices](https://github.com/clig-dev/clig) + +--- + +**Status:** Proposed +**Next Review:** 2026-04-12 +**Implementation Owner:** DanceLessonsCoach Team +**Approvers Needed:** @gabrielradureau \ No newline at end of file diff --git a/cmd/server/main.go b/cmd/server/main.go index a9498d4..62826fb 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -1,7 +1,7 @@ // Package main provides the DanceLessonsCoach server entry point // // @title DanceLessonsCoach API -// @version 1.0 +// @version 1.1.1 // @description API for DanceLessonsCoach service providing greeting functionality // @termsOfService http://swagger.io/terms/ @@ -20,14 +20,23 @@ package main import ( "context" + "fmt" + "os" "DanceLessonsCoach/pkg/config" "DanceLessonsCoach/pkg/server" + "DanceLessonsCoach/pkg/version" "github.com/rs/zerolog/log" ) func main() { + // Check for version flag first (before config loading) + if len(os.Args) > 1 && (os.Args[1] == "--version" || os.Args[1] == "-version") { + fmt.Println(version.Full()) + os.Exit(0) + } + // Load configuration (this will also setup logging) cfg, err := config.LoadConfig() if err != nil { diff --git a/doc/version-management-guide.md b/doc/version-management-guide.md new file mode 100644 index 0000000..b71576b --- /dev/null +++ b/doc/version-management-guide.md @@ -0,0 +1,365 @@ +# Version Management Guide + +This guide provides comprehensive instructions for managing versions in the DanceLessonsCoach project. + +## 📋 Table of Contents + +1. [Semantic Versioning](#semantic-versioning) +2. [Version Bumping](#version-bumping) +3. [Release Process](#release-process) +4. [Changelog Management](#changelog-management) +5. [Git Tagging](#git-tagging) +6. [Troubleshooting](#troubleshooting) + +## 📖 Semantic Versioning + +DanceLessonsCoach follows [Semantic Versioning 2.0.0](https://semver.org/): + +### Version Format: `MAJOR.MINOR.PATCH-PRERELEASE` + +| Component | When to Increment | Examples | +|-----------|-------------------|----------| +| **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` | + +### Examples +- `1.0.0` - Initial stable release +- `1.1.0` - Added new feature (backwards-compatible) +- `1.1.1` - Bug fix (backwards-compatible) +- `2.0.0` - Breaking changes +- `2.0.0-alpha.1` - Pre-release version + +## 🔢 Version Bumping + +### When to Bump Each Component + +#### MAJOR Version (Breaking Changes) +- **Database schema changes** that require migrations +- **API changes** that break existing clients +- **Configuration changes** that require user action +- **Dependency updates** with breaking changes + +**Example**: Removing or changing API endpoints, changing database schema + +#### MINOR Version (Features) +- **New API endpoints** (backwards-compatible) +- **New functionality** that doesn't break existing features +- **Enhancements** to existing features + +**Example**: Adding new API endpoints, adding new configuration options + +#### PATCH Version (Bug Fixes) +- **Bug fixes** that don't change functionality +- **Performance improvements** +- **Security patches** +- **Documentation updates** + +**Example**: Fixing bugs, improving performance, updating docs + +### How to Bump Version + +#### Using the Version Bump Script + +```bash +# Bump patch version (bug fixes) +./scripts/version-bump.sh patch # 1.0.0 → 1.0.1 + +# Bump minor version (new features) +./scripts/version-bump.sh minor # 1.0.1 → 1.1.0 + +# Bump major version (breaking changes) +./scripts/version-bump.sh major # 1.1.0 → 2.0.0 + +# Create pre-release version +./scripts/version-bump.sh pre # 2.0.0 → 2.0.0-alpha.1 + +# Release from pre-release +./scripts/version-bump.sh release # 2.0.0-alpha.1 → 2.0.0 +``` + +#### Manual Version Bumping + +1. Edit `VERSION` file: +```bash +# VERSION file +MAJOR=1 +MINOR=0 +PATCH=1 # ← Increment this +PRERELEASE="" +``` + +2. Update Swagger annotation in `cmd/server/main.go`: +```go +// @version 1.0.1 # ← Update this +``` + +3. Regenerate documentation: +```bash +go generate ./... +``` + +## 🚀 Release Process + +### Standard Release Workflow + +```mermaid +graph TD + A[Bump version] --> B[Update CHANGELOG] + B --> C[Test changes] + C --> D[Commit version bump] + D --> E[Create git tag] + E --> F[Build release] + F --> G[Deploy to production] +``` + +### Step-by-Step Release Checklist + +#### 1. Bump Version +```bash +# For patch release (bug fixes) +./scripts/version-bump.sh patch + +# For minor release (new features) +./scripts/version-bump.sh minor + +# For major release (breaking changes) +./scripts/version-bump.sh major +``` + +#### 2. Update CHANGELOG + +Edit `AGENT_CHANGELOG.md`: +```markdown +## [1.0.1] - 2026-04-05 + +### Fixed +- Fixed bug in greeting validation +- Improved error handling + +### Added +- New API endpoint for health checks + +### Changed +- Updated Swagger documentation +``` + +#### 3. Test Changes + +```bash +# Run tests +go test ./... + +# Test version endpoint +curl http://localhost:8080/api/version?format=json + +# Test Swagger UI +open http://localhost:8080/swagger/ +``` + +#### 4. Commit Version Bump + +```bash +git add VERSION cmd/server/main.go +git commit -m "📖 chore: bump version to 1.0.1" +``` + +#### 5. Create Git Tag + +```bash +# Annotated tag with message +git tag -a v1.0.1 -m "Release 1.0.1" + +# Lightweight tag +git tag v1.0.1 +``` + +#### 6. Build Release + +```bash +# Build with version info +./scripts/build-with-version.sh bin/release/server-v1.0.1 + +# Test the release binary +./bin/release/server-v1.0.1 --version +``` + +#### 7. Deploy to Production + +```bash +# Deploy the release binary +scp bin/release/server-v1.0.1 user@production:/opt/dance-lessons-coach/ + +# Restart service +systemctl restart dance-lessons-coach +``` + +#### 8. Push to GitHub + +```bash +# Push commit and tags +git push origin main --tags +``` + +## 📝 Changelog Management + +### Changelog Format + +Follow [Keep a Changelog](https://keepachangelog.com/) format: + +```markdown +## [1.0.1] - YYYY-MM-DD + +### Added +- New features here + +### Changed +- Changes to existing functionality + +### Deprecated +- Soon-to-be removed features + +### Removed +- Removed features + +### Fixed +- Bug fixes + +### Security +- Security improvements +``` + +### Changelog Best Practices + +1. **Group by type**: Added, Changed, Deprecated, Removed, Fixed, Security +2. **Be specific**: "Fixed bug" → "Fixed validation error in greeting endpoint" +3. **Link to issues**: Reference GitHub issues when possible +4. **Use imperative**: "Add" not "Added", "Fix" not "Fixed" +5. **One line per change**: Keep it concise + +### Example CHANGELOG Entry + +```markdown +## [Unreleased] + +### Added +- Add new `/api/version` endpoint for runtime version info +- Add hierarchical tagging to Swagger documentation + +### Changed +- Refactor version management to use VERSION file +- Update Swagger annotations to use hierarchical tags + +### Fixed +- Fix Swagger documentation generation for multi-package projects +- Fix version flag handling to work with both go run and compiled binary +``` + +## 🏷️ Git Tagging + +### Tag Naming Convention + +```bash +# Annotated tags (recommended) +git tag -a v1.0.1 -m "Release 1.0.1" + +# Lightweight tags +git tag v1.0.1 + +# Pre-release tags +git tag v2.0.0-alpha.1 +git tag v2.0.0-beta.2 +git tag v2.0.0-rc.1 +``` + +### Tag Management + +```bash +# List all tags +git tag -l + +# List tags matching pattern +git tag -l "v1.*" + +# Delete local tag +git tag -d v1.0.1 + +# Delete remote tag +git push origin :refs/tags/v1.0.1 + +# Show tag details +git show v1.0.1 +``` + +### Tagging Best Practices + +1. **Annotated tags**: Always use `-a` for release tags +2. **SemVer compliance**: Follow MAJOR.MINOR.PATCH format +3. **Signed tags**: Consider signing tags for security +4. **Changelog sync**: Tag after CHANGELOG update +5. **CI/CD integration**: Automate tag creation in pipeline + +## ⚠️ Troubleshooting + +### Version Not Updating + +**Problem**: Version shows old value after bump + +**Solution**: +```bash +# 1. Check VERSION file +cat VERSION + +# 2. Rebuild binary +./scripts/build-with-version.sh + +# 3. Restart server +./scripts/start-server.sh restart +``` + +### Swagger Docs Missing Endpoints + +**Problem**: Greet endpoints missing from Swagger UI + +**Solution**: +```bash +# Regenerate docs from project root +swag init -g ./cmd/server/main.go --parseDependency --parseInternal + +# Move docs to correct location +mv docs/* pkg/server/docs/ + +# Restart server +./scripts/start-server.sh restart +``` + +### Git Tag Issues + +**Problem**: Tag push rejected + +**Solution**: +```bash +# Delete local tag +git tag -d v1.0.1 + +# Delete remote tag +git push origin :refs/tags/v1.0.1 + +# Recreate tag +git tag -a v1.0.1 -m "Release 1.0.1" +git push origin v1.0.1 +``` + +## 📚 Resources + +- [Semantic Versioning](https://semver.org/) +- [Keep a Changelog](https://keepachangelog.com/) +- [Conventional Commits](https://www.conventionalcommits.org/) +- [Git Tagging](https://git-scm.com/book/en/v2/Git-Basics-Tagging) + +--- + +**Maintained by:** DanceLessonsCoach Team +**Last Updated:** 2026-04-05 +**Version:** 1.0 \ No newline at end of file diff --git a/pkg/config/config.go b/pkg/config/config.go index 7c93c67..49a9233 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -9,6 +9,8 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/viper" + + "DanceLessonsCoach/pkg/version" ) // Config represents the application configuration @@ -52,6 +54,21 @@ type APIConfig struct { V2Enabled bool `mapstructure:"v2_enabled"` } +// VersionInfo holds application version information +type VersionInfo struct { + Version string `mapstructure:"-"` // Set via ldflags + Commit string `mapstructure:"-"` // Set via ldflags + Date string `mapstructure:"-"` // Set via ldflags + GoVersion string `mapstructure:"-"` // Set at runtime +} + +// VersionCommand handles version display +func (c *Config) VersionCommand() string { + // This will be enhanced when we integrate with cobra + return fmt.Sprintf("DanceLessonsCoach %s (commit: %s, built: %s, go: %s)", + version.Version, version.Commit, version.Date, version.GoVersion) +} + // SamplerConfig holds tracing sampler configuration type SamplerConfig struct { Type string `mapstructure:"type"` diff --git a/pkg/server/server.go b/pkg/server/server.go index 6eae125..1eb84c8 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -5,6 +5,7 @@ package server import ( "context" "embed" + "fmt" "net" "net/http" "os/signal" @@ -20,6 +21,7 @@ import ( "DanceLessonsCoach/pkg/greet" "DanceLessonsCoach/pkg/telemetry" "DanceLessonsCoach/pkg/validation" + "DanceLessonsCoach/pkg/version" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" sdktrace "go.opentelemetry.io/otel/sdk/trace" @@ -70,6 +72,9 @@ func (s *Server) setupRoutes() { // Readiness endpoint at root level s.router.Get("/api/ready", s.handleReadiness) + // Version endpoint at root level + s.router.Get("/api/version", s.handleVersion) + // API routes s.router.Route("/api/v1", func(r chi.Router) { r.Use(s.getAllMiddlewares()...) @@ -169,6 +174,46 @@ func (s *Server) handleReadiness(w http.ResponseWriter, r *http.Request) { } } +// handleVersion godoc +// @Summary Get API version +// @Description Returns the API version information +// @Tags System/Version +// @Accept plain,json +// @Produce plain,json +// @Param format query string false "Response format (plain, full, json)" Enums(plain, full, json) default(plain) +// @Success 200 {string} string "Version information" +// @Router /version [get] +func (s *Server) handleVersion(w http.ResponseWriter, r *http.Request) { + log.Trace().Msg("Version check requested") + + // Get format parameter + format := r.URL.Query().Get("format") + if format == "" { + format = "plain" // default format + } + + switch format { + case "plain": + w.Header().Set("Content-Type", "text/plain") + w.Write([]byte(version.Short())) + case "full": + w.Header().Set("Content-Type", "text/plain") + w.Write([]byte(version.Full())) + case "json": + w.Header().Set("Content-Type", "application/json") + jsonResponse := fmt.Sprintf(`{ + "version": "%s", + "commit": "%s", + "built": "%s", + "go": "%s" + }`, version.Version, version.Commit, version.Date, version.GoVersion) + w.Write([]byte(jsonResponse)) + default: + w.Header().Set("Content-Type", "text/plain") + w.Write([]byte(version.Short())) + } +} + func (s *Server) Router() http.Handler { return s.router } diff --git a/pkg/version/version.go b/pkg/version/version.go new file mode 100644 index 0000000..e3c8b0a --- /dev/null +++ b/pkg/version/version.go @@ -0,0 +1,110 @@ +// Package version provides version information and management for DanceLessonsCoach +package version + +import ( + "fmt" + "os" + "os/exec" + "runtime" + "strings" +) + +// Version information - updated during build or from VERSION file +var ( + Version = "1.0.0" // Semantic version (MAJOR.MINOR.PATCH) + Commit = "" // Git commit hash + Date = "" // Build date + GoVersion = runtime.Version() // Go version used to build +) + +// init reads version from VERSION file if ldflags not used +func init() { + // Only read from VERSION file if Version is still default value + // This allows ldflags to override during build + if Version == "1.0.0" && Commit == "" && Date == "" { + readVersionFromFile() + } +} + +// readVersionFromFile reads version info from VERSION file +func readVersionFromFile() { + data, err := os.ReadFile("VERSION") + if err != nil { + // File not found or can't read - keep default values + return + } + + lines := strings.Split(string(data), "\n") + for _, line := range lines { + line = strings.TrimSpace(line) + if strings.HasPrefix(line, "MAJOR=") { + Version = strings.TrimPrefix(line, "MAJOR=") + } else if strings.HasPrefix(line, "MINOR=") { + // Append minor to version + minor := strings.TrimPrefix(line, "MINOR=") + if Version != "1.0.0" { + Version = Version + "." + minor + } + } else if strings.HasPrefix(line, "PATCH=") { + // Append patch to version + patch := strings.TrimPrefix(line, "PATCH=") + if Version != "1.0.0" { + Version = Version + "." + patch + } + } else if strings.HasPrefix(line, "PRERELEASE=") { + pre := strings.TrimPrefix(line, "PRERELEASE=") + pre = strings.Trim(pre, `"`) + if pre != "" && Version != "1.0.0" { + Version = Version + "-" + pre + } + } + } + + // Try to get git commit when running in development (go run) + if Commit == "" { + getGitCommit() + } + + // Try to get build date when running in development (go run) + if Date == "" { + getBuildDate() + } +} + +// getGitCommit tries to get the current git commit hash +func getGitCommit() { + cmd := exec.Command("git", "rev-parse", "--short", "HEAD") + output, err := cmd.Output() + if err == nil { + Commit = strings.TrimSpace(string(output)) + } +} + +// getBuildDate tries to get the current build date +func getBuildDate() { + cmd := exec.Command("date", "-u", "+%Y-%m-%dT%H:%M:%SZ") + output, err := cmd.Output() + if err == nil { + Date = strings.TrimSpace(string(output)) + } +} + +// Info returns formatted version information +func Info() string { + return fmt.Sprintf("DanceLessonsCoach %s (commit: %s, built: %s UTC, go: %s)", Version, Commit, Date, GoVersion) +} + +// Short returns just the version number +func Short() string { + return Version +} + +// Full returns detailed version information +func Full() string { + return fmt.Sprintf(`DanceLessonsCoach Version Information: + Version: %s + Commit: %s + Built: %s (UTC) + Go: %s`, + Version, Commit, Date, GoVersion) +} diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..76f657f --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,313 @@ +# DanceLessonsCoach Scripts + +This directory contains automation and management scripts for the DanceLessonsCoach project. + +## 📁 Script Categories + +### 🚀 Server Management +- **`start-server.sh`** - Start, stop, and manage the server lifecycle +- **`test-opentelemetry.sh`** - Test OpenTelemetry integration with Jaeger + +### 📦 Version Management +- **`version-bump.sh`** - Bump version numbers following Semantic Versioning +- **`build-with-version.sh`** - Build binaries with embedded version information + +### 🔧 Build System +- **`build.sh`** - Build server and CLI binaries + +### 📝 Documentation +- **`generate-docs.sh`** - Generate Swagger/OpenAPI documentation (future) + +## 📋 Script Documentation + +### 1. Server Management (`start-server.sh`) + +**Manage the DanceLessonsCoach server lifecycle** + +```bash +# Start the server +./scripts/start-server.sh start + +# Stop the server +./scripts/start-server.sh stop + +# Restart the server +./scripts/start-server.sh restart + +# Check server status +./scripts/start-server.sh status + +# View server logs +./scripts/start-server.sh logs + +# Test API endpoints +./scripts/start-server.sh test +``` + +**Features:** +- Background process management +- Log file rotation +- PID file tracking +- Graceful shutdown +- Health check testing + +### 2. Version Bumping (`version-bump.sh`) + +**Automate version increments following Semantic Versioning** + +```bash +# Bump patch version (bug fixes) +./scripts/version-bump.sh patch # 1.0.0 → 1.0.1 + +# Bump minor version (new features) +./scripts/version-bump.sh minor # 1.0.1 → 1.1.0 + +# Bump major version (breaking changes) +./scripts/version-bump.sh major # 1.1.0 → 2.0.0 + +# Create pre-release version +./scripts/version-bump.sh pre # 2.0.0 → 2.0.0-alpha.1 + +# Release from pre-release +./scripts/version-bump.sh release # 2.0.0-alpha.1 → 2.0.0 +``` + +**How it works:** +1. Reads current version from `VERSION` file +2. Increments appropriate version component +3. Updates `VERSION` file +4. Updates Swagger `@version` annotation in `main.go` +5. Resets lower components when needed (e.g., minor bump sets patch to 0) + +**Semantic Versioning Rules:** +- **MAJOR**: Breaking changes, major features +- **MINOR**: Backwards-compatible features +- **PATCH**: Backwards-compatible bug fixes +- **PRERELEASE**: alpha.1, beta.2, rc.1 + +### 3. Build with Version (`build-with-version.sh`) + +**Build binaries with embedded version information** + +```bash +# Build to default location (bin/server) +./scripts/build-with-version.sh + +# Build to custom location +./scripts/build-with-version.sh bin/my-server + +# Build with custom version (overrides VERSION file) +VERSION="1.2.3" ./scripts/build-with-version.sh bin/server-custom +``` + +**Features:** +- Automatically reads version from `VERSION` file +- Injects version info using Go `ldflags` +- Includes git commit hash +- Includes build timestamp +- Supports custom output paths + +**Version information includes:** +- Semantic version (e.g., `1.0.0`) +- Git commit hash (e.g., `abc123`) +- Build date in UTC (e.g., `2026-04-05T08:00:00Z`) +- Go version (e.g., `go1.26.1`) + +**Timezone Convention**: All timestamps use **UTC** for consistency across build environments. + +### 4. Build System (`build.sh`) + +**Build all project binaries** + +```bash +# Build all binaries +./scripts/build.sh + +# Build specific binary +./scripts/build.sh server +./scripts/build.sh greet +``` + +**Builds:** +- `bin/server` - Web server binary +- `bin/greet` - CLI greeting tool + +### 5. OpenTelemetry Testing (`test-opentelemetry.sh`) + +**Test OpenTelemetry integration with Jaeger** + +```bash +# Start Jaeger and test tracing +./scripts/test-opentelemetry.sh +``` + +**Features:** +- Starts Jaeger in Docker +- Builds server with OpenTelemetry +- Makes test API calls +- Shows Jaeger UI URL +- Cleans up on exit + +## 🎯 Usage Patterns + +### Development Workflow +```bash +# 1. Build with version info +./scripts/build-with-version.sh + +# 2. Start server +./scripts/start-server.sh start + +# 3. Test endpoints +./scripts/start-server.sh test + +# 4. Check version +./bin/server --version +``` + +### Release Workflow +```bash +# 1. Bump version +./scripts/version-bump.sh minor + +# 2. Update CHANGELOG +vim AGENT_CHANGELOG.md + +# 3. Build release +./scripts/build-with-version.sh bin/release/server-v1.1.0 + +# 4. Test release +./bin/release/server-v1.1.0 --version + +# 5. Commit and tag +git commit -m "📖 chore: bump version to 1.1.0" +git tag -a v1.1.0 -m "Release 1.1.0" +``` + +### CI/CD Integration +```bash +# In CI pipeline: +./scripts/build-with-version.sh bin/server +./scripts/start-server.sh start +./scripts/start-server.sh test +``` + +## 🔧 Technical Details + +### Script Requirements +- **Bash** (v4.0+ recommended) +- **Git** (for version scripts) +- **Go** (v1.26+) +- **Docker** (for OpenTelemetry testing) + +### Environment Variables + +| Variable | Purpose | Example | +|----------|---------|---------| +| `VERSION` | Override version | `VERSION="1.2.3"` | +| `MAJOR` | Major version | `MAJOR=1` | +| `MINOR` | Minor version | `MINOR=0` | +| `PATCH` | Patch version | `PATCH=0` | +| `PRERELEASE` | Pre-release | `PRERELEASE="beta.1"` | + +### Exit Codes + +| Code | Meaning | +|------|---------| +| `0` | Success | +| `1` | General error | +| `2` | Invalid arguments | +| `3` | Missing dependencies | +| `4` | Server already running | +| `5` | Server not running | + +## 📝 Best Practices + +### Script Development +1. **Idempotent operations**: Scripts should be safe to run multiple times +2. **Clear error messages**: Help users understand what went wrong +3. **Dry-run support**: Add `--dry-run` flag for safety +4. **Logging**: Use consistent logging format +5. **Documentation**: Keep README updated with new scripts + +### Script Usage +1. **Check script help**: Most scripts support `--help` +2. **Test in development**: Try new scripts locally first +3. **Review changes**: Check what scripts modify before committing +4. **Update documentation**: Add new scripts to this README +5. **Follow conventions**: Use consistent naming and patterns + +## 🎓 Script Development Guide + +### Creating New Scripts + +1. **Name conventionally**: Use kebab-case (e.g., `do-thing.sh`) +2. **Add shebang**: `#!/bin/bash` +3. **Make executable**: `chmod +x script.sh` +4. **Add error handling**: `set -e` +5. **Document usage**: Add help text +6. **Test thoroughly**: Verify in multiple scenarios +7. **Add to README**: Document in this file + +### Script Template + +```bash +#!/bin/bash +# Script Name: description +# Usage: ./script-name.sh [options] + +set -e # Exit on error + +# Parse arguments +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + echo "Usage: $0 [options]" + exit 0 + ;; + *) + echo "Unknown option: $1" + exit 2 + ;; + esac +done + +# Main logic here +echo "Script executed successfully" + +exit 0 +``` + +## 🔮 Future Scripts + +### Planned Scripts +- **`release.sh`** - Full release automation +- **`changelog.sh`** - Automated changelog generation +- **`deploy.sh`** - Deployment automation +- **`test-all.sh`** - Comprehensive test suite runner +- **`lint.sh`** - Code quality checking + +### Requesting New Scripts +1. **Open an issue**: Describe the automation need +2. **Discuss approach**: Team review and design +3. **Implement script**: Follow best practices +4. **Test thoroughly**: Verify in multiple scenarios +5. **Document**: Add to this README + +## 📚 Resources + +### Official Documentation +- [Bash Guide](https://www.gnu.org/software/bash/) +- [Git SCM](https://git-scm.com/) +- [Go Build](https://golang.org/cmd/go/) + +### DanceLessonsCoach Specific +- [ADR 0014: Version Management](adr/0014-version-management-lifecycle.md) +- [AGENTS.md Scripts Section](#-scripts) +- [Contributing Guide](CONTRIBUTING.md) + +--- + +**Maintained by:** DanceLessonsCoach Team +**License:** MIT +**Status:** Actively developed \ No newline at end of file diff --git a/scripts/build-with-version.sh b/scripts/build-with-version.sh new file mode 100755 index 0000000..db1b47b --- /dev/null +++ b/scripts/build-with-version.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Build DanceLessonsCoach with version information +# Usage: ./scripts/build-with-version.sh [output_path] + +set -e + +# Default output path +OUTPUT_PATH="${1:-bin/server}" + +# Get version from VERSION file or use default +if [ -f "VERSION" ]; then + source VERSION + VERSION="$MAJOR.$MINOR.$PATCH${PRERELEASE:+-$PRERELEASE}" +else + VERSION="1.0.0" +fi + +# Get git information +GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") +GIT_DATE=$(git log -1 --format=%cd --date=short 2>/dev/null || echo "unknown") + +# Build time (UTC for consistency) +BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) + +echo "🔧 Building DanceLessonsCoach $VERSION" +echo " Commit: $GIT_COMMIT" +echo " Date: $GIT_DATE" +echo " Output: $OUTPUT_PATH" + +# Build with ldflags to inject version information +go build \ + -o "$OUTPUT_PATH" \ + -ldflags="\ + -X DanceLessonsCoach/pkg/version.Version=$VERSION \ + -X DanceLessonsCoach/pkg/version.Commit=$GIT_COMMIT \ + -X DanceLessonsCoach/pkg/version.Date=$BUILD_DATE \ + " \ + ./cmd/server + +echo "✅ Build complete: $OUTPUT_PATH" + +# Show version info +"$OUTPUT_PATH" --version 2>/dev/null || echo "Version: $VERSION" \ No newline at end of file diff --git a/scripts/version-bump.sh b/scripts/version-bump.sh new file mode 100755 index 0000000..57cf90b --- /dev/null +++ b/scripts/version-bump.sh @@ -0,0 +1,133 @@ +#!/bin/bash +# DanceLessonsCoach Version Bump Script +# Usage: ./scripts/version-bump.sh [major|minor|patch|pre|release] + +set -e + +# Load current version +VERSION_FILE="VERSION" +if [ ! -f "$VERSION_FILE" ]; then + echo "❌ Version file not found: $VERSION_FILE" + exit 1 +fi + +# Source version variables +source "$VERSION_FILE" + +# Validate bump type +BUMP_TYPE="${1:-patch}" +case "$BUMP_TYPE" in + major|minor|patch|pre|release) + echo "📋 Bumping version: $BUMP_TYPE" + ;; + *) + echo "❌ Invalid bump type: $BUMP_TYPE" + echo "Usage: $0 [major|minor|patch|pre|release]" + exit 1 + ;; +esac + +# Bump version function +bump_version() { + local type="$1" + + case "$type" in + major) + MAJOR=$((MAJOR + 1)) + MINOR=0 + PATCH=0 + PRERELEASE="" + ;; + minor) + MINOR=$((MINOR + 1)) + PATCH=0 + PRERELEASE="" + ;; + patch) + PATCH=$((PATCH + 1)) + PRERELEASE="" + ;; + pre) + if [ -z "$PRERELEASE" ]; then + PRERELEASE="alpha.1" + else + # Extract number and increment + if [[ "$PRERELEASE" =~ ^(alpha|beta|rc)\.([0-9]+)$ ]]; then + PRE_TYPE="${BASH_REMATCH[1]}" + PRE_NUM="${BASH_REMATCH[2]}" + PRERELEASE="$PRE_TYPE.$((PRE_NUM + 1))" + else + PRERELEASE="alpha.1" + fi + fi + ;; + release) + PRERELEASE="" + ;; + esac +} + +# Bump the version +bump_version "$BUMP_TYPE" + +# Calculate new version +NEW_VERSION="$MAJOR.$MINOR.$PATCH" +if [ -n "$PRERELEASE" ]; then + NEW_VERSION="$NEW_VERSION-$PRERELEASE" +fi + +echo "🔢 Current version: $MAJOR.$MINOR.$PATCH${PRERELEASE:+-$PRERELEASE}" +echo "🔜 New version: $NEW_VERSION" + +# Update VERSION file +cat > "$VERSION_FILE" << VERSION_EOF +# DanceLessonsCoach Version + +# Current Version (Semantic Versioning) +MAJOR=$MAJOR +MINOR=$MINOR +PATCH=$PATCH +PRERELEASE="$PRERELEASE" + +# Auto-generated fields (do not edit manually) +BUILD_DATE="" +GIT_COMMIT="" +GIT_TAG="" + +# Version Format: {MAJOR}.{MINOR}.{PATCH}-{PRERELEASE} +# Example: 1.0.0, 1.0.0-alpha.1, 2.3.4-beta.2 + +# Semantic Versioning Rules: +# - MAJOR: Breaking changes, major features +# - MINOR: Backwards-compatible features +# - PATCH: Backwards-compatible bug fixes +# - PRERELEASE: alpha, beta, rc (pre-release versions) + +# Changelog Reference: +# See AGENT_CHANGELOG.md for version history +VERSION_EOF + +echo "✅ Updated VERSION file" + +# Update main.go Swagger version (cross-platform) +MAIN_GO="cmd/server/main.go" +if [ -f "$MAIN_GO" ]; then + # Create temporary file + TMP_FILE=$(mktemp) + + # Use awk for cross-platform sed replacement + awk -v new_version="$NEW_VERSION" ' + { + if ($0 ~ /^\/\/ @version [0-9.]+/) { + print "// @version " new_version + } else { + print $0 + } + }' "$MAIN_GO" > "$TMP_FILE" + + # Replace original file + mv "$TMP_FILE" "$MAIN_GO" + echo "✅ Updated Swagger version in main.go" +fi + +echo "🎉 Version bump complete: $NEW_VERSION"