Skip to content

Commit 5c048cb

Browse files
Merge pull request #1396 from salesforcecli/sl/W-18237102
fix: W-18237102 - refresh sandbox with sourceSandboxName
2 parents 8950dce + f3079a3 commit 5c048cb

File tree

3 files changed

+88
-2
lines changed

3 files changed

+88
-2
lines changed

command-snapshot.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@
159159
"no-auto-activate",
160160
"no-prompt",
161161
"poll-interval",
162+
"source-id",
163+
"source-sandbox-name",
162164
"target-org",
163165
"wait"
164166
],

messages/refresh.sandbox.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Refresh a sandbox org using the sandbox name.
44

55
# description
66

7-
Refreshing a sandbox copies the metadata, and optionally data, from your source org to the refreshed sandbox org. You can optionally specify a definition file if you want to change the configuration of the refreshed sandbox, such as its license type or template ID.
7+
Refreshing a sandbox copies the metadata, and optionally data, from your source org to the refreshed sandbox org. You can optionally specify a definition file if you want to change the configuration of the refreshed sandbox, such as its license type or template ID. You can also use the --source-id or --source-sandbox-name flags to change the refreshed sandbox org's original source org to a new org; in this case, the refreshed sandbox org's metadata is updated with the new source org's metadata.
88

99
You're not allowed to change the sandbox name when you refresh it with this command. If you want to change the sandbox name, first delete it with the "org delete sandbox" command. And then recreate it with the "org create sandbox" command and give it a new name.
1010

@@ -22,6 +22,10 @@ You're not allowed to change the sandbox name when you refresh it with this comm
2222

2323
<%= config.bin %> <%= command.id %> --definition-file devSbx3-config.json --target-org prodOrg
2424

25+
- Refresh the sandbox named "devSbx2" by changing its original source org to be a sandbox called "devSbx3":
26+
27+
<%= config.bin %> <%= command.id %> --name devSbx2 --source-sandbox-name devSbx3 --target-org prodOrg
28+
2529
# flags.no-auto-activate.summary
2630

2731
Disable auto-activation of the sandbox after a successful refresh.
@@ -106,3 +110,35 @@ The poll interval (%d seconds) can't be larger than the wait period (%d in secon
106110
# sandboxInfoRefreshFailed
107111

108112
The sandbox org refresh failed with a result of %s.
113+
114+
# flags.source-sandbox-name.summary
115+
116+
Name of the sandbox org that becomes the new source org for the refreshed sandbox.
117+
118+
# flags.source-sandbox-name.description
119+
120+
The value of --source-sandbox-name must be an existing sandbox. The new source sandbox, and the refreshed sandbox specified with the --name flag, must both be associated with the production org (--target-org) that contains the sandbox licenses.
121+
122+
You can specify either --source-sandbox-name or --source-id when refreshing an existing sandbox, but not both.
123+
124+
# flags.source-id.summary
125+
126+
ID of the sandbox org that becomes the new source org for the refreshed sandbox.
127+
128+
# flags.source-id.description
129+
130+
The value of --source-id must be an existing sandbox. The new source sandbox, and the refreshed sandbox specified with the --name flag, must both be associated with the production org (--target-org) that contains the sandbox licenses.
131+
132+
You can specify either --source-id or --source-sandbox-name when refreshing an existing sandbox, but not both.
133+
134+
# error.bothIdFlagAndDefFilePropertyAreProvided
135+
136+
You can't specify both the --source-id and --definition-file flags, and also include the "SourceId" option in the definition file. Pick one method of refreshing a sandbox and try again.
137+
138+
# error.bothNameFlagAndDefFilePropertyAreProvided
139+
140+
You can't specify both the --source-sandbox-name and --definition-file flags, and also include the "SourceSandboxName" option in the definition file. Pick one method of refreshing a sandbox and try again.
141+
142+
# error.bothIdFlagAndNameDefFileAreNotAllowed
143+
144+
You can't specify both the --source-sandbox-name and --definition-file flags, and also include the "SourceId" option in the definition file. Same with the --source-id flag and "SourceSandboxName" option. Pick one method of refreshing a sandbox and try again.

src/commands/org/refresh/sandbox.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Duration, omit } from '@salesforce/kit';
99
import { Flags } from '@salesforce/sf-plugins-core';
1010
import { Lifecycle, Messages, SandboxEvents, SandboxInfo, SfError } from '@salesforce/core';
1111
import { Interfaces } from '@oclif/core';
12-
import requestFunctions from '../../../shared/sandboxRequest.js';
12+
import requestFunctions, { readSandboxDefFile } from '../../../shared/sandboxRequest.js';
1313
import { SandboxCommandBase, SandboxCommandResponse } from '../../../shared/sandboxCommandBase.js';
1414

1515
type SandboxInfoRecord = SandboxInfo & {
@@ -69,6 +69,17 @@ export default class RefreshSandbox extends SandboxCommandBase<SandboxCommandRes
6969
helpValue: '<seconds>',
7070
exclusive: ['async'],
7171
}),
72+
'source-sandbox-name': Flags.string({
73+
summary: messages.getMessage('flags.source-sandbox-name.summary'),
74+
description: messages.getMessage('flags.source-sandbox-name.description'),
75+
exclusive: ['source-id'],
76+
}),
77+
'source-id': Flags.salesforceId({
78+
summary: messages.getMessage('flags.source-id.summary'),
79+
description: messages.getMessage('flags.source-id.description'),
80+
exclusive: ['source-sandbox-name'],
81+
length: 'both',
82+
}),
7283
async: Flags.boolean({
7384
summary: messages.getMessage('flags.async.summary'),
7485
description: messages.getMessage('flags.async.description'),
@@ -190,6 +201,7 @@ export default class RefreshSandbox extends SandboxCommandBase<SandboxCommandRes
190201

191202
let apexId: string | undefined;
192203
let groupId: string | undefined;
204+
let srcId: string | undefined;
193205

194206
if (defFileContent.ApexClassName) {
195207
apexId = await requestFunctions.getApexClassIdByName(
@@ -206,6 +218,15 @@ export default class RefreshSandbox extends SandboxCommandBase<SandboxCommandRes
206218
);
207219
delete defFileContent.ActivationUserGroupName;
208220
}
221+
222+
if (defFileContent.SourceSandboxName) {
223+
srcId = await requestFunctions.getSrcIdByName(
224+
this.flags['target-org'].getConnection(),
225+
defFileContent.SourceSandboxName
226+
);
227+
delete defFileContent.SourceSandboxName;
228+
}
229+
209230
// Warn if sandbox name is in `--name` and `--definition-file` flags and they differ.
210231
if (defFileContent?.SandboxName && sbxName && sbxName !== defFileContent?.SandboxName) {
211232
this.warn(messages.createWarning('warning.ConflictingSandboxNames', [sbxName, defFileContent?.SandboxName]));
@@ -232,8 +253,19 @@ export default class RefreshSandbox extends SandboxCommandBase<SandboxCommandRes
232253
sandboxInfo = Object.assign(sandboxInfo, defFileContent, {
233254
SandboxName: sbxName,
234255
AutoActivate: !this.flags['no-auto-activate'],
256+
...(this.flags['source-sandbox-name']
257+
? {
258+
SourceId: await requestFunctions.getSrcIdByName(
259+
this.flags['target-org'].getConnection(),
260+
this.flags['source-sandbox-name']
261+
),
262+
}
263+
: this.flags['source-id']
264+
? { SourceId: this.flags['source-id'] }
265+
: {}),
235266
...(apexId ? { ApexClassId: apexId } : {}),
236267
...(groupId ? { ActivationUserGroupId: groupId } : {}),
268+
...(srcId ? { SourceId: srcId } : {}),
237269
});
238270

239271
return sandboxInfo;
@@ -250,6 +282,22 @@ export default class RefreshSandbox extends SandboxCommandBase<SandboxCommandRes
250282
this.flags.wait.seconds,
251283
]);
252284
}
285+
if (!this.flags['definition-file']) {
286+
return undefined;
287+
}
288+
const parsedDef = readSandboxDefFile(this.flags['definition-file']);
289+
if (this.flags['source-id'] && parsedDef.SourceId) {
290+
throw messages.createError('error.bothIdFlagAndDefFilePropertyAreProvided');
291+
}
292+
if (this.flags['source-sandbox-name'] && parsedDef.SourceSandboxName) {
293+
throw messages.createError('error.bothNameFlagAndDefFilePropertyAreProvided');
294+
}
295+
if (this.flags['source-id'] && parsedDef.SourceSandboxName) {
296+
throw messages.createError('error.bothIdFlagAndNameDefFileAreNotAllowed');
297+
}
298+
if (this.flags['source-sandbox-name'] && parsedDef.SourceId) {
299+
throw messages.createError('error.bothIdFlagAndNameDefFileAreNotAllowed');
300+
}
253301
}
254302

255303
private initSandboxProcessData(sandboxInfo: SandboxInfo): void {

0 commit comments

Comments
 (0)