chore: Add automated release workflow and version management

- Add GitHub Actions workflow for automated releases
- Add semantic versioning support
- Update docker-compose files with version variables
- Add release script for manual versioning
- Add comprehensive version workflow documentation

🚀 Ready for v1.2.5 release
This commit is contained in:
Tomas Dvorak
2026-02-27 19:03:41 +01:00
parent aef1e39d7a
commit a9395be39f
13 changed files with 1861 additions and 280 deletions
+277
View File
@@ -0,0 +1,277 @@
# Trackeep Auto-Update System
This system provides automated daily updates for Trackeep using Docker pulls from GitHub Container Registry.
## Overview
The auto-update system pulls specific tagged images daily:
- `ghcr.io/dvorinka/trackeep/backend:main-aef1e39`
- `ghcr.io/dvorinka/trackeep/frontend:main-aef1e39`
## Files Created
### 1. Production Docker Compose
- **File**: `docker-compose.prod.yml`
- **Purpose**: Uses pre-built images instead of local builds
- **Images**: Uses the specific tagged versions you specified
### 2. Auto-Update Script
- **File**: `scripts/auto-update.sh`
- **Purpose**: Main script that performs the update process
- **Features**:
- Checks for new images
- Creates automatic backups
- Updates services safely
- Health checks after update
- Comprehensive logging
### 3. Cron Setup Script
- **File**: `scripts/setup-auto-update.sh`
- **Purpose**: Sets up daily cron job at 2 AM
- **Schedule**: Daily at 2:00 AM
- **Alternative**: Can be run manually
### 4. SystemD Service Setup
- **File**: `scripts/setup-systemd-update.sh`
- **Purpose**: Alternative to cron using systemd timers
- **Schedule**: Daily with randomized delay (up to 1 hour)
- **Benefits**: More reliable than cron, better logging
## Quick Start
### Option 1: Cron Setup (Recommended for simplicity)
```bash
# Setup daily auto-update at 2 AM
sudo ./scripts/setup-auto-update.sh
# Check status
./scripts/setup-auto-update.sh status
# Test manually
./scripts/setup-auto-update.sh test
# Remove later if needed
sudo ./scripts/setup-auto-update.sh remove
```
### Option 2: SystemD Setup (More robust)
```bash
# Install systemd service
sudo ./scripts/setup-systemd-update.sh
# Check status
./scripts/setup-systemd-update.sh status
# Test manually
sudo ./scripts/setup-systemd-update.sh test
# Remove later if needed
sudo ./scripts/setup-systemd-update.sh remove
```
### Option 3: Manual Execution
```bash
# Run auto-update manually
./scripts/auto-update.sh
# View logs
tail -f /var/log/trackeep-auto-update.log
```
## Configuration
### Image Tags
The system is configured to pull these specific images:
- Backend: `ghcr.io/dvorinka/trackeep/backend:main-aef1e39`
- Frontend: `ghcr.io/dvorinka/trackeep/frontend:main-aef1e39`
To update to different tags, edit these files:
1. `docker-compose.prod.yml` - Update image tags
2. `scripts/auto-update.sh` - Update BACKEND_IMAGE and FRONTEND_IMAGE variables
### Schedule Options
**Cron Schedule** (setup-auto-update.sh):
- Default: Daily at 2:00 AM
- Location: User's crontab
- Edit with: `crontab -e`
**SystemD Schedule** (setup-systemd-update.sh):
- Default: Daily with randomized delay
- Location: systemd timer
- More reliable than cron
- Better logging integration
## Features
### Safety Features
- ✅ Pre-update backups (database, config files)
- ✅ Health checks after update
- ✅ Rollback capability from backups
- ✅ Comprehensive logging
- ✅ Error handling and recovery
### Update Process
1. Check Docker daemon status
2. Pull latest images (compare with current)
3. Create backup if updates available
4. Stop and recreate services
5. Wait for health checks
6. Clean up old images
7. Log all actions
### Backup Strategy
- Automatic backup before each update
- Database dump (PostgreSQL)
- Configuration files (.env, docker-compose files)
- Timestamped backup directories
- Location: `./backups/auto-update-YYYYMMDD_HHMMSS/`
## Monitoring
### Logs
- **Location**: `/var/log/trackeep-auto-update.log`
- **View**: `tail -f /var/log/trackeep-auto-update.log`
- **SystemD**: `journalctl -u trackeep-auto-update.service -f`
### Status Commands
```bash
# Cron status
crontab -l | grep trackeep
# SystemD status
systemctl status trackeep-auto-update.timer
systemctl list-timers trackeep-auto-update.timer
# Manual check
./scripts/auto-update.sh
```
## Troubleshooting
### Common Issues
1. **Docker not running**
```
❌ Docker is not running. Aborting update.
```
**Solution**: Start Docker daemon
2. **Permission denied**
```
❌ Permission denied
```
**Solution**: Use sudo for setup scripts
3. **Image pull failed**
```
❌ Failed to pull backend image
```
**Solution**: Check internet connection and registry access
4. **Service not healthy**
```
⚠️ Backend health check timed out
```
**Solution**: Check service logs with `docker compose logs`
### Manual Recovery
```bash
# Check what's running
docker compose -f docker-compose.prod.yml ps
# View logs
docker compose -f docker-compose.prod.yml logs
# Manual restart
docker compose -f docker-compose.prod.yml restart
# Restore from backup
./backups/auto-update-YYYYMMDD_HHMMSS/
```
## Customization
### Change Update Frequency
**Cron**: Edit crontab entry
```bash
crontab -e
# Change "0 2 * * *" to desired schedule
# Examples:
# "0 */6 * * *" - Every 6 hours
# "0 2 * * 1" - Weekly on Monday
# "0 2 1 * *" - Monthly on 1st
```
**SystemD**: Edit timer file
```bash
sudo systemctl edit trackeep-auto-update.timer
# Change OnCalendar=daily to desired schedule
```
### Change Images
1. Edit `docker-compose.prod.yml`
2. Edit `scripts/auto-update.sh` (BACKEND_IMAGE, FRONTEND_IMAGE)
3. Restart services: `docker compose -f docker-compose.prod.yml up -d`
### Add Notifications
Edit `scripts/auto-update.sh` to add email/webhook notifications in the success/failure sections.
## Security Considerations
- ✅ Images pulled from trusted GitHub Container Registry
- ✅ Specific tags prevent unexpected updates
- ✅ Backups created before changes
- ✅ Health checks prevent broken deployments
- ⚠️ Ensure proper file permissions on backup directory
- ⚠️ Monitor log file size (add log rotation if needed)
## Comparison with Original Update System
| Feature | Original File-Based | New Docker-Based |
|---------|-------------------|------------------|
| Update Method | Download & extract files | Docker pull & recreate |
| Safety | Moderate | High (atomic updates) |
| Rollback | Manual | Automatic from backup |
| Speed | Slower (file operations) | Faster (Docker layers) |
| Reliability | Lower (file permissions) | Higher (container isolation) |
| Logging | Basic | Comprehensive |
| Scheduling | Not implemented | Cron/SystemD available |
## Migration from Original System
If you were using the original file-based update system:
1. **Backup current setup**:
```bash
cp docker-compose.yml docker-compose.backup.yml
```
2. **Switch to production compose**:
```bash
docker compose down
docker compose -f docker-compose.prod.yml up -d
```
3. **Setup auto-update**:
```bash
sudo ./scripts/setup-auto-update.sh
```
4. **Test manually**:
```bash
./scripts/auto-update.sh
```
5. **Monitor first automatic update**:
```bash
tail -f /var/log/trackeep-auto-update.log
```
## Support
For issues or questions:
1. Check logs: `/var/log/trackeep-auto-update.log`
2. Run manual test: `./scripts/auto-update.sh`
3. Check service status: `docker compose -f docker-compose.prod.yml ps`
4. Review this README for troubleshooting steps
+301
View File
@@ -0,0 +1,301 @@
# Trackeep Version Management & Update Workflow
## 📍 Where Version Comes From
### **Current Version Detection:**
1. **Backend**: `APP_VERSION` environment variable (defaults to "1.0.0")
2. **Frontend**: `VITE_APP_VERSION` environment variable (passed during build)
### **Version Priority Order:**
1. `__APP_VERSION__` build constant (highest priority)
2. `VITE_APP_VERSION` environment variable (frontend)
3. `APP_VERSION` environment variable (backend)
4. Falls back to "1.0.0" (default)
---
## 🏷️ How to Set Version Properly
### **Option 1: Environment Variables (Recommended)**
#### **Development:**
```bash
# Set version in .env file
echo "APP_VERSION=1.2.0" >> .env
# Start with version
docker compose up
```
#### **Production:**
```bash
# Set version environment variable
export APP_VERSION=1.2.0
docker compose -f docker-compose.prod.yml up
```
### **Option 2: Build-time Constants**
#### **Frontend (vite.config.ts):**
```typescript
export default defineConfig({
define: {
__APP_VERSION__: JSON.stringify(process.env.npm_package_version || '1.0.0')
},
// ... rest of config
})
```
#### **Backend (build):**
```bash
# Build with version
APP_VERSION=1.2.0 go build -ldflags "-X main.version=${APP_VERSION}"
```
---
## 🚀 How to Push Updates with Proper Labels
### **Method 1: GitHub Actions (Recommended)**
#### **Create `.github/workflows/release.yml`:**
```yaml
name: Release and Deploy
on:
push:
tags:
- 'v*' # Trigger on version tags like v1.2.0
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version from tag
run: |
VERSION=${GITHUB_REF#refs/tags/v*}
VERSION=${VERSION#refs/tags/v}
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "Building version: $VERSION"
- name: Build and push backend
uses: docker/build-push-action@v5
with:
context: ./backend
file: ./backend/Dockerfile
push: true
tags: |
ghcr.io/dvorinka/trackeep/backend:latest
ghcr.io/dvorinka/trackeep/backend:${{ env.VERSION }}
labels: |
version=${{ env.VERSION }}
build-date=${{ github.event.head_commit.timestamp }}
commit=${{ github.sha }}
- name: Build and push frontend
uses: docker/build-push-action@v5
with:
context: .
file: ./frontend/Dockerfile
push: true
tags: |
ghcr.io/dvorinka/trackeep/frontend:latest
ghcr.io/dvorinka/trackeep/frontend:${{ env.VERSION }}
labels: |
version=${{ env.VERSION }}
build-date=${{ github.event.head_commit.timestamp }}
commit=${{ github.sha }}
```
### **Method 2: Manual Docker Push**
#### **Tag and Push:**
```bash
# Set version
export VERSION=1.2.0
# Build and tag with version
docker build -t ghcr.io/dvorinka/trackeep/backend:${VERSION} ./backend
docker build -t ghcr.io/dvorinka/trackeep/backend:latest ./backend
docker build -t ghcr.io/dvorinka/trackeep/frontend:${VERSION} .
docker build -t ghcr.io/dvorinka/trackeep/frontend:latest .
# Push both tags
docker push ghcr.io/dvorinka/trackeep/backend:${VERSION}
docker push ghcr.io/dvorinka/trackeep/backend:latest
docker push ghcr.io/dvorinka/trackeep/frontend:${VERSION}
docker push ghcr.io/dvorinka/trackeep/frontend:latest
# Create Git tag
git tag v${VERSION}
git push origin v${VERSION}
```
---
## 📋 How People Do It (Industry Standards)
### **Semantic Versioning:**
```
MAJOR.MINOR.PATCH
1.2.0
│ │ └─ PATCH: Bug fixes, small features
│ └─ MINOR: New features, breaking changes
└─ MAJOR: Major changes, breaking API
```
### **Version Labels:**
```dockerfile
# In Dockerfile
LABEL version="1.2.0"
LABEL build-date="2024-02-27"
LABEL commit="abc123def"
```
### **Environment Variables:**
```bash
# Production
APP_VERSION=1.2.0
VITE_APP_VERSION=1.2.0
# Development
APP_VERSION=1.3.0-dev
VITE_APP_VERSION=1.3.0-dev
```
### **Git Tags:**
```bash
# Create version tag
git tag -a v1.2.0 -m "Release version 1.2.0"
git push origin v1.2.0
# Lightweight tags (for CI/CD)
git tag v1.2.0 ${COMMIT_SHA}
git push origin v1.2.0
```
---
## 🔄 Update Detection Logic
### **How System Detects Updates:**
#### **Current Setup:**
```go
// Backend gets current version
currentVersion := os.Getenv("APP_VERSION")
if currentVersion == "" {
currentVersion = "1.0.0"
}
// Frontend gets version from build
return import.meta.env.VITE_APP_VERSION || '1.0.0'
```
#### **Update Check:**
```go
// Compares current vs latest
if isNewerVersion("latest", currentVersion) {
// Update available!
return updateInfo, true, nil
}
```
---
## 🎯 Recommended Workflow
### **Development:**
```bash
# 1. Set version in .env
echo "APP_VERSION=1.2.1-dev" >> .env
# 2. Start development
docker compose up
# 3. Test updates
curl http://localhost:8080/api/updates/check
```
### **Production Release:**
```bash
# 1. Update version
export APP_VERSION=1.2.1
# 2. Build and push
./scripts/release.sh 1.2.1
# 3. Deploy
docker compose -f docker-compose.prod.yml up -d
```
### **Version Update Process:**
1. **Code changes** → Commit to main branch
2. **Version bump** → Update APP_VERSION in .env
3. **Tag release**`git tag v1.2.1 && git push origin v1.2.1`
4. **Auto-build** → GitHub Actions builds Docker images
5. **Push tags**`latest` + versioned tags to registry
6. **Deploy** → Users get updates automatically
---
## ✅ Best Practices
### **Version Management:**
- ✅ Use semantic versioning (MAJOR.MINOR.PATCH)
- ✅ Always update both frontend and backend versions
- ✅ Use environment variables for flexibility
- ✅ Tag releases in Git
### **Docker Tags:**
- ✅ Always push `latest` tag for updates
- ✅ Also push versioned tags for rollback
- ✅ Add labels for metadata
- ✅ Use consistent naming convention
### **Release Process:**
- ✅ Automate with GitHub Actions
- ✅ Test before tagging
- ✅ Document changes in release notes
- ✅ Use semantic versioning
---
## 🧪 Testing Your Setup
### **Test Version Detection:**
```bash
# Check current version
curl -s http://localhost:8080/api/updates/check | jq '.currentVersion'
# Should return your APP_VERSION value
```
### **Test Update Detection:**
```bash
# Simulate update available
# Backend will show "latest" vs your current version
```
### **Verify Docker Images:**
```bash
# Check if images have version labels
docker inspect ghcr.io/dvorinka/trackeep/backend:latest | jq '.[0].Config.Labels.version'
docker inspect ghcr.io/dvorinka/trackeep/frontend:latest | jq '.[0].Config.Labels.version'
```
This system ensures proper versioning and update detection for your Trackeep application!