Skip to content

Commit 060ad12

Browse files
Merge pull request #16 from salesforcecli/sm/match-library-changes
fix: match library changes for deploy
2 parents e180b0d + 9e42923 commit 060ad12

File tree

5 files changed

+157
-549
lines changed

5 files changed

+157
-549
lines changed

package.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
"@oclif/config": "^1",
99
"@salesforce/command": "^3.1.0",
1010
"@salesforce/core": "^2.19.1",
11-
"@salesforce/source-deploy-retrieve": "^1.1.17",
11+
"@salesforce/source-deploy-retrieve": "^1.1.19",
1212
"chalk": "^4.1.0",
1313
"tslib": "^2"
1414
},
1515
"devDependencies": {
1616
"@oclif/dev-cli": "^1",
1717
"@oclif/plugin-command-snapshot": "^2.0.0",
18-
"@salesforce/dev-config": "^2.1.0",
1918
"@salesforce/cli-plugins-testkit": "^0.0.8",
19+
"@salesforce/dev-config": "^2.1.0",
2020
"@salesforce/dev-scripts": "^0.7.0",
2121
"@salesforce/plugin-command-reference": "^1.3.0",
2222
"@salesforce/prettier-config": "^0.0.2",
@@ -25,24 +25,24 @@
2525
"@typescript-eslint/parser": "^4.2.0",
2626
"chai": "^4.2.0",
2727
"cz-conventional-changelog": "^3.3.0",
28-
"eslint": "^7.20.0",
28+
"eslint": "^6.8.0",
2929
"eslint-config-prettier": "^6.11.0",
3030
"eslint-config-salesforce": "^0.1.0",
3131
"eslint-config-salesforce-license": "^0.1.0",
3232
"eslint-config-salesforce-typescript": "^0.2.0",
3333
"eslint-plugin-header": "^3.0.0",
3434
"eslint-plugin-import": "^2.20.2",
35-
"eslint-plugin-jsdoc": "^32.0.2",
35+
"eslint-plugin-jsdoc": "^27.0.3",
3636
"eslint-plugin-prettier": "^3.1.3",
3737
"husky": "^4.2.5",
3838
"lint-staged": "^10.2.2",
39-
"mocha": "^8.3.0",
39+
"mocha": "^7.2.0",
4040
"nyc": "^15.1.0",
4141
"prettier": "^2.0.5",
42-
"pretty-quick": "^3.1.0",
42+
"pretty-quick": "^2.0.1",
4343
"shx": "0.3.3",
4444
"sinon": "^9.0.2",
45-
"ts-node": "^9.1.1",
45+
"ts-node": "^8.10.2",
4646
"typescript": "^4.1.3"
4747
},
4848
"config": {

src/commands/force/source/deploy.ts

+51-60
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import * as os from 'os';
88
import * as path from 'path';
99
import { flags, FlagsConfig } from '@salesforce/command';
1010
import { Lifecycle, Messages } from '@salesforce/core';
11-
import { SourceDeployResult } from '@salesforce/source-deploy-retrieve';
11+
import { DeployResult } from '@salesforce/source-deploy-retrieve';
1212
import { Duration } from '@salesforce/kit';
1313
import { asString, asArray } from '@salesforce/ts-types';
1414
import * as chalk from 'chalk';
@@ -26,7 +26,6 @@ export class deploy extends SourceCommand {
2626
checkonly: flags.boolean({
2727
char: 'c',
2828
description: messages.getMessage('flags.checkonly'),
29-
default: false,
3029
}),
3130
wait: flags.minutes({
3231
char: 'w',
@@ -48,12 +47,10 @@ export class deploy extends SourceCommand {
4847
ignoreerrors: flags.boolean({
4948
char: 'o',
5049
description: messages.getMessage('flags.ignoreErrors'),
51-
default: false,
5250
}),
5351
ignorewarnings: flags.boolean({
5452
char: 'g',
5553
description: messages.getMessage('flags.ignoreWarnings'),
56-
default: false,
5754
}),
5855
validateddeployrequestid: flags.id({
5956
char: 'q',
@@ -90,7 +87,7 @@ export class deploy extends SourceCommand {
9087
};
9188
protected readonly lifecycleEventNames = ['predeploy', 'postdeploy'];
9289

93-
public async run(): Promise<SourceDeployResult> {
90+
public async run(): Promise<DeployResult> {
9491
if (this.flags.validatedeployrequestid) {
9592
// TODO: return this.doDeployRecentValidation();
9693
}
@@ -104,88 +101,82 @@ export class deploy extends SourceCommand {
104101

105102
await hookEmitter.emit('predeploy', { packageXmlPath: cs.getPackageXml() });
106103

107-
const results = await cs.deploy(this.org.getUsername(), {
108-
wait: (this.flags.wait as Duration).milliseconds,
109-
apiOptions: {
110-
// TODO: build out more api options
111-
checkOnly: this.flags.checkonly as boolean,
112-
ignoreWarnings: this.flags.ignorewarnings as boolean,
113-
runTests: this.flags.runtests as string[],
114-
},
115-
});
116-
104+
const results = await cs
105+
.deploy({
106+
usernameOrConnection: this.org.getUsername(),
107+
})
108+
.start();
117109
await hookEmitter.emit('postdeploy', results);
118110

119-
this.print(results);
111+
// skip a lot of steps that would do nothing
112+
if (!this.flags.json) {
113+
this.print(results);
114+
}
120115

121116
return results;
122117
}
123118

124-
private printComponentFailures(result: SourceDeployResult): void {
125-
if (result.status === 'Failed' && result.components) {
119+
private printComponentFailures(result: DeployResult): void {
120+
if (result.response.status === 'Failed' && result.components) {
126121
// sort by filename then fullname
127-
const failures = result.components.sort((i, j) => {
128-
if (i.component.type.directoryName === j.component.type.directoryName) {
122+
const failures = result.getFileResponses().sort((i, j) => {
123+
if (i.filePath === j.filePath) {
129124
// if the have the same directoryName then sort by fullName
130-
return i.component.fullName < j.component.fullName ? 1 : -1;
125+
return i.fullName < j.fullName ? 1 : -1;
131126
}
132-
return i.component.type.directoryName < j.component.type.directoryName ? 1 : -1;
127+
return i.filePath < j.filePath ? 1 : -1;
133128
});
134129
this.ux.log('');
135130
this.ux.styledHeader(chalk.red(`Component Failures [${failures.length}]`));
136131
this.ux.table(failures, {
137-
// TODO: these accessors are temporary until library JSON fixes
138132
columns: [
139-
{ key: 'component.type.name', label: 'Type' },
140-
{ key: 'diagnostics[0].filePath', label: 'File' },
141-
{ key: 'component.name', label: 'Name' },
142-
{ key: 'diagnostics[0].message', label: 'Problem' },
133+
{ key: 'componentType', label: 'Type' },
134+
{ key: 'fileName', label: 'File' },
135+
{ key: 'fullName', label: 'Name' },
136+
{ key: 'problem', label: 'Problem' },
143137
],
144138
});
145139
this.ux.log('');
146140
}
147141
}
148142

149-
private printComponentSuccess(result: SourceDeployResult): void {
150-
if (result.success && result.components) {
151-
if (result.components.length > 0) {
152-
// sort by type then filename then fullname
153-
const files = result.components.sort((i, j) => {
154-
if (i.component.type.name === j.component.type.name) {
155-
// same metadata type, according to above comment sort on filename
156-
if (i.component.type.directoryName === j.component.type.directoryName) {
157-
// same filename's according to comment sort by fullName
158-
return i.component.fullName < j.component.fullName ? 1 : -1;
159-
}
160-
return i.component.type.directoryName < j.component.type.directoryName ? 1 : -1;
143+
private printComponentSuccess(result: DeployResult): void {
144+
if (result.response.success && result.components?.size) {
145+
// sort by type then filename then fullname
146+
const files = result.getFileResponses().sort((i, j) => {
147+
if (i.fullName === j.fullName) {
148+
// same metadata type, according to above comment sort on filename
149+
if (i.filePath === j.filePath) {
150+
// same filename's according to comment sort by fullName
151+
return i.fullName < j.fullName ? 1 : -1;
161152
}
162-
return i.component.type.name < j.component.type.name ? 1 : -1;
163-
});
164-
// get relative path for table output
165-
files.forEach((file) => {
166-
if (file.component.content) {
167-
file.component.content = path.relative(process.cwd(), file.component.content);
168-
}
169-
});
170-
this.ux.log('');
171-
this.ux.styledHeader(chalk.blue('Deployed Source'));
172-
this.ux.table(files, {
173-
// TODO: these accessors are temporary until library JSON fixes
174-
columns: [
175-
{ key: 'component.name', label: 'FULL NAME' },
176-
{ key: 'component.type.name', label: 'TYPE' },
177-
{ key: 'component.content', label: 'PROJECT PATH' },
178-
],
179-
});
180-
}
153+
return i.filePath < j.filePath ? 1 : -1;
154+
}
155+
return i.type < j.type ? 1 : -1;
156+
});
157+
// get relative path for table output
158+
files.forEach((file) => {
159+
if (file.filePath) {
160+
file.filePath = path.relative(process.cwd(), file.filePath);
161+
}
162+
});
163+
this.ux.log('');
164+
this.ux.styledHeader(chalk.blue('Deployed Source'));
165+
this.ux.table(files, {
166+
columns: [
167+
{ key: 'fullName', label: 'FULL NAME' },
168+
{ key: 'type', label: 'TYPE' },
169+
{ key: 'filePath', label: 'PROJECT PATH' },
170+
],
171+
});
181172
}
182173
}
183174

184-
private print(result: SourceDeployResult): SourceDeployResult {
175+
private print(result: DeployResult): DeployResult {
185176
this.printComponentSuccess(result);
186177
this.printComponentFailures(result);
187178
// TODO: this.printTestResults(result); <- this has WI @W-8903671@
188-
if (result.success && this.flags.checkonly) {
179+
if (result.response.success && this.flags.checkonly) {
189180
this.log(messages.getMessage('checkOnlySuccess'));
190181
}
191182

src/commands/force/source/retrieve.ts

+33-27
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
77
import * as os from 'os';
8-
import * as path from 'path';
8+
99
import { flags, FlagsConfig } from '@salesforce/command';
1010
import { Lifecycle, Messages, SfdxError, SfdxProjectJson } from '@salesforce/core';
11-
import { SourceRetrieveResult } from '@salesforce/source-deploy-retrieve';
1211
import { Duration } from '@salesforce/kit';
1312
import { asArray, asString } from '@salesforce/ts-types';
14-
import { blue, yellow } from 'chalk';
13+
import { blue } from 'chalk';
14+
import { MetadataApiRetrieveStatus } from '@salesforce/source-deploy-retrieve';
15+
import { FileProperties } from '@salesforce/source-deploy-retrieve/lib/src/client/types';
1516
import { SourceCommand } from '../../../sourceCommand';
1617

1718
Messages.importMessagesDirectory(__dirname);
@@ -51,7 +52,8 @@ export class retrieve extends SourceCommand {
5152
};
5253
protected readonly lifecycleEventNames = ['preretrieve', 'postretrieve'];
5354

54-
public async run(): Promise<SourceRetrieveResult> {
55+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
56+
public async run(): Promise<any> {
5557
const hookEmitter = Lifecycle.getInstance();
5658

5759
const proj = await SfdxProjectJson.create({});
@@ -70,20 +72,27 @@ export class retrieve extends SourceCommand {
7072
// needs to be a path to the temp dir package.xml
7173
await hookEmitter.emit('preretrieve', { packageXmlPath: cs.getPackageXml() });
7274

73-
const results = await cs.retrieve(this.org.getUsername(), path.resolve(defaultPackage.path), {
74-
merge: true,
75-
// TODO: fix this once wait has been updated in library
76-
wait: (this.flags.wait as Duration).milliseconds,
77-
// TODO: implement retrieve via package name
78-
// package: options.packagenames
79-
});
75+
const mdapiResult = await cs
76+
.retrieve({
77+
usernameOrConnection: this.org.getUsername(),
78+
merge: true,
79+
output: (this.flags.sourcepath as string) ?? defaultPackage.path,
80+
packageNames: asArray<string>(this.flags.packagenames),
81+
})
82+
.start();
8083

84+
const results = mdapiResult.response;
8185
await hookEmitter.emit('postretrieve', results);
8286

8387
if (results.status === 'InProgress') {
8488
throw new SfdxError(messages.getMessage('retrieveTimeout', [(this.flags.wait as Duration).minutes]));
8589
}
86-
this.printTable(results, true);
90+
91+
if (this.flags.json) {
92+
this.ux.logJson(mdapiResult.getFileResponses());
93+
} else {
94+
this.printTable(results, true);
95+
}
8796

8897
return results;
8998
}
@@ -94,28 +103,25 @@ export class retrieve extends SourceCommand {
94103
* @param results what the .deploy or .retrieve method returns
95104
* @param withoutState a boolean to add state, default to true
96105
*/
97-
public printTable(results: SourceRetrieveResult, withoutState?: boolean): void {
98-
const stateCol = withoutState ? [] : [{ key: 'state', label: messages.getMessage('stateTableColumn') }];
106+
public printTable(results: MetadataApiRetrieveStatus, withoutState?: boolean): void {
107+
const stateCol = withoutState ? [] : [{ key: 'state', label: 'STATE' }];
99108

100109
this.ux.styledHeader(blue(messages.getMessage('retrievedSourceHeader')));
101-
if (results.success && results.successes.length) {
110+
if (results.success) {
102111
const columns = [
103-
{ key: 'properties.fullName', label: messages.getMessage('fullNameTableColumn') },
104-
{ key: 'properties.type', label: messages.getMessage('typeTableColumn') },
105-
{
106-
key: 'properties.fileName',
107-
label: messages.getMessage('workspacePathTableColumn'),
108-
},
112+
{ key: 'fullName', label: 'FULL NAME' },
113+
{ key: 'type', label: 'TYPE' },
114+
{ key: 'fileName', label: 'PROJECT PATH' },
109115
];
110-
this.ux.table(results.successes, { columns: [...stateCol, ...columns] });
116+
this.ux.table(results.fileProperties as FileProperties[], { columns: [...stateCol, ...columns] });
111117
} else {
112118
this.ux.log(messages.getMessage('NoResultsFound'));
113119
}
114120

115-
if (results.status === 'PartialSuccess' && results.successes.length && results.failures.length) {
116-
this.ux.log('');
117-
this.ux.styledHeader(yellow(messages.getMessage('metadataNotFoundWarning')));
118-
results.failures.forEach((warning) => this.ux.log(warning.message));
119-
}
121+
// if (results.status === 'SucceededPartial' && results.successes.length && results.failures.length) {
122+
// this.ux.log('');
123+
// this.ux.styledHeader(yellow(messages.getMessage('metadataNotFoundWarning')));
124+
// results.failures.forEach((warning) => this.ux.log(warning.message));
125+
// }
120126
}
121127
}

src/sourceCommand.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ export abstract class SourceCommand extends SfdxCommand {
4242
}
4343

4444
if (options.packagenames) {
45-
// retrieve only
46-
// TODO: @W-8908888@
45+
// return ComponentSet and use packageNames in the library via `.retrieve` options
46+
setAggregator.push(...new ComponentSet([]));
4747
}
4848

4949
if (options.manifest) {

0 commit comments

Comments
 (0)