feat: add snapshot/rollback system with download capability
- Add AppSnapshot entity with type (pre_deploy/manual), status tracking, and file paths - Add SnapshotsService with create, capture, rollback, prune (max 10), and download logic - Add SnapshotsController with REST endpoints for CRUD, rollback, and file downloads - Add K8s methods: exportDatabaseDump, archiveWpContent, restoreWpContent - Auto-create pre-deploy snapshots before each deployment for rollback safety - Support downloading current live state (source, wp-content, database) without snapshots - Add snapshot management UI in app detail page with create, rollback, download, delete - Wire circular dependencies with forwardRef between Deployments and Snapshots modules
This commit is contained in:
@@ -6,6 +6,7 @@ import { Deployment } from './entities/deployment.entity';
|
||||
import { ApplicationsModule } from '../applications/applications.module';
|
||||
import { KubernetesModule } from '../kubernetes/kubernetes.module';
|
||||
import { BuildModule } from '../build/build.module';
|
||||
import { SnapshotsModule } from '../snapshots/snapshots.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -13,6 +14,7 @@ import { BuildModule } from '../build/build.module';
|
||||
forwardRef(() => ApplicationsModule),
|
||||
KubernetesModule,
|
||||
BuildModule,
|
||||
forwardRef(() => SnapshotsModule),
|
||||
],
|
||||
controllers: [DeploymentsController],
|
||||
providers: [DeploymentsService],
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ApplicationsService } from '../applications/applications.service';
|
||||
import { KubernetesService } from '../kubernetes/kubernetes.service';
|
||||
import { BuildService } from '../build/build.service';
|
||||
import { DeploymentStatus } from '../common/enums';
|
||||
import { SnapshotsService } from '../snapshots/snapshots.service';
|
||||
|
||||
@Injectable()
|
||||
export class DeploymentsService {
|
||||
@@ -18,11 +19,22 @@ export class DeploymentsService {
|
||||
private applicationsService: ApplicationsService,
|
||||
private kubernetesService: KubernetesService,
|
||||
private buildService: BuildService,
|
||||
@Inject(forwardRef(() => SnapshotsService))
|
||||
private snapshotsService: SnapshotsService,
|
||||
) {}
|
||||
|
||||
async triggerDeployment(applicationId: string, userId: string): Promise<Deployment> {
|
||||
const app = await this.applicationsService.findOne(applicationId, userId);
|
||||
|
||||
// Auto-snapshot before deploying (capture current state for rollback)
|
||||
try {
|
||||
const version = `v${Date.now()}`;
|
||||
await this.snapshotsService.createPreDeploySnapshot(app.id, userId, version);
|
||||
this.logger.log(`Pre-deploy snapshot created for ${app.name}`);
|
||||
} catch (e: any) {
|
||||
this.logger.warn(`Pre-deploy snapshot failed for ${app.name}: ${e.message} — continuing deploy`);
|
||||
}
|
||||
|
||||
// Create deployment record
|
||||
const deployment = this.deploymentsRepository.create({
|
||||
applicationId: app.id,
|
||||
@@ -173,6 +185,15 @@ export class DeploymentsService {
|
||||
throw new NotFoundException('No source code available. Upload code or set a git URL first.');
|
||||
}
|
||||
|
||||
// Auto-snapshot before redeploy
|
||||
try {
|
||||
const version = `v${Date.now()}`;
|
||||
await this.snapshotsService.createPreDeploySnapshot(app.id, userId, version);
|
||||
this.logger.log(`Pre-redeploy snapshot created for ${app.name}`);
|
||||
} catch (e: any) {
|
||||
this.logger.warn(`Pre-redeploy snapshot failed for ${app.name}: ${e.message} — continuing`);
|
||||
}
|
||||
|
||||
// Create new deployment record
|
||||
const deployment = this.deploymentsRepository.create({
|
||||
applicationId: app.id,
|
||||
|
||||
Reference in New Issue
Block a user