Skip to content

Commit 8bc0797

Browse files
mshanemcshetzel
andauthored
Sm/status-codes (#265)
* feat: detailed status codes for deploy/retrieve * feat: spinners for retrieve statuses * refactor: partial success is success * test: ut adds and bugs from tests * test: remove only * feat: better no results message for status * fix: avoid undefined for push api version message * feat: status code per command * fix: zero is falsy, so ?? instead of || * refactor: no getString * fix: handle warning-only "failures" * chore: repo cleanup * refactor: demote and defer isRest * fix: don't modify tracking when no deployResult * chore: bump sdr/stl * refactor: shared logic for display api versions * fix: deploy message only runs after CS, not validateddeployrequestid Co-authored-by: Steve Hetzel <[email protected]>
1 parent c8f878e commit 8bc0797

22 files changed

+312
-141
lines changed

.images/vscodeScreenshot.png

-364 KB
Binary file not shown.

.vscode/launch.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"request": "attach",
1010
"name": "Attach",
1111
"port": 9229,
12-
"skipFiles": ["<node_internals>/**"]
12+
"skipFiles": ["<node_internals>/**"],
13+
"continueOnAttach": true
1314
},
1415
{
1516
"name": "Run All Tests",

CHANGELOG.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,21 @@ All notable changes to this project will be documented in this file. See [standa
44

55
## [1.4.0](https://github.com/salesforcecli/plugin-source/compare/v1.3.1...v1.4.0) (2021-11-09)
66

7-
87
### Features
98

10-
* listmetadata and describemetadata ([b00a59a](https://github.com/salesforcecli/plugin-source/commit/b00a59a3c06cd81b121c306b6b9af3ee581a61ad))
9+
- listmetadata and describemetadata ([b00a59a](https://github.com/salesforcecli/plugin-source/commit/b00a59a3c06cd81b121c306b6b9af3ee581a61ad))
1110

1211
### [1.3.1](https://github.com/salesforcecli/plugin-source/compare/v1.3.0...v1.3.1) (2021-10-28)
1312

14-
1513
### Bug Fixes
1614

17-
* bump SDR to 5.1.1 ([#266](https://github.com/salesforcecli/plugin-source/issues/266)) ([ff6a4f7](https://github.com/salesforcecli/plugin-source/commit/ff6a4f74401668faec6404f941ce5cf73da426ff))
15+
- bump SDR to 5.1.1 ([#266](https://github.com/salesforcecli/plugin-source/issues/266)) ([ff6a4f7](https://github.com/salesforcecli/plugin-source/commit/ff6a4f74401668faec6404f941ce5cf73da426ff))
1816

1917
## [1.3.0](https://github.com/salesforcecli/plugin-source/compare/v1.2.6...v1.3.0) (2021-10-28)
2018

21-
2219
### Features
2320

24-
* source tracking beta commands ([b871774](https://github.com/salesforcecli/plugin-source/commit/b87177498c184580db7e3bd81f164ddc77e6de0b)), closes [#253](https://github.com/salesforcecli/plugin-source/issues/253) [#251](https://github.com/salesforcecli/plugin-source/issues/251) [#230](https://github.com/salesforcecli/plugin-source/issues/230) [#260](https://github.com/salesforcecli/plugin-source/issues/260) [#259](https://github.com/salesforcecli/plugin-source/issues/259)
21+
- source tracking beta commands ([b871774](https://github.com/salesforcecli/plugin-source/commit/b87177498c184580db7e3bd81f164ddc77e6de0b)), closes [#253](https://github.com/salesforcecli/plugin-source/issues/253) [#251](https://github.com/salesforcecli/plugin-source/issues/251) [#230](https://github.com/salesforcecli/plugin-source/issues/230) [#260](https://github.com/salesforcecli/plugin-source/issues/260) [#259](https://github.com/salesforcecli/plugin-source/issues/259)
2522

2623
### [1.2.6](https://github.com/salesforcecli/plugin-source/compare/v1.2.5...v1.2.6) (2021-10-21)
2724

README.md

Lines changed: 79 additions & 75 deletions
Large diffs are not rendered by default.

messages/retrieve.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,10 @@
4747
"columnNumberColumn": "COLUMN NUMBER",
4848
"lineNumberColumn": "LINE NUMBER",
4949
"errorColumn": "PROBLEM",
50-
"wantsToRetrieveCustomFields": "Because you're retrieving one or more CustomFields, we're also retrieving the CustomObject to which it's associated."
50+
"wantsToRetrieveCustomFields": "Because you're retrieving one or more CustomFields, we're also retrieving the CustomObject to which it's associated.",
51+
"spinnerMessages": {
52+
"componentSetBuild": "Preparing retrieve request",
53+
"sendingRequest": "Sending request to org (metadata API version %s)",
54+
"polling": "Waiting for the org to respond"
55+
}
5156
}

messages/status.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
"remote": "list the changes that have been made in the scratch org",
1616
"remoteLong": "Lists the changes that have been made in the scratch org."
1717
},
18-
"humanSuccess": "Source Status"
18+
"humanSuccess": "Source Status",
19+
"noResults": "No local or remote changes found."
1920
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
"@oclif/config": "^1",
99
"@salesforce/command": "^4.1.3",
1010
"@salesforce/core": "^2.28.0",
11-
"@salesforce/source-deploy-retrieve": "^5.1.1",
12-
"@salesforce/source-tracking": "^0.4.1",
11+
"@salesforce/source-deploy-retrieve": "^5.3.0",
12+
"@salesforce/source-tracking": "^0.4.2",
1313
"chalk": "^4.1.2",
1414
"cli-ux": "^5.6.3",
1515
"open": "^8.2.1",

src/commands/force/source/beta/pull.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,17 @@ export default class Pull extends SourceCommand {
156156
}
157157

158158
protected resolveSuccess(): void {
159+
const StatusCodeMap = new Map<RequestStatus, number>([
160+
[RequestStatus.Succeeded, 0],
161+
[RequestStatus.Canceled, 1],
162+
[RequestStatus.Failed, 1],
163+
[RequestStatus.InProgress, 69],
164+
[RequestStatus.Pending, 69],
165+
[RequestStatus.Canceling, 69],
166+
]);
159167
// there might not be a retrieveResult if we don't have anything to retrieve
160-
if (this.retrieveResult && this.retrieveResult.response.status !== RequestStatus.Succeeded) {
161-
this.setExitCode(1);
168+
if (this.retrieveResult && this.retrieveResult.response.status) {
169+
this.setExitCode(StatusCodeMap.get(this.retrieveResult.response.status) ?? 1);
162170
}
163171
}
164172

src/commands/force/source/beta/push.ts

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { Messages } from '@salesforce/core';
1111
import { RequestStatus, ComponentStatus } from '@salesforce/source-deploy-retrieve';
1212

1313
import { SourceTracking, throwIfInvalid, replaceRenamedCommands } from '@salesforce/source-tracking';
14-
import { DeployCommand } from '../../../../deployCommand';
14+
import { DeployCommand, getVersionMessage } from '../../../../deployCommand';
1515
import { PushResponse, PushResultFormatter } from '../../../../formatters/pushResultFormatter';
1616
import { ProgressFormatter } from '../../../../formatters/progressFormatter';
1717
import { DeployProgressBarFormatter } from '../../../../formatters/deployProgressBarFormatter';
@@ -51,11 +51,12 @@ export default class Push extends DeployCommand {
5151
protected static requiresProject = true;
5252
protected readonly lifecycleEventNames = ['predeploy', 'postdeploy'];
5353

54-
private isRest = false;
54+
private tracking: SourceTracking;
5555

5656
public async run(): Promise<PushResponse[]> {
5757
await this.deploy();
5858
this.resolveSuccess();
59+
await this.updateTrackingFiles();
5960
return this.formatResult();
6061
}
6162

@@ -66,19 +67,20 @@ export default class Push extends DeployCommand {
6667
toValidate: 'plugin-source',
6768
command: replaceRenamedCommands('force:source:push'),
6869
});
69-
const waitDuration = this.getFlag<Duration>('wait');
70-
this.isRest = await this.isRestDeploy();
7170

72-
const tracking = await SourceTracking.create({
71+
this.tracking = await SourceTracking.create({
7372
org: this.org,
7473
project: this.project,
7574
apiVersion: this.flags.apiversion as string,
7675
});
7776
if (!this.flags.forceoverwrite) {
78-
processConflicts(await tracking.getConflicts(), this.ux, messages.getMessage('conflictMsg'));
77+
processConflicts(await this.tracking.getConflicts(), this.ux, messages.getMessage('conflictMsg'));
78+
}
79+
const componentSet = await this.tracking.localChangesAsComponentSet();
80+
const sourceApiVersion = await this.getSourceApiVersion();
81+
if (sourceApiVersion) {
82+
componentSet.sourceApiVersion = sourceApiVersion;
7983
}
80-
const componentSet = await tracking.localChangesAsComponentSet();
81-
componentSet.sourceApiVersion = await this.getSourceApiVersion();
8284

8385
// there might have been components in local tracking, but they might be ignored by SDR or unresolvable.
8486
// SDR will throw when you try to resolve them, so don't
@@ -89,13 +91,15 @@ export default class Push extends DeployCommand {
8991

9092
// fire predeploy event for sync and async deploys
9193
await this.lifecycle.emit('predeploy', componentSet.toArray());
92-
this.ux.log(`*** Pushing with ${this.isRest ? 'REST' : 'SOAP'} API v${componentSet.sourceApiVersion} ***`);
94+
95+
const isRest = await this.isRestDeploy();
96+
this.ux.log(getVersionMessage('Pushing', componentSet, isRest));
9397

9498
const deploy = await componentSet.deploy({
9599
usernameOrConnection: this.org.getUsername(),
96100
apiOptions: {
97101
ignoreWarnings: this.getFlag<boolean>('ignorewarnings', false),
98-
rest: this.isRest,
102+
rest: isRest,
99103
testLevel: 'NoTestRun',
100104
},
101105
});
@@ -107,32 +111,52 @@ export default class Push extends DeployCommand {
107111
: new DeployProgressStatusFormatter(this.logger, this.ux);
108112
progressFormatter.progress(deploy);
109113
}
110-
this.deployResult = await deploy.pollStatus(500, waitDuration.seconds);
114+
this.deployResult = await deploy.pollStatus(500, this.getFlag<Duration>('wait').seconds);
115+
116+
if (this.deployResult) {
117+
// Only fire the postdeploy event when we have results. I.e., not async.
118+
await this.lifecycle.emit('postdeploy', this.deployResult);
119+
}
120+
}
111121

122+
protected async updateTrackingFiles(): Promise<void> {
123+
if (process.exitCode !== 0 || !this.deployResult) {
124+
return;
125+
}
112126
const successes = this.deployResult
113127
.getFileResponses()
114128
.filter((fileResponse) => fileResponse.state !== ComponentStatus.Failed);
115129
const successNonDeletes = successes.filter((fileResponse) => fileResponse.state !== ComponentStatus.Deleted);
116130
const successDeletes = successes.filter((fileResponse) => fileResponse.state === ComponentStatus.Deleted);
117131

118-
if (this.deployResult) {
119-
// Only fire the postdeploy event when we have results. I.e., not async.
120-
await this.lifecycle.emit('postdeploy', this.deployResult);
121-
}
122-
123132
await Promise.all([
124-
tracking.updateLocalTracking({
133+
this.tracking.updateLocalTracking({
125134
files: successNonDeletes.map((fileResponse) => fileResponse.filePath),
126135
deletedFiles: successDeletes.map((fileResponse) => fileResponse.filePath),
127136
}),
128-
tracking.updateRemoteTracking(successes),
137+
this.tracking.updateRemoteTracking(successes),
129138
]);
130139
}
131140

132141
protected resolveSuccess(): void {
142+
const StatusCodeMap = new Map<RequestStatus, number>([
143+
[RequestStatus.Succeeded, 0],
144+
[RequestStatus.Canceled, 1],
145+
[RequestStatus.Failed, 1],
146+
[RequestStatus.InProgress, 69],
147+
[RequestStatus.Pending, 69],
148+
[RequestStatus.Canceling, 69],
149+
]);
133150
// there might not be a deployResult if we exited early with an empty componentSet
134-
if (this.deployResult && this.deployResult.response.status !== RequestStatus.Succeeded) {
135-
this.setExitCode(1);
151+
if (this.deployResult && this.deployResult.response.status) {
152+
this.setExitCode(StatusCodeMap.get(this.deployResult.response.status) ?? 1);
153+
// special override case for "only warnings about deleted things that are already deleted"
154+
if (
155+
this.deployResult.response.status === RequestStatus.Failed &&
156+
this.deployResult.getFileResponses().every((fr) => fr.state !== 'Failed')
157+
) {
158+
this.setExitCode(0);
159+
}
136160
}
137161
}
138162

src/commands/force/source/deploy.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import { flags, FlagsConfig } from '@salesforce/command';
99
import { Messages } from '@salesforce/core';
1010
import { AsyncResult, DeployResult, RequestStatus } from '@salesforce/source-deploy-retrieve';
1111
import { Duration, env, once } from '@salesforce/kit';
12-
import { getString, isString } from '@salesforce/ts-types';
13-
import { DeployCommand } from '../../../deployCommand';
12+
import { isString } from '@salesforce/ts-types';
13+
import { DeployCommand, getVersionMessage } from '../../../deployCommand';
1414
import { ComponentSetBuilder } from '../../../componentSetBuilder';
1515
import { DeployCommandResult, DeployResultFormatter } from '../../../formatters/deployResultFormatter';
1616
import { DeployAsyncResultFormatter, DeployCommandAsyncResult } from '../../../formatters/deployAsyncResultFormatter';
@@ -144,7 +144,6 @@ export class Deploy extends DeployCommand {
144144
const waitDuration = this.getFlag<Duration>('wait');
145145
this.isAsync = waitDuration.quantity === 0;
146146
this.isRest = await this.isRestDeploy();
147-
this.ux.log(`*** Deploying with ${this.isRest ? 'REST' : 'SOAP'} API ***`);
148147

149148
if (this.flags.validateddeployrequestid) {
150149
this.deployResult = await this.deployRecentValidation();
@@ -166,6 +165,7 @@ export class Deploy extends DeployCommand {
166165
});
167166
// fire predeploy event for sync and async deploys
168167
await this.lifecycle.emit('predeploy', this.componentSet.toArray());
168+
this.ux.log(getVersionMessage('Deploying', this.componentSet, this.isRest));
169169

170170
const deploy = await this.componentSet.deploy({
171171
usernameOrConnection: this.org.getUsername(),
@@ -205,11 +205,17 @@ export class Deploy extends DeployCommand {
205205
* unsuccessful in oclif.
206206
*/
207207
protected resolveSuccess(): void {
208+
const StatusCodeMap = new Map<RequestStatus, number>([
209+
[RequestStatus.Succeeded, 0],
210+
[RequestStatus.Canceled, 1],
211+
[RequestStatus.Failed, 1],
212+
[RequestStatus.SucceededPartial, 68],
213+
[RequestStatus.InProgress, 69],
214+
[RequestStatus.Pending, 69],
215+
[RequestStatus.Canceling, 69],
216+
]);
208217
if (!this.isAsync) {
209-
const status = getString(this.deployResult, 'response.status');
210-
if (status !== RequestStatus.Succeeded) {
211-
this.setExitCode(1);
212-
}
218+
this.setExitCode(StatusCodeMap.get(this.deployResult.response?.status) ?? 1);
213219
}
214220
}
215221

0 commit comments

Comments
 (0)