@@ -452,6 +452,137 @@ export const deployPreviewApplication = async ({
452452 return true ;
453453} ;
454454
455+ export const rebuildPreviewApplication = async ( {
456+ applicationId,
457+ titleLog = "Rebuild Preview Deployment" ,
458+ descriptionLog = "" ,
459+ previewDeploymentId,
460+ } : {
461+ applicationId : string ;
462+ titleLog : string ;
463+ descriptionLog : string ;
464+ previewDeploymentId : string ;
465+ } ) => {
466+ const application = await findApplicationById ( applicationId ) ;
467+ const previewDeployment =
468+ await findPreviewDeploymentById ( previewDeploymentId ) ;
469+
470+ const deployment = await createDeploymentPreview ( {
471+ title : titleLog ,
472+ description : descriptionLog ,
473+ previewDeploymentId : previewDeploymentId ,
474+ } ) ;
475+
476+ const previewDomain = getDomainHost ( previewDeployment ?. domain as Domain ) ;
477+ const issueParams = {
478+ owner : application ?. owner || "" ,
479+ repository : application ?. repository || "" ,
480+ issue_number : previewDeployment . pullRequestNumber ,
481+ comment_id : Number . parseInt ( previewDeployment . pullRequestCommentId ) ,
482+ githubId : application ?. githubId || "" ,
483+ } ;
484+
485+ try {
486+ const commentExists = await issueCommentExists ( {
487+ ...issueParams ,
488+ } ) ;
489+ if ( ! commentExists ) {
490+ const result = await createPreviewDeploymentComment ( {
491+ ...issueParams ,
492+ previewDomain,
493+ appName : previewDeployment . appName ,
494+ githubId : application ?. githubId || "" ,
495+ previewDeploymentId,
496+ } ) ;
497+
498+ if ( ! result ) {
499+ throw new TRPCError ( {
500+ code : "NOT_FOUND" ,
501+ message : "Pull request comment not found" ,
502+ } ) ;
503+ }
504+
505+ issueParams . comment_id = Number . parseInt ( result ?. pullRequestCommentId ) ;
506+ }
507+
508+ const buildingComment = getIssueComment (
509+ application . name ,
510+ "running" ,
511+ previewDomain ,
512+ ) ;
513+ await updateIssueComment ( {
514+ ...issueParams ,
515+ body : `### Dokploy Preview Deployment\n\n${ buildingComment } ` ,
516+ } ) ;
517+
518+ // Set application properties for preview deployment
519+ application . appName = previewDeployment . appName ;
520+ application . env = `${ application . previewEnv } \nDOKPLOY_DEPLOY_URL=${ previewDeployment ?. domain ?. host } ` ;
521+ application . buildArgs = `${ application . previewBuildArgs } \nDOKPLOY_DEPLOY_URL=${ previewDeployment ?. domain ?. host } ` ;
522+ application . buildSecrets = `${ application . previewBuildSecrets } \nDOKPLOY_DEPLOY_URL=${ previewDeployment ?. domain ?. host } ` ;
523+ application . rollbackActive = false ;
524+ application . buildRegistry = null ;
525+ application . rollbackRegistry = null ;
526+ application . registry = null ;
527+
528+ const serverId = application . serverId ;
529+ let command = "set -e;" ;
530+ // Only rebuild, don't clone repository
531+ command += await getBuildCommand ( application ) ;
532+ const commandWithLog = `(${ command } ) >> ${ deployment . logPath } 2>&1` ;
533+ if ( serverId ) {
534+ await execAsyncRemote ( serverId , commandWithLog ) ;
535+ } else {
536+ await execAsync ( commandWithLog ) ;
537+ }
538+ await mechanizeDockerContainer ( application ) ;
539+
540+ const successComment = getIssueComment (
541+ application . name ,
542+ "success" ,
543+ previewDomain ,
544+ ) ;
545+ await updateIssueComment ( {
546+ ...issueParams ,
547+ body : `### Dokploy Preview Deployment\n\n${ successComment } ` ,
548+ } ) ;
549+ await updateDeploymentStatus ( deployment . deploymentId , "done" ) ;
550+ await updatePreviewDeployment ( previewDeploymentId , {
551+ previewStatus : "done" ,
552+ } ) ;
553+ } catch ( error ) {
554+ let command = "" ;
555+
556+ // Only log details for non-ExecError errors
557+ if ( ! ( error instanceof ExecError ) ) {
558+ const message = error instanceof Error ? error . message : String ( error ) ;
559+ const encodedMessage = encodeBase64 ( message ) ;
560+ command += `echo "${ encodedMessage } " | base64 -d >> "${ deployment . logPath } ";` ;
561+ }
562+
563+ command += `echo "\nError occurred ❌, check the logs for details." >> ${ deployment . logPath } ;` ;
564+ const serverId = application . buildServerId || application . serverId ;
565+ if ( serverId ) {
566+ await execAsyncRemote ( serverId , command ) ;
567+ } else {
568+ await execAsync ( command ) ;
569+ }
570+
571+ const comment = getIssueComment ( application . name , "error" , previewDomain ) ;
572+ await updateIssueComment ( {
573+ ...issueParams ,
574+ body : `### Dokploy Preview Deployment\n\n${ comment } ` ,
575+ } ) ;
576+ await updateDeploymentStatus ( deployment . deploymentId , "error" ) ;
577+ await updatePreviewDeployment ( previewDeploymentId , {
578+ previewStatus : "error" ,
579+ } ) ;
580+ throw error ;
581+ }
582+
583+ return true ;
584+ } ;
585+
455586export const getApplicationStats = async ( appName : string ) => {
456587 if ( appName === "dokploy" ) {
457588 return await getAdvancedStats ( appName ) ;
0 commit comments