From 6b99f44c0fdbe9f3d398a7e98dff29d00fc02c46 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Thu, 27 Jan 2022 09:00:13 -0700 Subject: [PATCH] fix: add purgeondelete flag to deploy (#394) * fix: add purgeondelete flag to deploy * chore: Juliet's Update messages/md.deploy.json Co-authored-by: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Co-authored-by: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> --- command-snapshot.json | 2 + messages/deploy.json | 3 +- messages/md.deploy.json | 1 + src/commands/force/mdapi/beta/deploy.ts | 4 ++ src/commands/force/source/deploy.ts | 5 ++ test/commands/source/deploy.test.ts | 83 +++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 1 deletion(-) diff --git a/command-snapshot.json b/command-snapshot.json index bdcd68f80..6e3e235c4 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -16,6 +16,7 @@ "ignorewarnings", "json", "loglevel", + "purgeondelete", "runtests", "singlepackage", "soapdeploy", @@ -143,6 +144,7 @@ "metadata", "postdestructivechanges", "predestructivechanges", + "purgeondelete", "runtests", "soapdeploy", "sourcepath", diff --git a/messages/deploy.json b/messages/deploy.json index 8d7f9118a..cebee7bf7 100644 --- a/messages/deploy.json +++ b/messages/deploy.json @@ -29,7 +29,8 @@ "validateDeployRequestId": "deploy request ID of the validated deployment to run a Quick Deploy", "soapDeploy": "deploy metadata with SOAP API instead of REST API", "predestructivechanges": "file path for a manifest (destructiveChangesPre.xml) of components to delete before the deploy", - "postdestructivechanges": "file path for a manifest (destructiveChangesPost.xml) of components to delete after the deploy" + "postdestructivechanges": "file path for a manifest (destructiveChangesPost.xml) of components to delete after the deploy", + "purgeOnDelete": "the deleted components in the destructiveChanges.xml manifest file aren't stored in the Recycle Bin. Instead, they become immediately eligible for deletion." }, "flagsLong": { "sourcePath": [ diff --git a/messages/md.deploy.json b/messages/md.deploy.json index 1d74949cb..f2749ab0b 100644 --- a/messages/md.deploy.json +++ b/messages/md.deploy.json @@ -26,6 +26,7 @@ "validatedDeployRequestId": "request ID of the validated deployment to run a Quick Deploy", "singlePackage": "Indicates that the zip file points to a directory structure for a single package", "soapDeploy": "deploy metadata with SOAP API instead of REST API", + "purgeOnDelete": "specify that deleted components in the destructive changes manifest file are immediately eligible for deletion rather than being stored in the Recycle Bin", "concise": "omit success messages for smaller JSON output" }, "flagsLong": { diff --git a/src/commands/force/mdapi/beta/deploy.ts b/src/commands/force/mdapi/beta/deploy.ts index 8f4dfb13f..5f9e02d8f 100644 --- a/src/commands/force/mdapi/beta/deploy.ts +++ b/src/commands/force/mdapi/beta/deploy.ts @@ -94,6 +94,9 @@ export class Deploy extends DeployCommand { description: messages.getMessage('flags.soapDeploy'), longDescription: messages.getMessage('flagsLong.soapDeploy'), }), + purgeondelete: flags.boolean({ + description: messages.getMessage('flags.purgeOnDelete'), + }), concise: flags.builtin({ description: messages.getMessage('flags.concise'), }), @@ -123,6 +126,7 @@ export class Deploy extends DeployCommand { usernameOrConnection: this.org.getUsername(), ...deploymentOptions, apiOptions: { + purgeOnDelete: this.getFlag('purgeondelete', false), ignoreWarnings: this.getFlag('ignorewarnings', false), rollbackOnError: !this.getFlag('ignoreerrors', false), checkOnly: this.getFlag('checkonly', false), diff --git a/src/commands/force/source/deploy.ts b/src/commands/force/source/deploy.ts index f3fc6fc7a..5b906c992 100644 --- a/src/commands/force/source/deploy.ts +++ b/src/commands/force/source/deploy.ts @@ -70,6 +70,10 @@ export class Deploy extends DeployCommand { description: messages.getMessage('flags.ignoreWarnings'), longDescription: messages.getMessage('flagsLong.ignoreWarnings'), }), + purgeondelete: flags.boolean({ + description: messages.getMessage('flags.purgeOnDelete'), + dependsOn: ['manifest'], + }), validateddeployrequestid: flags.id({ char: 'q', description: messages.getMessage('flags.validateDeployRequestId'), @@ -150,6 +154,7 @@ export class Deploy extends DeployCommand { const deploy = await this.componentSet.deploy({ usernameOrConnection: this.org.getUsername(), apiOptions: { + purgeOnDelete: this.getFlag('purgeondelete', false), ignoreWarnings: this.getFlag('ignorewarnings', false), rollbackOnError: !this.getFlag('ignoreerrors', false), checkOnly: this.getFlag('checkonly', false), diff --git a/test/commands/source/deploy.test.ts b/test/commands/source/deploy.test.ts index 6e4e8a9a1..07500b72d 100644 --- a/test/commands/source/deploy.test.ts +++ b/test/commands/source/deploy.test.ts @@ -156,9 +156,11 @@ describe('force:source:deploy', () => { ignoreWarnings: false, rollbackOnError: true, checkOnly: false, + purgeOnDelete: false, runTests: [], testLevel: 'NoTestRun', rest: false, + ...overrides?.apiOptions, }, }; if (overrides?.apiOptions) { @@ -263,6 +265,87 @@ describe('force:source:deploy', () => { ensureProgressBar(0); }); + it('should pass purgeOnDelete flag', async () => { + const manifest = 'package.xml'; + const destructiveChanges = 'destructiveChangesPost.xml'; + const runTests = ['MyClassTest']; + const testLevel = 'RunSpecifiedTests'; + const result = await runDeployCmd([ + `--manifest=${manifest}`, + `--postdestructivechanges=${destructiveChanges}`, + '--ignorewarnings', + '--ignoreerrors', + '--checkonly', + `--runtests=${runTests[0]}`, + `--testlevel=${testLevel}`, + '--purgeondelete', + '--json', + ]); + + expect(result).to.deep.equal(expectedResults); + ensureDeployArgs({ + apiOptions: { + checkOnly: true, + ignoreWarnings: true, + purgeOnDelete: true, + rest: false, + rollbackOnError: false, + runTests: ['MyClassTest'], + testLevel: 'RunSpecifiedTests', + }, + }); + ensureCreateComponentSetArgs({ + manifest: { + manifestPath: manifest, + directoryPaths: [defaultDir], + destructiveChangesPost: destructiveChanges, + destructiveChangesPre: undefined, + }, + }); + ensureHookArgs(); + ensureProgressBar(0); + }); + + it('should pass default purgeondelete flag to false', async () => { + const manifest = 'package.xml'; + const destructiveChanges = 'destructiveChangesPost.xml'; + const runTests = ['MyClassTest']; + const testLevel = 'RunSpecifiedTests'; + const result = await runDeployCmd([ + `--manifest=${manifest}`, + `--postdestructivechanges=${destructiveChanges}`, + '--ignorewarnings', + '--ignoreerrors', + '--checkonly', + `--runtests=${runTests[0]}`, + `--testlevel=${testLevel}`, + '--json', + ]); + + expect(result).to.deep.equal(expectedResults); + ensureDeployArgs({ + apiOptions: { + checkOnly: true, + ignoreWarnings: true, + purgeOnDelete: false, + rest: false, + rollbackOnError: false, + runTests: ['MyClassTest'], + testLevel: 'RunSpecifiedTests', + }, + }); + ensureCreateComponentSetArgs({ + manifest: { + manifestPath: manifest, + directoryPaths: [defaultDir], + destructiveChangesPost: destructiveChanges, + destructiveChangesPre: undefined, + }, + }); + ensureHookArgs(); + ensureProgressBar(0); + }); + it('should pass along all deploy options', async () => { const manifest = 'package.xml'; const runTests = ['MyClassTest'];