@@ -25,13 +25,14 @@ import {
2525 OAUTH_SECTION_INTRO ,
2626 type DeployComponentStatus ,
2727 type DeployPlanStep ,
28+ DEPLOY_COMPONENT_ORDER ,
29+ deployComponentLabels ,
2830 deployComponentStatus ,
2931 deployStatusPendingFooter ,
3032 domainAssociationSummary ,
3133 dnsDashboardHandoff ,
3234 dnsIntro ,
3335 dnsRecords ,
34- dnsVerified ,
3536 pausedOperationNotice ,
3637 printPlan ,
3738 productionSummary ,
@@ -581,7 +582,7 @@ async function runExistingDomainDnsVerification(
581582async function runDnsVerification (
582583 ctx : DeployContext ,
583584 state : DeployOperationState ,
584- ) : Promise < DnsVerificationResult > {
585+ ) : Promise < DnsVerificationResult | false > {
585586 const productionInstanceId =
586587 state . productionInstanceId ?? ctx . productionInstanceId ?? ctx . profile . instances . production ;
587588 if ( ! productionInstanceId ) {
@@ -592,13 +593,10 @@ async function runDnsVerification(
592593
593594 await requestDomainDnsCheck ( ctx . appId , state . productionDomainId ?? state . domain ) ;
594595
595- const outcome = await withSpinner ( `Verifying production setup for ${ state . domain } ...` , ( ) =>
596- pollDeployStatus ( ctx . appId , productionInstanceId ) ,
597- ) ;
596+ const outcome = await pollDeployStatus ( ctx . appId , productionInstanceId , state . domain ) ;
598597
599598 if ( outcome . verified ) {
600599 log . blank ( ) ;
601- for ( const line of dnsVerified ( state . domain ) ) log . success ( line ) ;
602600 log . info ( deployComponentStatus ( outcome . status ) ) ;
603601 return "verified" ;
604602 }
@@ -609,6 +607,15 @@ async function runDnsVerification(
609607 for ( const line of deployStatusPendingFooter ( state . domain , outcome . status ) ) {
610608 log . warn ( line ) ;
611609 }
610+
611+ // When all DNS components are verified but the server has not yet marked the
612+ // deployment complete (proxy_ok or another server-side gate is still pending),
613+ // do not offer a retry — the user cannot influence the remaining wait. Fail
614+ // closed so the caller exits without reaching finishDeploy.
615+ if ( outcome . status . dns && outcome . status . ssl && outcome . status . mail ) {
616+ return false ;
617+ }
618+
612619 if ( state . cnameTargets && state . cnameTargets . length > 0 ) {
613620 log . blank ( ) ;
614621 for ( const line of dnsRecords ( state . cnameTargets ) ) log . info ( line ) ;
@@ -630,15 +637,41 @@ type DeployStatusOutcome =
630637async function pollDeployStatus (
631638 appId : string ,
632639 productionInstanceId : string ,
640+ domain : string ,
633641) : Promise < DeployStatusOutcome > {
634- let status : DeployComponentStatus = { dns : false , ssl : false , mail : false } ;
635- for ( let attempt = 0 ; attempt < DEPLOY_STATUS_MAX_POLLS ; attempt ++ ) {
636- const result = await mapDeployError ( getDeployStatus ( appId , productionInstanceId ) ) ;
637- status = { dns : result . dns_ok , ssl : result . ssl_ok , mail : result . mail_ok } ;
638- if ( result . status === "complete" ) return { verified : true , status } ;
639- await sleep ( DEPLOY_STATUS_POLL_INTERVAL_MS ) ;
640- }
641- return { verified : false , status } ;
642+ let response = await mapDeployError ( getDeployStatus ( appId , productionInstanceId ) ) ;
643+ let status : DeployComponentStatus = {
644+ dns : response . dns_ok ,
645+ ssl : response . ssl_ok ,
646+ mail : response . mail_ok ,
647+ } ;
648+ let pollsRemaining = DEPLOY_STATUS_MAX_POLLS - 1 ;
649+
650+ for ( const component of DEPLOY_COMPONENT_ORDER ) {
651+ const labels = deployComponentLabels ( component , domain ) ;
652+ const flipped = await withSpinner ( labels . progress , async ( ) => {
653+ if ( status [ component ] ) return true ;
654+ while ( pollsRemaining > 0 ) {
655+ await sleep ( DEPLOY_STATUS_POLL_INTERVAL_MS ) ;
656+ pollsRemaining -- ;
657+ response = await mapDeployError ( getDeployStatus ( appId , productionInstanceId ) ) ;
658+ status = {
659+ dns : response . dns_ok ,
660+ ssl : response . ssl_ok ,
661+ mail : response . mail_ok ,
662+ } ;
663+ if ( status [ component ] ) return true ;
664+ }
665+ return false ;
666+ } ) ;
667+ if ( ! flipped ) return { verified : false , status } ;
668+ log . success ( labels . done ) ;
669+ }
670+
671+ if ( response . status !== "complete" ) {
672+ return { verified : false , status } ;
673+ }
674+ return { verified : true , status } ;
642675}
643676
644677async function requestDomainDnsCheck ( appId : string , domainIdOrName : string ) : Promise < void > {
0 commit comments