diff --git a/backend/deployment/orchestrator.go b/backend/deployment/orchestrator.go index 7ed5e81..8e0be81 100644 --- a/backend/deployment/orchestrator.go +++ b/backend/deployment/orchestrator.go @@ -13,6 +13,7 @@ import ( "io" "os" "path/filepath" + "strings" "time" "gorm.io/gorm" @@ -45,7 +46,8 @@ func NewOrchestrator(db *gorm.DB) *DeploymentOrchestrator { } // createBackup creates a pre-deployment backup -func (o *DeploymentOrchestrator) createBackup() (string, error) { +// Returns (backupPath, isFreshInstall, error) +func (o *DeploymentOrchestrator) createBackup() (string, bool, error) { // Get current version for backup metadata runner := migrations.NewMigrationRunner(o.DB) currentVer, migNum, err := runner.GetCurrentVersion() @@ -58,10 +60,14 @@ func (o *DeploymentOrchestrator) createBackup() (string, error) { backupService := backup.NewBackupService() metadata, err := backupService.CreateJSONBackup(currentVer, migNum) if err != nil { - return "", fmt.Errorf("failed to create backup: %w", err) + // Check if this is a fresh installation (no tables exist) + if strings.Contains(err.Error(), "doesn't exist") || strings.Contains(err.Error(), "no such table") { + return "", true, nil // Fresh install, no backup needed + } + return "", false, fmt.Errorf("failed to create backup: %w", err) } - return metadata.FilePath, nil + return metadata.FilePath, false, nil } // checkCompatibility verifies version compatibility @@ -203,24 +209,33 @@ func (o *DeploymentOrchestrator) FullDeploymentWithImport(importFilePath string) // Step 1: Create backup of current state logger.Info("Step 1/5: Creating pre-deployment backup...") - backupPath, err := o.createBackup() + backupPath, isFreshInstall, err := o.createBackup() if err != nil { report.Errors = append(report.Errors, fmt.Sprintf("Backup failed: %v", err)) return report, fmt.Errorf("backup failed: %w", err) } - report.BackupCreated = true - report.BackupPath = backupPath - logger.Info("✓ Backup created: %s", backupPath) + if isFreshInstall { + logger.Info("ℹ Fresh installation detected - skipping backup") + report.Warnings = append(report.Warnings, "Fresh installation - no backup created") + } else { + report.BackupCreated = true + report.BackupPath = backupPath + logger.Info("✓ Backup created: %s", backupPath) + } // Step 2: Export current state (before migration) logger.Info("Step 2/5: Exporting current master data state...") - exportDir := "./tmp" - err = gsmaster.ExportAll(exportDir) - if err != nil { - report.Warnings = append(report.Warnings, fmt.Sprintf("Current state export failed: %v", err)) - logger.Warn("Could not export current state: %v", err) + if isFreshInstall { + logger.Info("ℹ Fresh installation - skipping export") } else { - logger.Info("✓ Current state exported to: %s", exportDir) + exportDir := "./tmp" + err = gsmaster.ExportAll(exportDir) + if err != nil { + report.Warnings = append(report.Warnings, fmt.Sprintf("Current state export failed: %v", err)) + logger.Warn("Could not export current state: %v", err) + } else { + logger.Info("✓ Current state exported to: %s", exportDir) + } } // Step 3: Check version compatibility diff --git a/docs/deployment/README_DEPLOYMENT.md b/docs/deployment/README_DEPLOYMENT.md index 73d5d32..ec66f3c 100644 --- a/docs/deployment/README_DEPLOYMENT.md +++ b/docs/deployment/README_DEPLOYMENT.md @@ -271,7 +271,8 @@ Type 'DEPLOY' to continue: 2. **Backup current database** - Creates timestamped backup in `backups/` directory - Format: `pre-deploy-v0.1.38-20260117-143022.sql` - - Aborts deployment if backup fails + - Skips backup on fresh installation (when tables don't exist) + - Aborts deployment if backup fails on existing installation 3. **Checkout version** - Fetches from git origin @@ -292,8 +293,8 @@ Type 'DEPLOY' to continue: 7. **Run deployment command** - Executes `deploy deploy [importDir]` in backend container - - Creates backup of current database state - - Exports current master data + - Creates backup of current database state (skipped on fresh install) + - Exports current master data (skipped on fresh install) - Checks version compatibility - Applies pending database migrations - Imports master data (if package provided) @@ -319,6 +320,8 @@ Type 'DEPLOY' to continue: - Reports deployment status - Cleans up temporary files +**Fresh Installation**: On first deployment to an empty database, backup and export steps are automatically skipped. This is expected behavior and not an error. + **Deployment log**: Saved to `logs/deploy-YYYYMMDD-HHMMSS.log` ### 7. Target System: Post-Deployment