Skip to content

Commit e7d7215

Browse files
shetzelWillieRuemmelemaggibenSF-CLI-BOTdependabot[bot]
authored
feat: add support for async deploys (#89)
* feat: add support for async deploys * feat: use async SDR in source plugin * fix: fixes and refactors result output Fixes result output for retrieve. Combines common sorting and relative file path conversion. Fixes sorting. * refactor: refactor for SDR changes * chore: add rest to deploy options - needs SDR publish (#108) * chore: deploy NUTs (#84) * chore: deploy NUTs * chore: disable other NUTs * chore: make test:nuts test all nuts * chore: reduce number of redundant tests * chore: move from nutshell to source-teskit (#85) * chore: move from nutshell to source-teskit * chore: try deploy NUTs * chore: undo try deploy NUTs * chore: try new way to find package.xml * chore: undo find package xml * chore: bump testkit to 0.0.5 * chore: don't throw if cleanup fails * chore: parallelize NUTs, add wildcard option to retrieve * chore: add logging when cleanup fails * chore: update convert, NUTs to use genUniqueDir: false (#88) * chore: update convert, NUTs to use genUniqueDir: false * chore: add large executor to windows * chore: add findAndMove manifest back * chore: fix convert NUT output dir * chore: try new approach * chore: remove .github/autointegrator.yml (#80) Authored via Leif * Update README.md @W-9260305@ * chore(release): 0.0.17 [ci skip] * chore(deps-dev): bump @typescript-eslint/parser from 4.24.0 to 4.26.0 (#90) * chore(deps-dev): bump @typescript-eslint/parser from 4.24.0 to 4.26.0 Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.24.0 to 4.26.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.26.0/packages/parser) Signed-off-by: dependabot[bot] <[email protected]> * chore(deps-dev): bump sinon from 9.2.4 to 11.1.1 Bumps [sinon](https://github.com/sinonjs/sinon) from 9.2.4 to 11.1.1. - [Release notes](https://github.com/sinonjs/sinon/releases) - [Changelog](https://github.com/sinonjs/sinon/blob/master/CHANGELOG.md) - [Commits](sinonjs/sinon@v9.2.4...v11.1.1) Signed-off-by: dependabot[bot] <[email protected]> * chore(deps-dev): bump @typescript-eslint/eslint-plugin Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.24.0 to 4.26.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.26.0/packages/eslint-plugin) Signed-off-by: dependabot[bot] <[email protected]> * chore: update yarn.lock * chore: pin sinon to v10.0.0 Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Peter Hale <[email protected]> * chore: dependabot combined changes (#105) * chore: bump dep versions # Conflicts: # package.json * chore: bump dev-scripts # Conflicts: # yarn.lock * chore: update yarn lock * chore(deps-dev): bump @oclif/plugin-command-snapshot from 2.0.0 to 2.1.2 (#106) Bumps [@oclif/plugin-command-snapshot](https://github.com/oclif/plugin-command-snapshot) from 2.0.0 to 2.1.2. - [Release notes](https://github.com/oclif/plugin-command-snapshot/releases) - [Changelog](https://github.com/oclif/plugin-command-snapshot/blob/master/CHANGELOG.md) - [Commits](oclif/plugin-command-snapshot@v2.0.0...v2.1.2) --- updated-dependencies: - dependency-name: "@oclif/plugin-command-snapshot" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore: add rest to deploy options - needs SDR publish * chore: default to SOAP Co-authored-by: Benjamin <[email protected]> Co-authored-by: Steve Hetzel <[email protected]> Co-authored-by: SF-CLI-BOT <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Peter Hale <[email protected]> Co-authored-by: peternhale <[email protected]> * fix: change the frequency to match deploy * refactor: bump retrieve frequency to 1 second * chore: enable async NUTs, logic for different deploy states when cancelling/reporting Co-authored-by: Willie Ruemmele <[email protected]> Co-authored-by: Benjamin <[email protected]> Co-authored-by: SF-CLI-BOT <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Peter Hale <[email protected]> Co-authored-by: peternhale <[email protected]>
1 parent 664a00a commit e7d7215

22 files changed

+389
-222
lines changed

README.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ sfdx plugins
7575
# Usage
7676

7777
<!-- usage -->
78+
7879
```sh-session
7980
$ npm install -g @salesforce/plugin-source
8081
$ sfdx COMMAND
@@ -86,16 +87,18 @@ USAGE
8687
$ sfdx COMMAND
8788
...
8889
```
90+
8991
<!-- usagestop -->
9092

9193
# Commands
9294

9395
<!-- commands -->
94-
* [`sfdx force:source:convert [-r <directory>] [-d <directory>] [-n <string>] [-p <array> | -x <string> | -m <array>] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-forcesourceconvert--r-directory--d-directory--n-string--p-array---x-string---m-array---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal)
95-
* [`sfdx force:source:deploy [--soapdeploy] [-w <minutes>] [-q <id> | -x <filepath> | -m <array> | -p <array> | -c | -l NoTestRun|RunSpecifiedTests|RunLocalTests|RunAllTestsInOrg | -r <array> | -o | -g] [-u <string>] [--apiversion <string>] [--verbose] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-forcesourcedeploy---soapdeploy--w-minutes--q-id---x-filepath---m-array---p-array---c---l-notestrunrunspecifiedtestsrunlocaltestsrunalltestsinorg---r-array---o---g--u-string---apiversion-string---verbose---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal)
96-
* [`sfdx force:source:deploy:cancel [-w <minutes>] [-i <id>] [-u <string>] [--apiversion <string>] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-forcesourcedeploycancel--w-minutes--i-id--u-string---apiversion-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal)
97-
* [`sfdx force:source:deploy:report [-w <minutes>] [-i <id>] [-u <string>] [--apiversion <string>] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-forcesourcedeployreport--w-minutes--i-id--u-string---apiversion-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal)
98-
* [`sfdx force:source:retrieve [-p <array> | -x <filepath> | -m <array>] [-w <minutes>] [-n <array>] [-u <string>] [-a <string>] [--verbose] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-forcesourceretrieve--p-array---x-filepath---m-array--w-minutes--n-array--u-string--a-string---verbose---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal)
96+
97+
- [`sfdx force:source:convert [-r <directory>] [-d <directory>] [-n <string>] [-p <array> | -x <string> | -m <array>] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-forcesourceconvert--r-directory--d-directory--n-string--p-array---x-string---m-array---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal)
98+
- [`sfdx force:source:deploy [--soapdeploy] [-w <minutes>] [-q <id> | -x <filepath> | -m <array> | -p <array> | -c | -l NoTestRun|RunSpecifiedTests|RunLocalTests|RunAllTestsInOrg | -r <array> | -o | -g] [-u <string>] [--apiversion <string>] [--verbose] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-forcesourcedeploy---soapdeploy--w-minutes--q-id---x-filepath---m-array---p-array---c---l-notestrunrunspecifiedtestsrunlocaltestsrunalltestsinorg---r-array---o---g--u-string---apiversion-string---verbose---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal)
99+
- [`sfdx force:source:deploy:cancel [-w <minutes>] [-i <id>] [-u <string>] [--apiversion <string>] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-forcesourcedeploycancel--w-minutes--i-id--u-string---apiversion-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal)
100+
- [`sfdx force:source:deploy:report [-w <minutes>] [-i <id>] [-u <string>] [--apiversion <string>] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-forcesourcedeployreport--w-minutes--i-id--u-string---apiversion-string---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal)
101+
- [`sfdx force:source:retrieve [-p <array> | -x <filepath> | -m <array>] [-w <minutes>] [-n <array>] [-u <string>] [-a <string>] [--verbose] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`](#sfdx-forcesourceretrieve--p-array---x-filepath---m-array--w-minutes--n-array--u-string--a-string---verbose---json---loglevel-tracedebuginfowarnerrorfataltracedebuginfowarnerrorfatal)
99102

100103
## `sfdx force:source:convert [-r <directory>] [-d <directory>] [-n <string>] [-p <array> | -x <string> | -m <array>] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]`
101104

@@ -105,7 +108,7 @@ convert source into Metadata API format
105108
convert source into Metadata API format
106109
107110
USAGE
108-
$ sfdx force:source:convert [-r <directory>] [-d <directory>] [-n <string>] [-p <array> | -x <string> | -m <array>]
111+
$ sfdx force:source:convert [-r <directory>] [-d <directory>] [-n <string>] [-p <array> | -x <string> | -m <array>]
109112
[--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
110113
111114
OPTIONS
@@ -148,8 +151,8 @@ deploy source to an org
148151
deploy source to an org
149152
150153
USAGE
151-
$ sfdx force:source:deploy [--soapdeploy] [-w <minutes>] [-q <id> | -x <filepath> | -m <array> | -p <array> | -c | -l
152-
NoTestRun|RunSpecifiedTests|RunLocalTests|RunAllTestsInOrg | -r <array> | -o | -g] [-u <string>] [--apiversion
154+
$ sfdx force:source:deploy [--soapdeploy] [-w <minutes>] [-q <id> | -x <filepath> | -m <array> | -p <array> | -c | -l
155+
NoTestRun|RunSpecifiedTests|RunLocalTests|RunAllTestsInOrg | -r <array> | -o | -g] [-u <string>] [--apiversion
153156
<string>] [--verbose] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
154157
155158
OPTIONS
@@ -223,7 +226,7 @@ cancel a source deployment
223226
cancel a source deployment
224227
225228
USAGE
226-
$ sfdx force:source:deploy:cancel [-w <minutes>] [-i <id>] [-u <string>] [--apiversion <string>] [--json] [--loglevel
229+
$ sfdx force:source:deploy:cancel [-w <minutes>] [-i <id>] [-u <string>] [--apiversion <string>] [--json] [--loglevel
227230
trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
228231
229232
OPTIONS
@@ -261,7 +264,7 @@ check the status of a metadata deployment
261264
check the status of a metadata deployment
262265
263266
USAGE
264-
$ sfdx force:source:deploy:report [-w <minutes>] [-i <id>] [-u <string>] [--apiversion <string>] [--json] [--loglevel
267+
$ sfdx force:source:deploy:report [-w <minutes>] [-i <id>] [-u <string>] [--apiversion <string>] [--json] [--loglevel
265268
trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
266269
267270
OPTIONS
@@ -304,7 +307,7 @@ retrieve source from an org
304307
retrieve source from an org
305308
306309
USAGE
307-
$ sfdx force:source:retrieve [-p <array> | -x <filepath> | -m <array>] [-w <minutes>] [-n <array>] [-u <string>] [-a
310+
$ sfdx force:source:retrieve [-p <array> | -x <filepath> | -m <array>] [-w <minutes>] [-n <array>] [-u <string>] [-a
308311
<string>] [--verbose] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
309312
310313
OPTIONS
@@ -350,4 +353,5 @@ EXAMPLES
350353
```
351354

352355
_See code: [src/commands/force/source/retrieve.ts](https://github.com/salesforcecli/plugin-source/blob/v0.0.18/src/commands/force/source/retrieve.ts)_
356+
353357
<!-- commandsstop -->

command-snapshot.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
{
3535
"command": "force:source:deploy:report",
3636
"plugin": "@salesforce/plugin-source",
37-
"flags": ["apiversion", "jobid", "json", "loglevel", "targetusername", "wait"]
37+
"flags": ["apiversion", "jobid", "json", "loglevel", "targetusername", "wait", "verbose"]
3838
},
3939
{
4040
"command": "force:source:retrieve",

messages/deploy.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,8 @@
3030
"checkOnlySuccess": "Successfully validated the deployment. %s components deployed and %s tests run.\nUse the --verbose parameter to see detailed output.",
3131
"MissingDeployId": "No deploy ID was provided or found in deploy history",
3232
"deployCanceled": "The deployment has been canceled by %s",
33-
"deployFailed": "Deploy failed."
33+
"deployFailed": "Deploy failed.",
34+
"asyncDeployQueued": "Deploy has been queued.",
35+
"asyncDeployCancel": "Run sfdx force:source:deploy:cancel -i %s to cancel the deploy.",
36+
"asyncDeployReport": "Run sfdx force:source:deploy:report -i %s to get the latest status."
3437
}

messages/report.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
],
1414
"flags": {
1515
"jobid": "job ID of the deployment you want to check; defaults to your most recent CLI deployment if not specified",
16-
"wait": "wait time for command to finish in minutes"
16+
"wait": "wait time for command to finish in minutes",
17+
"verbose": "verbose output of deploy result"
1718
}
1819
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"name": "@salesforce/plugin-source",
33
"description": "Commands to interact with source formatted metadata",
4-
"version": "0.0.19",
4+
"version": "0.1.19",
55
"author": "Salesforce",
66
"bugs": "https://github.com/forcedotcom/cli/issues",
77
"dependencies": {
88
"@oclif/config": "^1",
99
"@salesforce/command": "^3.1.3",
1010
"@salesforce/core": "^2.23.4",
11-
"@salesforce/source-deploy-retrieve": "^2.1.5",
11+
"@salesforce/source-deploy-retrieve": "^3.0.0",
1212
"chalk": "^4.1.0",
1313
"cli-ux": "^5.5.1",
1414
"tslib": "^2"

src/commands/force/source/convert.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export class Convert extends SourceCommand {
8080
paths.push(this.project.getDefaultPackage().path);
8181
}
8282

83-
const cs = await ComponentSetBuilder.build({
83+
this.componentSet = await ComponentSetBuilder.build({
8484
sourcepath: paths,
8585
manifest: manifest && {
8686
manifestPath: this.getFlag<string>('manifest'),
@@ -93,7 +93,7 @@ export class Convert extends SourceCommand {
9393
});
9494

9595
const converter = new MetadataConverter();
96-
this.convertResult = await converter.convert(cs.getSourceComponents().toArray(), 'metadata', {
96+
this.convertResult = await converter.convert(this.componentSet.getSourceComponents().toArray(), 'metadata', {
9797
type: 'directory',
9898
outputDirectory: this.getFlag<string>('outputdir'),
9999
packageName: this.getFlag<string>('packagename'),

src/commands/force/source/deploy.ts

Lines changed: 60 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,15 @@
88
import * as os from 'os';
99
import { flags, FlagsConfig } from '@salesforce/command';
1010
import { Messages } from '@salesforce/core';
11-
import { DeployResult, MetadataApiDeploy } from '@salesforce/source-deploy-retrieve';
11+
import { AsyncResult, DeployResult, MetadataApiDeploy } from '@salesforce/source-deploy-retrieve';
1212
import { Duration } from '@salesforce/kit';
1313
import { getString, isString } from '@salesforce/ts-types';
14-
import { env } from '@salesforce/kit';
14+
import { env, once } from '@salesforce/kit';
1515
import { RequestStatus } from '@salesforce/source-deploy-retrieve/lib/src/client/types';
1616
import { DeployCommand } from '../../../deployCommand';
1717
import { ComponentSetBuilder } from '../../../componentSetBuilder';
18-
import {
19-
DeployResultFormatter,
20-
DeployCommandResult,
21-
DeployCommandAsyncResult,
22-
} from '../../../formatters/deployResultFormatter';
18+
import { DeployResultFormatter, DeployCommandResult } from '../../../formatters/deployResultFormatter';
19+
import { DeployAsyncResultFormatter, DeployCommandAsyncResult } from '../../../formatters/deployAsyncResultFormatter';
2320

2421
Messages.importMessagesDirectory(__dirname);
2522
const messages = Messages.loadMessages('@salesforce/plugin-source', 'deploy');
@@ -102,6 +99,12 @@ export class Deploy extends DeployCommand {
10299

103100
private isAsync = false;
104101
private isRest = false;
102+
private asyncDeployResult: AsyncResult;
103+
104+
private updateDeployId = once((id) => {
105+
this.displayDeployId(id);
106+
this.setStash(id);
107+
});
105108

106109
public async run(): Promise<DeployCommandResult | DeployCommandAsyncResult> {
107110
await this.deploy();
@@ -114,15 +117,15 @@ export class Deploy extends DeployCommand {
114117
// 2. asynchronous - deploy metadata and immediately return.
115118
// 3. recent validation - deploy metadata that's already been validated by the org
116119
protected async deploy(): Promise<void> {
117-
this.isAsync = this.getFlag<Duration>('wait').quantity === 0;
120+
const waitDuration = this.getFlag<Duration>('wait');
121+
this.isAsync = waitDuration.quantity === 0;
118122
this.isRest = await this.isRestDeploy();
119123
this.ux.log(`*** Deploying with ${this.isRest ? 'REST' : 'SOAP'} API ***`);
120124

121125
if (this.flags.validateddeployrequestid) {
122126
this.deployResult = await this.deployRecentValidation();
123127
} else {
124-
// the deployment involves a component set
125-
const cs = await ComponentSetBuilder.build({
128+
this.componentSet = await ComponentSetBuilder.build({
126129
apiversion: this.getFlag<string>('apiversion'),
127130
sourcepath: this.getFlag<string[]>('sourcepath'),
128131
manifest: this.flags.manifest && {
@@ -135,57 +138,63 @@ export class Deploy extends DeployCommand {
135138
},
136139
});
137140
// fire predeploy event for sync and async deploys
138-
await this.lifecycle.emit('predeploy', cs.toArray());
139-
if (this.isAsync) {
140-
// This is an async deploy. We just kick off the request.
141-
throw Error('ASYNC DEPLOYS NOT IMPLEMENTED YET');
142-
} else {
143-
const deploy = cs.deploy({
144-
usernameOrConnection: this.org.getUsername(),
145-
apiOptions: {
146-
ignoreWarnings: this.getFlag<boolean>('ignorewarnings', false),
147-
rollbackOnError: !this.getFlag<boolean>('ignoreerrors', false),
148-
checkOnly: this.getFlag<boolean>('checkonly', false),
149-
runTests: this.getFlag<string[]>('runtests'),
150-
testLevel: this.getFlag<TestLevel>('testlevel', 'NoTestRun'),
151-
},
152-
});
141+
await this.lifecycle.emit('predeploy', this.componentSet.toArray());
153142

143+
const deploy = await this.componentSet.deploy({
144+
usernameOrConnection: this.org.getUsername(),
145+
apiOptions: {
146+
ignoreWarnings: this.getFlag<boolean>('ignorewarnings', false),
147+
rollbackOnError: !this.getFlag<boolean>('ignoreerrors', false),
148+
checkOnly: this.getFlag<boolean>('checkonly', false),
149+
runTests: this.getFlag<string[]>('runtests'),
150+
testLevel: this.getFlag<TestLevel>('testlevel'),
151+
rest: this.isRest,
152+
},
153+
});
154+
this.asyncDeployResult = { id: deploy.id };
155+
this.updateDeployId(deploy.id);
156+
157+
if (!this.isAsync) {
154158
// if SFDX_USE_PROGRESS_BAR is unset or true (default true) AND we're not print JSON output
155159
if (env.getBoolean('SFDX_USE_PROGRESS_BAR', true) && !this.isJsonOutput()) {
156160
this.initProgressBar();
157161
this.progress(deploy);
158162
}
159-
160-
this.deployResult = await deploy.start();
163+
this.deployResult = await deploy.pollStatus(500, waitDuration.seconds);
161164
}
162165
}
163166

164-
await this.lifecycle.emit('postdeploy', this.deployResult);
165-
166-
const deployId = getString(this.deployResult, 'response.id');
167-
if (deployId) {
168-
this.displayDeployId(deployId);
169-
const file = this.getStash();
170-
// TODO: I think we should stash the ID as soon as we know it.
171-
this.logger.debug(`Stashing deploy ID: ${deployId}`);
172-
await file.write({ [DeployCommand.STASH_KEY]: { jobid: deployId } });
167+
if (this.deployResult) {
168+
// Only fire the postdeploy event when we have results. I.e., not async.
169+
await this.lifecycle.emit('postdeploy', this.deployResult);
173170
}
174171
}
175172

173+
/**
174+
* Checks the response status to determine whether the deploy was successful.
175+
* Async deploys are successful unless an error is thrown, which resolves as
176+
* unsuccessful in oclif.
177+
*/
176178
protected resolveSuccess(): void {
177-
const status = getString(this.deployResult, 'response.status');
178-
if (status !== RequestStatus.Succeeded) {
179-
this.setExitCode(1);
179+
if (!this.isAsync) {
180+
const status = getString(this.deployResult, 'response.status');
181+
if (status !== RequestStatus.Succeeded) {
182+
this.setExitCode(1);
183+
}
180184
}
181185
}
182186

183187
protected formatResult(): DeployCommandResult | DeployCommandAsyncResult {
184188
const formatterOptions = {
185189
verbose: this.getFlag<boolean>('verbose', false),
186-
async: this.isAsync,
187190
};
188-
const formatter = new DeployResultFormatter(this.logger, this.ux, formatterOptions, this.deployResult);
191+
192+
let formatter: DeployAsyncResultFormatter | DeployResultFormatter;
193+
if (this.isAsync) {
194+
formatter = new DeployAsyncResultFormatter(this.logger, this.ux, formatterOptions, this.asyncDeployResult);
195+
} else {
196+
formatter = new DeployResultFormatter(this.logger, this.ux, formatterOptions, this.deployResult);
197+
}
189198

190199
// Only display results to console when JSON flag is unset.
191200
if (!this.isJsonOutput()) {
@@ -199,15 +208,8 @@ export class Deploy extends DeployCommand {
199208
const conn = this.org.getConnection();
200209
const id = this.getFlag<string>('validateddeployrequestid');
201210

202-
// TODO: This is an async call so we need to poll unless `--wait 0`
203-
// See mdapiCheckStatusApi.ts for the toolbelt polling impl.
204211
const response = await conn.deployRecentValidation({ id, rest: this.isRest });
205212

206-
if (!this.isAsync) {
207-
// Remove this and add polling if we need to poll in the plugin.
208-
throw Error('deployRecentValidation polling not yet implemented');
209-
}
210-
211213
// This is the deploy ID of the deployRecentValidation response, not
212214
// the already validated deploy ID (i.e., validateddeployrequestid).
213215
let validatedDeployId: string;
@@ -218,26 +220,27 @@ export class Deploy extends DeployCommand {
218220
// REST API
219221
validatedDeployId = (response as { id: string }).id;
220222
}
223+
this.updateDeployId(validatedDeployId);
221224

222-
return this.report(validatedDeployId);
225+
return this.isAsync ? this.report(validatedDeployId) : this.poll(validatedDeployId);
223226
}
224227

225228
private progress(deploy: MetadataApiDeploy): void {
226-
let started = false;
229+
const startProgressBar = once((componentTotal: number) => {
230+
this.progressBar.start(componentTotal);
231+
});
232+
227233
deploy.onUpdate((data) => {
228234
// the numCompTot. isn't computed right away, wait to start until we know how many we have
229-
if (data.numberComponentsTotal && !started) {
230-
this.displayDeployId(data.id);
231-
this.progressBar.start(data.numberComponentsTotal + data.numberTestsTotal);
232-
started = true;
235+
if (data.numberComponentsTotal) {
236+
startProgressBar(data.numberComponentsTotal + data.numberTestsTotal);
237+
this.progressBar.update(data.numberComponentsDeployed + data.numberTestsCompleted);
233238
}
234239

235240
// the numTestsTot. isn't computed until validated as tests by the server, update the PB once we know
236-
if (data.numberTestsTotal) {
241+
if (data.numberTestsTotal && data.numberComponentsTotal) {
237242
this.progressBar.setTotal(data.numberComponentsTotal + data.numberTestsTotal);
238243
}
239-
240-
this.progressBar.update(data.numberComponentsDeployed + data.numberTestsCompleted);
241244
});
242245

243246
// any thing else should stop the progress bar

0 commit comments

Comments
 (0)