44 * Licensed under the BSD 3-Clause license.
55 * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66 */
7-
8- import ansis from 'ansis' ;
97import { EnvironmentVariable , Lifecycle , Messages , OrgConfigProperties , SfError } from '@salesforce/core' ;
108import { type DeployVersionData , DeployZipData } from '@salesforce/source-deploy-retrieve' ;
119import { Duration } from '@salesforce/kit' ;
1210import { SfCommand , toHelpSection , Flags } from '@salesforce/sf-plugins-core' ;
1311import { SourceConflictError } from '@salesforce/source-tracking' ;
12+ import { DeployStages } from '../../../utils/deployStages.js' ;
1413import { AsyncDeployResultFormatter } from '../../../formatters/asyncDeployResultFormatter.js' ;
1514import { DeployResultFormatter } from '../../../formatters/deployResultFormatter.js' ;
1615import { AsyncDeployResultJson , DeployResultJson , TestLevel } from '../../../utils/types.js' ;
17- import { DeployProgress } from '../../../utils/progressBar.js' ;
1816import { executeDeploy , resolveApi , validateTests , determineExitCode } from '../../../utils/deploy.js' ;
1917import { DeployCache } from '../../../utils/deployCache.js' ;
2018import { DEPLOY_STATUS_CODES_DESCRIPTIONS } from '../../../utils/errorCodes.js' ;
@@ -177,6 +175,8 @@ export default class DeployMetadata extends SfCommand<DeployResultJson> {
177175
178176 public static errorCodes = toHelpSection ( 'ERROR CODES' , DEPLOY_STATUS_CODES_DESCRIPTIONS ) ;
179177
178+ protected stages ! : DeployStages ;
179+
180180 private zipSize ?: number ;
181181 private zipFileCount ?: number ;
182182
@@ -201,33 +201,47 @@ export default class DeployMetadata extends SfCommand<DeployResultJson> {
201201
202202 const api = await resolveApi ( this . configAggregator ) ;
203203 const username = flags [ 'target-org' ] . getUsername ( ) ;
204- const action = flags [ 'dry-run' ] ? 'Deploying (dry-run)' : 'Deploying' ;
204+ const title = flags [ 'dry-run' ] ? 'Deploying Metadata (dry-run)' : 'Deploying Metadata ' ;
205205
206- // eslint-disable-next-line @typescript-eslint/require-await
207- Lifecycle . getInstance ( ) . on ( 'apiVersionDeploy' , async ( apiData : DeployVersionData ) => {
208- this . log (
209- messages . getMessage ( 'apiVersionMsgDetailed' , [
210- action ,
211- // technically manifestVersion can be undefined, but only on raw mdapi deployments.
212- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
213- flags [ 'metadata-dir' ] ? '<version specified in manifest>' : `v${ apiData . manifestVersion } ` ,
214- username ,
215- apiData . apiVersion ,
216- apiData . webService ,
217- ] )
218- ) ;
206+ this . stages = new DeployStages ( {
207+ title,
208+ jsonEnabled : this . jsonEnabled ( ) ,
219209 } ) ;
220-
210+ const lifecycle = Lifecycle . getInstance ( ) ;
221211 // eslint-disable-next-line @typescript-eslint/require-await
222- Lifecycle . getInstance ( ) . on ( 'deployZipData' , async ( zipData : DeployZipData ) => {
212+ lifecycle . on ( 'deployZipData' , async ( zipData : DeployZipData ) => {
223213 this . zipSize = zipData . zipSize ;
224- if ( flags . verbose && this . zipSize ) this . log ( `Deploy size: ${ getZipFileSize ( this . zipSize ) } of ~39 MB limit` ) ;
214+ if ( flags . verbose && this . zipSize ) {
215+ this . stages . update ( {
216+ deploySize : `${ getZipFileSize ( this . zipSize ) } of ~39 MB limit` ,
217+ } ) ;
218+ }
225219 if ( zipData . zipFileCount ) {
226220 this . zipFileCount = zipData . zipFileCount ;
227- if ( flags . verbose && this . zipSize ) this . log ( `Deployed files count: ${ this . zipFileCount } of 10,000 limit` ) ;
221+ if ( flags . verbose && this . zipSize ) {
222+ this . stages . update ( {
223+ deployFileCount : `${ this . zipFileCount } of 10,000 limit` ,
224+ } ) ;
225+ }
228226 }
229227 } ) ;
230228
229+ lifecycle . on ( 'apiVersionDeploy' , async ( apiData : DeployVersionData ) =>
230+ Promise . resolve (
231+ this . stages . update ( {
232+ message : messages . getMessage ( 'apiVersionMsgDetailed' , [
233+ flags [ 'dry-run' ] ? 'Deploying (dry-run)' : 'Deploying' ,
234+ // technically manifestVersion can be undefined, but only on raw mdapi deployments.
235+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
236+ flags [ 'metadata-dir' ] ? '<version specified in manifest>' : `v${ apiData . manifestVersion } ` ,
237+ username ,
238+ apiData . apiVersion ,
239+ apiData . webService ,
240+ ] ) ,
241+ } )
242+ )
243+ ) ;
244+
231245 const { deploy } = await executeDeploy (
232246 {
233247 ...flags ,
@@ -238,16 +252,20 @@ export default class DeployMetadata extends SfCommand<DeployResultJson> {
238252 ) ;
239253
240254 if ( ! deploy ) {
255+ this . stages . stop ( ) ;
241256 this . log ( 'No changes to deploy' ) ;
242257 return { status : 'Nothing to deploy' , files : [ ] } ;
243258 }
244259
245260 if ( ! deploy . id ) {
246261 throw new SfError ( 'The deploy id is not available.' ) ;
247262 }
248- this . log ( `Deploy ID: ${ ansis . bold ( deploy . id ) } ` ) ;
263+
264+ this . stages . start ( { username, deploy } ) ;
249265
250266 if ( flags . async ) {
267+ this . stages . done ( { status : 'Queued' , username } ) ;
268+ this . stages . stop ( ) ;
251269 if ( flags [ 'coverage-formatters' ] ) {
252270 this . warn ( messages . getMessage ( 'asyncCoverageJunitWarning' ) ) ;
253271 }
@@ -257,8 +275,6 @@ export default class DeployMetadata extends SfCommand<DeployResultJson> {
257275 return this . mixinZipMeta ( await asyncFormatter . getJson ( ) ) ;
258276 }
259277
260- new DeployProgress ( deploy , this . jsonEnabled ( ) ) . start ( ) ;
261-
262278 const result = await deploy . pollStatus ( { timeout : flags . wait } ) ;
263279 process . exitCode = determineExitCode ( result ) ;
264280 const formatter = new DeployResultFormatter ( result , flags ) ;
@@ -276,6 +292,8 @@ export default class DeployMetadata extends SfCommand<DeployResultJson> {
276292 protected catch ( error : Error | SfError ) : Promise < never > {
277293 if ( error instanceof SourceConflictError && error . data ) {
278294 if ( ! this . jsonEnabled ( ) ) {
295+ this . stages . update ( { status : 'Failed' } ) ;
296+ this . stages . stop ( error ) ;
279297 writeConflictTable ( error . data ) ;
280298 // set the message and add plugin-specific actions
281299 return super . catch ( {
0 commit comments