@@ -26,6 +26,7 @@ import { BACKGROUND_FUNCTIONS_WARNING } from '../../lib/log.js'
26
26
import { type Spinner , startSpinner , stopSpinner } from '../../lib/spinner.js'
27
27
import { detectFrameworkSettings , getDefaultConfig } from '../../utils/build-info.js'
28
28
import {
29
+ NETLIFY_CYAN_HEX ,
29
30
NETLIFYDEVERR ,
30
31
NETLIFYDEVLOG ,
31
32
chalk ,
@@ -48,6 +49,8 @@ import { sitesCreate } from '../sites/sites-create.js'
48
49
import type { $TSFixMe } from '../types.js'
49
50
import { SiteInfo } from '../../utils/types.js'
50
51
import type { DeployOptionValues } from './option_values.js'
52
+ import boxen from 'boxen'
53
+ import terminalLink from 'terminal-link'
51
54
52
55
const triggerDeploy = async ( {
53
56
api,
@@ -280,7 +283,6 @@ const prepareProductionDeploy = async ({ api, siteData }) => {
280
283
await api . unlockDeploy ( { deploy_id : siteData . published_deploy . id } )
281
284
log ( `\n${ NETLIFYDEVLOG } "Auto publishing" has been enabled for production context\n` )
282
285
}
283
- log ( 'Deploying to main site URL...' )
284
286
}
285
287
286
288
// @ts -expect-error TS(7006) FIXME: Parameter 'actual' implicitly has an 'any' type.
@@ -345,7 +347,7 @@ const deployProgressCb = function () {
345
347
return
346
348
case 'stop' :
347
349
default : {
348
- stopSpinner ( { spinner : spinnersByType [ event . type ] , text : event . msg } )
350
+ spinnersByType [ event . type ] . success ( event . msg )
349
351
delete spinnersByType [ event . type ]
350
352
}
351
353
}
@@ -380,7 +382,9 @@ const uploadDeployBlobs = async ({
380
382
const blobsToken = token || undefined
381
383
const { success } = await runCoreSteps ( [ 'blobs_upload' ] , {
382
384
...options ,
383
- quiet : silent ,
385
+ // We log our own progress so we don't want this as well. Plus, this logs much of the same
386
+ // information as the build that (likely) came before this as part of the deploy build.
387
+ quiet : options . debug ?? true ,
384
388
// @ts -expect-error(serhalp) -- Untyped in `@netlify/build`
385
389
cachedConfig,
386
390
packagePath,
@@ -458,8 +462,6 @@ const runDeploy = async ({
458
462
try {
459
463
if ( deployToProduction ) {
460
464
await prepareProductionDeploy ( { siteData, api } )
461
- } else {
462
- log ( 'Deploying to draft URL...' )
463
465
}
464
466
465
467
const draft = ! deployToProduction && ! alias
@@ -590,13 +592,7 @@ const handleBuild = async ({
590
592
return { newConfig, configMutations }
591
593
}
592
594
593
- /**
594
- *
595
- * @param {* } options Bundling options
596
- * @returns
597
- */
598
- // @ts -expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
599
- const bundleEdgeFunctions = async ( options , command : BaseCommand ) => {
595
+ const bundleEdgeFunctions = async ( options : DeployOptionValues , command : BaseCommand ) : Promise < void > => {
600
596
const argv = process . argv . slice ( 2 )
601
597
const statusCb =
602
598
options . silent || argv . includes ( '--json' ) || argv . includes ( '--silent' ) ? ( ) => { } : deployProgressCb ( )
@@ -612,6 +608,10 @@ const bundleEdgeFunctions = async (options, command: BaseCommand) => {
612
608
packagePath : command . workspacePackage ,
613
609
buffer : true ,
614
610
featureFlags : edgeFunctionsFeatureFlags ,
611
+ // We log our own progress so we don't want this as well. Plus, this logs much of the same
612
+ // information as the build that (likely) came before this as part of the deploy build.
613
+ quiet : options . debug ?? true ,
614
+ // @ts -expect-error FIXME(serhalp): This is missing from the `runCoreSteps` type in @netlify/build
615
615
edgeFunctionsBootstrapURL : await getBootstrapURL ( ) ,
616
616
} )
617
617
@@ -645,32 +645,24 @@ interface JsonData {
645
645
646
646
const printResults = ( {
647
647
deployToProduction,
648
- isIntegrationDeploy,
649
648
json,
650
649
results,
651
650
runBuildCommand,
652
651
} : {
653
652
deployToProduction : boolean
654
- isIntegrationDeploy : boolean
655
653
json : boolean
656
654
results : Awaited < ReturnType < typeof prepAndRunDeploy > >
657
655
runBuildCommand : boolean
658
656
} ) : void => {
659
657
const msgData : Record < string , string > = {
660
- 'Build logs' : results . logsUrl ,
661
- 'Function logs' : results . functionLogsUrl ,
662
- 'Edge function Logs' : results . edgeFunctionLogsUrl ,
663
- }
664
-
665
- if ( deployToProduction ) {
666
- msgData [ 'Unique deploy URL' ] = results . deployUrl
667
- msgData [ 'Website URL' ] = results . siteUrl
668
- } else {
669
- msgData [ 'Website draft URL' ] = results . deployUrl
658
+ 'Build logs' : terminalLink ( results . logsUrl , results . logsUrl ) ,
659
+ 'Function logs' : terminalLink ( results . functionLogsUrl , results . functionLogsUrl ) ,
660
+ 'Edge function Logs' : terminalLink ( results . edgeFunctionLogsUrl , results . edgeFunctionLogsUrl ) ,
670
661
}
671
662
672
- // Spacer
673
- log ( )
663
+ log ( '' )
664
+ // Note: this is leakily mimicking the @netlify /build heading style
665
+ log ( chalk . cyanBright . bold ( `🚀 Deploy complete\n${ '─' . repeat ( 64 ) } ` ) )
674
666
675
667
// Json response for piping commands
676
668
if ( json ) {
@@ -690,40 +682,52 @@ const printResults = ({
690
682
logJson ( jsonData )
691
683
exit ( 0 )
692
684
} else {
685
+ const message = deployToProduction
686
+ ? `Deployed to production URL: ${ terminalLink ( results . siteUrl , results . siteUrl ) } \n
687
+ Unique deploy URL: ${ terminalLink ( results . deployUrl , results . deployUrl ) } `
688
+ : `Deployed draft to ${ terminalLink ( results . deployUrl , results . deployUrl ) } `
689
+
690
+ log (
691
+ boxen ( message , {
692
+ padding : 1 ,
693
+ margin : 1 ,
694
+ textAlignment : 'center' ,
695
+ borderStyle : 'round' ,
696
+ borderColor : NETLIFY_CYAN_HEX ,
697
+ // This is an intentional half-width space to work around a unicode padding math bug in boxen
698
+ // eslint-disable-next-line no-irregular-whitespace
699
+ title : `⬥ ${ deployToProduction ? 'Production deploy' : 'Draft deploy' } is live ⬥ ` ,
700
+ titleAlignment : 'center' ,
701
+ } ) ,
702
+ )
703
+
693
704
log ( prettyjson . render ( msgData ) )
694
705
695
706
if ( ! deployToProduction ) {
696
707
log ( )
697
- log ( 'If everything looks good on your draft URL, deploy it to your main site URL with the --prod flag.' )
698
- log (
699
- chalk . cyanBright . bold (
700
- `netlify ${ isIntegrationDeploy ? 'integration:' : '' } deploy${ runBuildCommand ? ' --build' : '' } --prod` ,
701
- ) ,
702
- )
708
+ log ( 'If everything looks good on your draft URL, deploy it to your main site URL with the --prod flag:' )
709
+ log ( chalk . cyanBright . bold ( `netlify deploy${ runBuildCommand ? '' : '--no-build' } --prod` ) )
703
710
log ( )
704
711
}
705
712
}
706
713
}
707
714
708
715
const prepAndRunDeploy = async ( {
709
- // @ts -expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
710
716
api,
711
- // @ts -expect-error TS(7031) FIXME: Binding element 'command' implicitly has an 'any' ... Remove this comment to see the full error message
712
717
command,
713
- // @ts -expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message
714
718
config,
715
- // @ts -expect-error TS(7031) FIXME: Binding element 'deployToProduction' implicitly ha... Remove this comment to see the full error message
716
719
deployToProduction,
717
- // @ts -expect-error TS(7031) FIXME: Binding element 'options' implicitly has an 'any' ... Remove this comment to see the full error message
718
720
options,
719
- // @ts -expect-error TS(7031) FIXME: Binding element 'site' implicitly has an 'any' typ... Remove this comment to see the full error message
720
721
site,
721
- // @ts -expect-error TS(7031) FIXME: Binding element 'siteData' implicitly has an 'any'... Remove this comment to see the full error message
722
722
siteData,
723
- // @ts -expect-error TS(7031) FIXME: Binding element 'siteId' implicitly has an 'any' t... Remove this comment to see the full error message
724
723
siteId,
725
- // @ts -expect-error TS(7031) FIXME: Binding element 'workingDir' implicitly has an 'an... Remove this comment to see the full error message
726
724
workingDir,
725
+ } : {
726
+ options : DeployOptionValues
727
+ command : BaseCommand
728
+ workingDir : string
729
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- FIXME(serhalp)
730
+ [ key : string ] : any
727
731
} ) => {
728
732
const alias = options . alias || options . branch
729
733
// if a context is passed besides dev, we need to pull env vars from that specific context
@@ -747,13 +751,19 @@ const prepAndRunDeploy = async ({
747
751
await bundleEdgeFunctions ( options , command )
748
752
}
749
753
754
+ log ( '' )
755
+ // Note: this is leakily mimicking the @netlify /build heading style
756
+ log ( chalk . cyanBright . bold ( `Deploying to Netlify\n${ '─' . repeat ( 64 ) } ` ) )
757
+
758
+ log ( '' )
750
759
log (
751
760
prettyjson . render ( {
752
761
'Deploy path' : deployFolder ,
753
762
'Functions path' : functionsFolder ,
754
763
'Configuration path' : configPath ,
755
764
} ) ,
756
765
)
766
+ log ( )
757
767
758
768
const { functionsFolderStat } = await validateFolders ( {
759
769
deployFolder,
@@ -782,7 +792,7 @@ const prepAndRunDeploy = async ({
782
792
command,
783
793
config,
784
794
deployFolder,
785
- deployTimeout : options . timeout * SEC_TO_MILLISEC || DEFAULT_DEPLOY_TIMEOUT ,
795
+ deployTimeout : options . timeout ? options . timeout * SEC_TO_MILLISEC : DEFAULT_DEPLOY_TIMEOUT ,
786
796
deployToProduction,
787
797
functionsConfig,
788
798
// pass undefined functionsFolder if doesn't exist
@@ -893,11 +903,8 @@ export const deploy = async (options: DeployOptionValues, command: BaseCommand)
893
903
deployToProduction,
894
904
} )
895
905
}
896
- const isIntegrationDeploy = command . name ( ) === 'integration:deploy'
897
-
898
906
printResults ( {
899
907
runBuildCommand : options . build ,
900
- isIntegrationDeploy,
901
908
json : options . json ,
902
909
results,
903
910
deployToProduction,
0 commit comments