Skip to content

Commit d01a155

Browse files
mdonnalleymshanemc
andauthored
Metadata format deploys (#245)
* feat: support metadata format deploys * chore: regenerate yarn.lock * chore: update snapshot * chore: add NUTs * chore: add file * ci: exclude windows maintenance * fix: correctly resume deployments * fix: dont remove completed deploys from cache * fix: handle 15 char ids and bump SDR * chore: update nuts * chore: fix tests * chore: fix cancel nut Co-authored-by: mshanemc <[email protected]>
1 parent 29a166d commit d01a155

File tree

19 files changed

+332
-84
lines changed

19 files changed

+332
-84
lines changed

.circleci/config.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ workflows:
5151
- latest
5252
- lts
5353
- maintenance
54+
exclude:
55+
- os: windows
56+
node_version: maintenance
5457
- release-management/test-nut:
5558
context:
5659
- na40-auth-url
@@ -65,6 +68,7 @@ workflows:
6568
command:
6669
[
6770
'yarn test:nuts:deploy:metadata:manifest',
71+
'yarn test:nuts:deploy:metadata:metadata-dir',
6872
'yarn test:nuts:deploy:metadata:metadata',
6973
'yarn test:nuts:deploy:metadata:source-dir',
7074
'yarn test:nuts:deploy:metadata:test-level',

command-snapshot.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
"json",
2121
"manifest",
2222
"metadata",
23+
"metadata-dir",
24+
"single-package",
2325
"source-dir",
2426
"target-org",
2527
"test-level",
@@ -89,6 +91,8 @@
8991
"json",
9092
"manifest",
9193
"metadata",
94+
"metadata-dir",
95+
"single-package",
9296
"source-dir",
9397
"target-org",
9498
"test-level",

messages/deploy.metadata.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@ Run the command asynchronously.
154154

155155
The command immediately returns the job ID and control of the terminal to you. This way, you can continue to use the CLI. To resume the deployment, run "sf deploy metadata resume". To check the status of the deployment, run "sf deploy metadata report".
156156

157+
# flags.metadata-dir.summary
158+
159+
Root of directory or zip file of metadata formatted files to deploy.
160+
161+
# flags.single-package.summary
162+
163+
Indicates that the metadata zip file points to a directory structure for a single package.
164+
157165
# save.as.default
158166

159167
Save %s as default target-org?

messages/deploy.metadata.resume.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,7 @@ Show verbose output of the deploy operation result.
5656
# flags.concise.summary
5757

5858
Show concise output of the deploy operation result.
59+
60+
# error.DeployNotResumable
61+
62+
Job ID %s is not resumable with status %s.

messages/deploy.metadata.validate.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ To validate the deployment of multiple metadata components, either set multiple
1414

1515
# examples
1616

17-
- NOTE: These examples focus on validating large deployments. See the help for "sf deploy metadata" for examples of deploying smaller sets of metadata which you can also use to validate.
17+
- NOTE: These examples focus on validating large deployments. See the help for "sf deploy metadata" for examples of deploying smaller sets of metadata which you can also use to validate.
1818

1919
- Validate the deployment of all source files in a directory to the default org:
2020

@@ -53,9 +53,9 @@ Valid values are:
5353
- RunLocalTests — All tests in your org are run, except the ones that originate from installed managed and unlocked packages. This test level is the default for production deployments that include Apex classes or triggers.
5454

5555
- RunAllTestsInOrg — All tests in your org are run, including tests of managed packages.
56-
56+
5757
If you don’t specify a test level, the default behavior depends on the contents of your deployment package. For more information, see [Running Tests in a Deployment](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_deploy_running_tests.htm) in the "Metadata API Developer Guide".
58-
58+
5959
# flags.source-dir.summary
6060

6161
Path to the local source files to validate for deployment.
@@ -114,6 +114,14 @@ Run the command asynchronously.
114114

115115
The command immediately returns the job ID and control of the terminal to you. This way, you can continue to use the CLI. To resume watching the validation, run "sf deploy metadata resume". To check the status of the validation, run "sf deploy metadata report".
116116

117+
# flags.metadata-dir.summary
118+
119+
Root of directory or zip file of metadata formatted files to deploy.
120+
121+
# flags.single-package.summary
122+
123+
Indicates that the metadata zip file points to a directory structure for a single package.
124+
117125
# info.SuccessfulValidation
118126

119127
Successfully validated the deployment (%s).

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"@salesforce/core": "^3.15.5",
1010
"@salesforce/kit": "^1.5.41",
1111
"@salesforce/sf-plugins-core": "^1.12.3",
12-
"@salesforce/source-deploy-retrieve": "^5.12.4",
12+
"@salesforce/source-deploy-retrieve": "^5.13.1",
1313
"chalk": "^4.1.2",
1414
"fs-extra": "^10.0.1",
1515
"shelljs": "^0.8.5",
@@ -28,10 +28,12 @@
2828
"@salesforce/prettier-config": "^0.0.2",
2929
"@salesforce/source-testkit": "^0.0.18",
3030
"@salesforce/ts-sinon": "1.3.21",
31+
"@types/archiver": "^5.3.1",
3132
"@types/fs-extra": "^9.0.13",
3233
"@types/shelljs": "^0.8.11",
3334
"@typescript-eslint/eslint-plugin": "^4.33.0",
3435
"@typescript-eslint/parser": "^4.33.0",
36+
"archiver": "^5.3.1",
3537
"chai": "^4.3.6",
3638
"cross-env": "^7.0.3",
3739
"cz-conventional-changelog": "^3.3.0",
@@ -138,6 +140,7 @@
138140
"test:json-schema": "./bin/dev schema:compare",
139141
"test:nuts": "ts-node ./test/nuts/generateNuts.ts && nyc mocha \"**/*.nut.ts\" --slow 4500 --timeout 600000 --parallel --retries 0",
140142
"test:nuts:deploy:metadata:manifest": "cross-env PLUGIN_DEPLOY_RETRIEVE_SEED_FILTER=deploy.metadata.manifest ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 600000 --parallel --retries 0",
143+
"test:nuts:deploy:metadata:metadata-dir": "cross-env PLUGIN_DEPLOY_RETRIEVE_SEED_FILTER=deploy.metadata.metadata-dir ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 600000 --parallel --retries 0",
141144
"test:nuts:deploy:metadata:metadata": "cross-env PLUGIN_DEPLOY_RETRIEVE_SEED_FILTER=deploy.metadata.metadata ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 600000 --parallel --retries 0",
142145
"test:nuts:deploy:metadata:source-dir": "cross-env PLUGIN_DEPLOY_RETRIEVE_SEED_FILTER=deploy.metadata.source-dir ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 600000 --parallel --retries 0",
143146
"test:nuts:deploy:metadata:test-level": "cross-env PLUGIN_DEPLOY_RETRIEVE_SEED_FILTER=deploy.metadata.test-level ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 600000 --parallel --retries 0",

src/commands/deploy/metadata.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,16 @@ import { SfCommand, toHelpSection, Flags } from '@salesforce/sf-plugins-core';
1111
import { AsyncDeployResultFormatter, DeployResultFormatter, getVersionMessage } from '../../utils/output';
1212
import { DeployProgress } from '../../utils/progressBar';
1313
import { DeployResultJson, TestLevel } from '../../utils/types';
14-
import {
15-
executeDeploy,
16-
testLevelFlag,
17-
resolveApi,
18-
validateTests,
19-
determineExitCode,
20-
DeployCache,
21-
shouldRemoveFromCache,
22-
} from '../../utils/deploy';
14+
import { executeDeploy, resolveApi, validateTests, determineExitCode, DeployCache } from '../../utils/deploy';
2315
import { DEPLOY_STATUS_CODES_DESCRIPTIONS } from '../../utils/errorCodes';
2416
import { ConfigVars } from '../../configMeta';
17+
import { fileOrDirFlag, testLevelFlag } from '../../utils/flags';
2518

2619
Messages.importMessagesDirectory(__dirname);
2720
const messages = Messages.loadMessages('@salesforce/plugin-deploy-retrieve', 'deploy.metadata');
2821

22+
const EXACTLY_ONE_FLAGS = ['manifest', 'source-dir', 'metadata', 'metadata-dir'];
23+
2924
export default class DeployMetadata extends SfCommand<DeployResultJson> {
3025
public static readonly description = messages.getMessage('description');
3126
public static readonly summary = messages.getMessage('summary');
@@ -68,21 +63,30 @@ export default class DeployMetadata extends SfCommand<DeployResultJson> {
6863
char: 'x',
6964
description: messages.getMessage('flags.manifest.description'),
7065
summary: messages.getMessage('flags.manifest.summary'),
71-
exactlyOne: ['manifest', 'source-dir', 'metadata'],
66+
exactlyOne: EXACTLY_ONE_FLAGS,
7267
exists: true,
7368
}),
7469
metadata: Flags.string({
7570
char: 'm',
7671
summary: messages.getMessage('flags.metadata.summary'),
7772
multiple: true,
78-
exactlyOne: ['manifest', 'source-dir', 'metadata'],
73+
exactlyOne: EXACTLY_ONE_FLAGS,
74+
}),
75+
'metadata-dir': fileOrDirFlag({
76+
summary: messages.getMessage('flags.metadata-dir.summary'),
77+
exactlyOne: EXACTLY_ONE_FLAGS,
78+
exists: true,
79+
}),
80+
'single-package': Flags.boolean({
81+
summary: messages.getMessage('flags.single-package.summary'),
82+
dependsOn: ['metadata-dir'],
7983
}),
8084
'source-dir': Flags.string({
8185
char: 'd',
8286
description: messages.getMessage('flags.source-dir.description'),
8387
summary: messages.getMessage('flags.source-dir.summary'),
8488
multiple: true,
85-
exactlyOne: ['manifest', 'source-dir', 'metadata'],
89+
exactlyOne: EXACTLY_ONE_FLAGS,
8690
}),
8791
'target-org': Flags.requiredOrg({
8892
char: 'o',
@@ -166,9 +170,7 @@ export default class DeployMetadata extends SfCommand<DeployResultJson> {
166170
if (flags['dry-run']) this.logSuccess('Dry-run complete.');
167171
}
168172

169-
if (shouldRemoveFromCache(result.response.status)) {
170-
await DeployCache.unset(deploy.id);
171-
}
173+
await DeployCache.update(deploy.id, { status: result.response.status });
172174

173175
return formatter.getJson();
174176
}

src/commands/deploy/metadata/cancel.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import { Messages } from '@salesforce/core';
99
import { Duration } from '@salesforce/kit';
1010
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
11-
import { DeployCache, cancelDeploy, shouldRemoveFromCache, cancelDeployAsync } from '../../../utils/deploy';
11+
import { DeployCache, cancelDeploy, cancelDeployAsync } from '../../../utils/deploy';
1212
import { AsyncDeployCancelResultFormatter, DeployCancelResultFormatter } from '../../../utils/output';
1313
import { DeployResultJson } from '../../../utils/types';
1414

@@ -70,11 +70,9 @@ export default class DeployMetadataCancel extends SfCommand<DeployResultJson> {
7070
const formatter = new DeployCancelResultFormatter(result);
7171
if (!this.jsonEnabled()) formatter.display();
7272

73-
if (shouldRemoveFromCache(result.response.status)) {
74-
cache.unset(result.response.id);
75-
cache.unset(jobId);
76-
await cache.write();
77-
}
73+
cache.update(result.response.id, { status: result.response.status });
74+
await cache.write();
75+
7876
return formatter.getJson();
7977
}
8078
}

src/commands/deploy/metadata/quick.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {
1616
determineExitCode,
1717
poll,
1818
resolveApi,
19-
shouldRemoveFromCache,
2019
} from '../../../utils/deploy';
2120
import { DEPLOY_STATUS_CODES_DESCRIPTIONS } from '../../../utils/errorCodes';
2221
import { AsyncDeployResultFormatter, DeployResultFormatter, getVersionMessage } from '../../../utils/output';
@@ -106,9 +105,7 @@ export default class DeployMetadataQuick extends SfCommand<DeployResultJson> {
106105

107106
if (!this.jsonEnabled()) formatter.display();
108107

109-
if (shouldRemoveFromCache(result.response.status)) {
110-
await DeployCache.unset(jobId);
111-
}
108+
await DeployCache.update(jobId, { status: result.response.status });
112109

113110
this.setExitCode(result);
114111

src/commands/deploy/metadata/resume.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { Duration } from '@salesforce/kit';
1313
import { DeployResultFormatter, getVersionMessage } from '../../../utils/output';
1414
import { DeployProgress } from '../../../utils/progressBar';
1515
import { DeployResultJson } from '../../../utils/types';
16-
import { DeployCache, determineExitCode, executeDeploy, shouldRemoveFromCache } from '../../../utils/deploy';
16+
import { DeployCache, determineExitCode, executeDeploy, isNotResumable } from '../../../utils/deploy';
1717
import { DEPLOY_STATUS_CODES_DESCRIPTIONS } from '../../../utils/errorCodes';
1818

1919
Messages.importMessagesDirectory(__dirname);
@@ -69,6 +69,11 @@ export default class DeployMetadataResume extends SfCommand<DeployResultJson> {
6969
const jobId = cache.resolveLatest(flags['use-most-recent'], flags['job-id']);
7070

7171
const deployOpts = cache.get(jobId);
72+
73+
if (isNotResumable(deployOpts.status)) {
74+
throw messages.createError('error.DeployNotResumable', [jobId, deployOpts.status]);
75+
}
76+
7277
const wait = flags.wait || Duration.minutes(deployOpts.wait);
7378
const { deploy, componentSet } = await executeDeploy({ ...deployOpts, wait, 'dry-run': false }, jobId);
7479

@@ -87,11 +92,8 @@ export default class DeployMetadataResume extends SfCommand<DeployResultJson> {
8792

8893
if (!this.jsonEnabled()) formatter.display();
8994

90-
if (shouldRemoveFromCache(result.response.status)) {
91-
cache.unset(deploy.id);
92-
cache.unset(jobId);
93-
await cache.write();
94-
}
95+
cache.update(deploy.id, { status: result.response.status });
96+
await cache.write();
9597

9698
return formatter.getJson();
9799
}

0 commit comments

Comments
 (0)