Skip to content

Commit 6b85325

Browse files
authored
Merge pull request #314 from salesforcecli/phale/W-11253606
fix: display error found in individual deploys
2 parents e820114 + 803a4cd commit 6b85325

File tree

6 files changed

+2069
-1884
lines changed

6 files changed

+2069
-1884
lines changed

messages/deploy.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,39 @@ Initialization Failures. The following table describes each failure:
4444
# warning.TargetOrgIsExpired
4545

4646
The target-org, "%s", is expired. Do you want to pick another org?
47+
48+
# AnalyzingProject
49+
50+
Analyzing project
51+
52+
# UsingOptionsFromFile
53+
54+
Using options found in %s.
55+
56+
# FoundNothingToDeploy
57+
58+
Found nothing in the project to deploy.
59+
60+
# NothingSelectedToDeploy
61+
62+
Nothing was selected to deploy.
63+
64+
# DeployOptionsSavedToFile
65+
66+
Your deploy options have been saved to %s.
67+
68+
# DeployOptionsIncludedInGitIgnore
69+
70+
We added %s to the .gitignore for you.
71+
72+
# DeployersHaveNonZeroExitCode
73+
74+
One or more of the selected deployers exited with a non-zero exit code.
75+
76+
# DeployerExitCode
77+
78+
Deployer "%s" exited with code %d.
79+
80+
# save.as.default
81+
82+
Save username %s as default?

package.json

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,43 @@
55
"author": "Salesforce",
66
"bugs": "https://github.com/forcedotcom/cli/issues",
77
"dependencies": {
8-
"@oclif/core": "^1.9.0",
9-
"@salesforce/core": "^3.22.1",
10-
"@salesforce/kit": "^1.5.41",
11-
"@salesforce/sf-plugins-core": "^1.13.0",
12-
"@salesforce/source-deploy-retrieve": "^6.1.0",
13-
"@salesforce/source-tracking": "^2.2.0",
8+
"@oclif/core": "^1.13.10",
9+
"@salesforce/core": "^3.26.1",
10+
"@salesforce/kit": "^1.5.45",
11+
"@salesforce/sf-plugins-core": "1.13.2",
12+
"@salesforce/source-deploy-retrieve": "^6.2.9",
13+
"@salesforce/source-tracking": "^2.2.2",
1414
"chalk": "^4.1.2",
1515
"fs-extra": "^10.0.1",
1616
"shelljs": "^0.8.5",
1717
"tslib": "^2"
1818
},
1919
"devDependencies": {
2020
"@oclif/plugin-command-snapshot": "^3.1.3",
21-
"@salesforce/cli-plugins-testkit": "^2.3.0",
22-
"@salesforce/dev-config": "^3.0.1",
23-
"@salesforce/dev-scripts": "^2.0.1",
21+
"@salesforce/cli-plugins-testkit": "^2.3.10",
22+
"@salesforce/dev-config": "^3.1.0",
23+
"@salesforce/dev-scripts": "^2.0.4",
2424
"@salesforce/plugin-command-reference": "^2.2.8",
2525
"@salesforce/plugin-config": "^2.3.0",
26-
"@salesforce/plugin-functions": "^1.7.0",
27-
"@salesforce/plugin-source": "^2.0.3",
28-
"@salesforce/plugin-user": "^2.0.2",
26+
"@salesforce/plugin-functions": "^1.13.4",
27+
"@salesforce/plugin-source": "^2.0.11",
28+
"@salesforce/plugin-user": "^2.1.0",
2929
"@salesforce/prettier-config": "^0.0.2",
3030
"@salesforce/source-testkit": "^1.2.0",
3131
"@salesforce/ts-sinon": "1.3.21",
32+
"@salesforce/ts-types": "^1.5.20",
3233
"@types/archiver": "^5.3.1",
3334
"@types/fs-extra": "^9.0.13",
3435
"@types/shelljs": "^0.8.11",
35-
"@typescript-eslint/eslint-plugin": "^5.27.1",
36-
"@typescript-eslint/parser": "^5.27.1",
36+
"@typescript-eslint/eslint-plugin": "^5.32.0",
37+
"@typescript-eslint/parser": "^5.32.0",
3738
"archiver": "^5.3.1",
3839
"chai": "^4.3.6",
3940
"cross-env": "^7.0.3",
4041
"cz-conventional-changelog": "^3.3.0",
4142
"eslint": "^8.17.0",
4243
"eslint-config-prettier": "^6.15.0",
43-
"eslint-config-salesforce": "^1.0.1",
44+
"eslint-config-salesforce": "^1.1.0",
4445
"eslint-config-salesforce-license": "^0.1.6",
4546
"eslint-config-salesforce-typescript": "^1.0.0",
4647
"eslint-plugin-header": "^3.1.1",
@@ -50,20 +51,20 @@
5051
"eslint-plugin-sf-plugin": "^0.3.0",
5152
"husky": "^7.0.4",
5253
"lint-staged": "^11.2.6",
53-
"mocha": "^9.1.3",
54+
"mocha": "^10.0.0",
5455
"nyc": "^15.1.0",
55-
"oclif": "^2.6.3",
56-
"prettier": "^2.5.1",
56+
"oclif": "^3.1.2",
57+
"prettier": "^2.7.1",
5758
"pretty-quick": "^3.1.3",
5859
"salesforcedx-templates": "^49.8.0",
5960
"shx": "0.3.4",
6061
"sinon": "11.1.2",
61-
"ts-node": "^10.7.0",
62-
"typescript": "^4.6.2"
62+
"ts-node": "^10.9.1",
63+
"typescript": "^4.7.4"
6364
},
6465
"resolutions": {
65-
"@oclif/core": "^1.6.4",
66-
"@salesforce/sf-plugins-core": "^1.11.0"
66+
"@oclif/core": "1.13.10",
67+
"@salesforce/sf-plugins-core": "1.13.2"
6768
},
6869
"config": {
6970
"commitizen": {

src/commands/deploy.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { writeJson, pathExists, writeFile, readFile } from 'fs-extra';
1313
import { Env, parseJsonMap } from '@salesforce/kit';
1414
import { Deployable, Deployer, generateTableChoices, Prompter, SfCommand, SfHook } from '@salesforce/sf-plugins-core';
1515
import { exec } from 'shelljs';
16+
import { DeployerResult } from '@salesforce/sf-plugins-core/lib/deployer';
1617

1718
Messages.importMessagesDirectory(__dirname);
1819

@@ -24,13 +25,13 @@ export default class Deploy extends SfCommand<void> {
2425
public static summary = messages.getMessage('summary');
2526
public static description = messages.getMessage('description');
2627
public static examples = messages.getMessages('examples');
27-
public static enableJsonFlag = false;
2828

2929
public static flags = {
3030
interactive: Flags.boolean({
3131
summary: messages.getMessage('flags.interactive.summary'),
3232
}),
3333
};
34+
public static enableJsonFlag = false;
3435

3536
public async run(): Promise<void> {
3637
process.setMaxListeners(new Env().getNumber('SF_MAX_EVENT_LISTENERS') || 1000);
@@ -39,10 +40,10 @@ export default class Deploy extends SfCommand<void> {
3940
flags.interactive = await this.isInteractive(flags.interactive);
4041
const options = await this.readOptions();
4142

42-
this.log('Analyzing project');
43+
this.log(messages.getMessage('AnalyzingProject'));
4344

4445
if (!flags.interactive) {
45-
this.log(`Using options found in ${DEPLOY_OPTIONS_FILE}`);
46+
this.log(messages.getMessage('UsingOptionsFromFile', [DEPLOY_OPTIONS_FILE]));
4647
}
4748

4849
const hookResults = await SfHook.run(this.config, 'sf:deploy', options);
@@ -52,7 +53,7 @@ export default class Deploy extends SfCommand<void> {
5253
let deployers = hookResults.successes.flatMap((s) => s.result);
5354

5455
if (deployers.length === 0) {
55-
this.log('Found nothing in the project to deploy');
56+
this.log(messages.getMessage('FoundNothingToDeploy'));
5657
} else {
5758
if (flags.interactive) {
5859
deployers = await this.selectDeployers(deployers);
@@ -61,7 +62,7 @@ export default class Deploy extends SfCommand<void> {
6162
}
6263

6364
if (deployers.length === 0) {
64-
this.log('Nothing was selected to deploy.');
65+
this.log(messages.getMessage('NothingSelectedToDeploy'));
6566
}
6667

6768
const deployOptions: Record<string, Deployer.Options> = {};
@@ -75,17 +76,29 @@ export default class Deploy extends SfCommand<void> {
7576
if (flags.interactive && (await this.askToSave())) {
7677
await writeJson(DEPLOY_OPTIONS_FILE, deployOptions);
7778
this.log();
78-
this.log(`Your deploy options have been saved to ${DEPLOY_OPTIONS_FILE}`);
79+
this.log(messages.getMessage('DeployOptionsSavedToFile', [DEPLOY_OPTIONS_FILE]));
7980
if (await this.shouldCommit()) {
8081
await this.commit();
81-
this.log(`We added ${DEPLOY_OPTIONS_FILE} to the .gitignore for you.`);
82+
this.log(messages.getMessage('DeployOptionsIncludedInGitIgnore', [DEPLOY_OPTIONS_FILE]));
8283
}
8384
}
8485

86+
const deployResults: Array<[Deployer, void | DeployerResult]> = [];
8587
for (const deployer of deployers) {
8688
// deployments must be done sequentially?
8789
// eslint-disable-next-line no-await-in-loop
88-
await deployer.deploy();
90+
deployResults.push([deployer, await deployer.deploy()]);
91+
}
92+
if (deployResults.some(([, result]) => !!result && result.exitCode !== 0)) {
93+
process.exitCode = 1;
94+
this.warn(messages.getMessage('DeployersHaveNonZeroExitCode'));
95+
deployResults
96+
.filter(([, result]) => !!result && result.exitCode !== 0)
97+
.forEach(([deployer, result]) => {
98+
this.log(
99+
messages.getMessage('DeployerExitCode', [deployer.getName(), result ? result.exitCode : 'unknown'])
100+
);
101+
});
89102
}
90103
}
91104
}

src/utils/metadataDeployer.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ import {
1818
OrgAuthorization,
1919
OrgConfigProperties,
2020
} from '@salesforce/core';
21-
import { Deployable, Deployer, generateTableChoices } from '@salesforce/sf-plugins-core';
21+
import { Deployable, Deployer, DeployerResult, generateTableChoices } from '@salesforce/sf-plugins-core';
2222

2323
import { DeployResultFormatter } from './output';
2424
import { TestLevel } from './types';
2525
import { DeployProgress } from './progressBar';
26-
import { executeDeploy, resolveApi } from './deploy';
26+
import { determineExitCode, executeDeploy, resolveApi } from './deploy';
2727

2828
Messages.importMessagesDirectory(__dirname);
2929
const messages = Messages.loadMessages('@salesforce/plugin-deploy-retrieve', 'deploy');
@@ -120,7 +120,7 @@ export class MetadataDeployer extends Deployer {
120120
};
121121
}
122122

123-
public async deploy(): Promise<void> {
123+
public async deploy<R extends DeployerResult>(): Promise<void | R> {
124124
const directories = this.deployables.map((d) => d.pkg.fullPath);
125125
const name = this.deployables.map((p) => cyan.bold(p.getPath())).join(', ');
126126
const api = await resolveApi();
@@ -136,12 +136,17 @@ export class MetadataDeployer extends Deployer {
136136
new DeployProgress(deploy).start();
137137

138138
const result = await deploy.pollStatus(500, Duration.minutes(33).seconds);
139+
139140
const formatter = new DeployResultFormatter(result, {
140141
'test-level': this.testLevel,
141142
verbose: false,
142143
concise: false,
143144
});
144145
formatter.display();
146+
const deployerResult: DeployerResult = {
147+
exitCode: determineExitCode(result),
148+
};
149+
return deployerResult as R;
145150
}
146151

147152
public async promptForUsername(): Promise<string> {

src/utils/output.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ export class DeployResultFormatter implements Formatter<DeployResultJson> {
162162
private displaySuccesses(): void {
163163
const successes = this.relativeFiles.filter((f) => f.state !== 'Failed');
164164

165-
if (!successes.length) return;
165+
if (!successes.length || this.result.response.status === RequestStatus.Failed) return;
166166

167167
const columns = {
168168
state: { header: 'State' },

0 commit comments

Comments
 (0)