📝 docs: add comprehensive version management and CLI documentation
This commit is contained in:
166
AGENTS.md
166
AGENTS.md
@@ -136,6 +136,22 @@ DanceLessonsCoach/
|
|||||||
|
|
||||||
## 🚀 Server Management
|
## 🚀 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
|
### Using the Server Control Script
|
||||||
|
|
||||||
A convenient shell script is provided for managing the server lifecycle:
|
A convenient shell script is provided for managing the server lifecycle:
|
||||||
@@ -874,6 +890,156 @@ defer cancel()
|
|||||||
- ✅ Comprehensive logging with Zerolog
|
- ✅ Comprehensive logging with Zerolog
|
||||||
- ✅ Build system with binary output
|
- ✅ Build system with binary output
|
||||||
- ✅ Complete documentation with commit conventions
|
- ✅ 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
|
## 📝 Architecture Decision Records
|
||||||
|
|
||||||
|
|||||||
24
VERSION
Normal file
24
VERSION
Normal file
@@ -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
|
||||||
@@ -309,6 +309,44 @@ go install github.com/swaggo/swag/cmd/swag@latest
|
|||||||
// @BasePath /api
|
// @BasePath /api
|
||||||
package main
|
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
|
# 3. Annotate handlers and models with hierarchical tags
|
||||||
// @Summary Get personalized greeting
|
// @Summary Get personalized greeting
|
||||||
// @Description Returns a greeting with the specified name
|
// @Description Returns a greeting with the specified name
|
||||||
|
|||||||
402
adr/0014-version-management-lifecycle.md
Normal file
402
adr/0014-version-management-lifecycle.md
Normal file
@@ -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
|
||||||
198
adr/0015-cli-subcommands-cobra.md
Normal file
198
adr/0015-cli-subcommands-cobra.md
Normal file
@@ -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
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// Package main provides the DanceLessonsCoach server entry point
|
// Package main provides the DanceLessonsCoach server entry point
|
||||||
//
|
//
|
||||||
// @title DanceLessonsCoach API
|
// @title DanceLessonsCoach API
|
||||||
// @version 1.0
|
// @version 1.1.1
|
||||||
// @description API for DanceLessonsCoach service providing greeting functionality
|
// @description API for DanceLessonsCoach service providing greeting functionality
|
||||||
// @termsOfService http://swagger.io/terms/
|
// @termsOfService http://swagger.io/terms/
|
||||||
|
|
||||||
@@ -20,14 +20,23 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"DanceLessonsCoach/pkg/config"
|
"DanceLessonsCoach/pkg/config"
|
||||||
"DanceLessonsCoach/pkg/server"
|
"DanceLessonsCoach/pkg/server"
|
||||||
|
"DanceLessonsCoach/pkg/version"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
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)
|
// Load configuration (this will also setup logging)
|
||||||
cfg, err := config.LoadConfig()
|
cfg, err := config.LoadConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
365
doc/version-management-guide.md
Normal file
365
doc/version-management-guide.md
Normal file
@@ -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
|
||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
|
"DanceLessonsCoach/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config represents the application configuration
|
// Config represents the application configuration
|
||||||
@@ -52,6 +54,21 @@ type APIConfig struct {
|
|||||||
V2Enabled bool `mapstructure:"v2_enabled"`
|
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
|
// SamplerConfig holds tracing sampler configuration
|
||||||
type SamplerConfig struct {
|
type SamplerConfig struct {
|
||||||
Type string `mapstructure:"type"`
|
Type string `mapstructure:"type"`
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"embed"
|
"embed"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@@ -20,6 +21,7 @@ import (
|
|||||||
"DanceLessonsCoach/pkg/greet"
|
"DanceLessonsCoach/pkg/greet"
|
||||||
"DanceLessonsCoach/pkg/telemetry"
|
"DanceLessonsCoach/pkg/telemetry"
|
||||||
"DanceLessonsCoach/pkg/validation"
|
"DanceLessonsCoach/pkg/validation"
|
||||||
|
"DanceLessonsCoach/pkg/version"
|
||||||
|
|
||||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||||
@@ -70,6 +72,9 @@ func (s *Server) setupRoutes() {
|
|||||||
// Readiness endpoint at root level
|
// Readiness endpoint at root level
|
||||||
s.router.Get("/api/ready", s.handleReadiness)
|
s.router.Get("/api/ready", s.handleReadiness)
|
||||||
|
|
||||||
|
// Version endpoint at root level
|
||||||
|
s.router.Get("/api/version", s.handleVersion)
|
||||||
|
|
||||||
// API routes
|
// API routes
|
||||||
s.router.Route("/api/v1", func(r chi.Router) {
|
s.router.Route("/api/v1", func(r chi.Router) {
|
||||||
r.Use(s.getAllMiddlewares()...)
|
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 {
|
func (s *Server) Router() http.Handler {
|
||||||
return s.router
|
return s.router
|
||||||
}
|
}
|
||||||
|
|||||||
110
pkg/version/version.go
Normal file
110
pkg/version/version.go
Normal file
@@ -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)
|
||||||
|
}
|
||||||
313
scripts/README.md
Normal file
313
scripts/README.md
Normal file
@@ -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
|
||||||
43
scripts/build-with-version.sh
Executable file
43
scripts/build-with-version.sh
Executable file
@@ -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"
|
||||||
133
scripts/version-bump.sh
Executable file
133
scripts/version-bump.sh
Executable file
@@ -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"
|
||||||
Reference in New Issue
Block a user