Skip to content

Commit c09d229

Browse files
feat: more scratch org creation flags (#641)
* feat: more scratch org creation flags * fix: edit messages for new flags * feat: edition overrides definition file, both are allowed * test: allow edition with config file * test: remove unused test dep --------- Co-authored-by: Juliet Shackell <[email protected]>
1 parent c133036 commit c09d229

File tree

5 files changed

+86
-14
lines changed

5 files changed

+86
-14
lines changed

command-snapshot.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,18 @@
7878
"async",
7979
"client-id",
8080
"definition-file",
81+
"description",
8182
"duration-days",
8283
"edition",
8384
"json",
85+
"name",
8486
"no-ancestors",
8587
"no-namespace",
88+
"release",
8689
"set-default",
8790
"target-dev-hub",
8891
"track-source",
92+
"username",
8993
"wait"
9094
],
9195
"alias": ["env:create:scratch"]

messages/create_scratch.md

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,17 @@ Create a scratch org.
44

55
# description
66

7-
There are two ways to create a scratch org: specify a definition file that contains the options or use the --edition flag to specify the one required option. If you want to set options other than the edition, such as org features or settings, you must use a definition file.
7+
There are two ways to create a scratch org: either specify a definition file that contains the options or use the --edition flag to specify the one required option.
8+
9+
For either method, you can also use these flags; if you use them with --definition-file, they override their equivalent option in the scratch org definition file:
10+
11+
* --description
12+
* --name (equivalent to the "orgName" option)
13+
* --username
14+
* --release
15+
* --edition
16+
17+
If you want to set options other than the preceding ones, such as org features or settings, you must use a definition file.
818

919
You must specify a Dev Hub to create a scratch org, either with the --target-dev-hub flag or by setting your default Dev Hub with the target-dev-hub configuration variable.
1020

@@ -14,9 +24,13 @@ You must specify a Dev Hub to create a scratch org, either with the --target-dev
1424

1525
<%= config.bin %> <%= command.id %> --edition=developer --alias my-scratch-org
1626

17-
- Specify the Dev Hub using its alias and a scratch org definition file. Set the scratch org as your default and specify that it expires in 3 days:
27+
- Create a scratch org with a definition file. Specify the Dev Hub using its alias, set the scratch org as your default, and specify that it expires in 3 days:
28+
29+
<%= config.bin %> <%= command.id %> --target-dev-hub MyHub --definition-file config/project-scratch-def.json --set-default --duration-days 3
30+
31+
- Create a preview Enterprise edition scratch org; for use only during Salesforce release transition periods:
1832

19-
<%= config.bin %> <%= command.id %> --target-dev-hub=MyHub --definition-file config/project-scratch-def.json --set-default --duration-days 3
33+
<%= config.bin %> <%= command.id %> --edition=enterprise --alias my-scratch-org --target-dev-hub MyHub --release preview
2034

2135
# flags.target-hub.summary
2236

@@ -44,7 +58,7 @@ Don't include second-generation managed package (2GP) ancestors in the scratch o
4458

4559
# flags.edition.summary
4660

47-
Salesforce edition of the scratch org.
61+
Salesforce edition of the scratch org. Overrides the value of the "edition" option in the definition file, if set.
4862

4963
# flags.async.summary
5064

@@ -96,6 +110,32 @@ Create the scratch org with no namespace, even if the Dev Hub has a namespace.
96110

97111
Number of days before the org expires.
98112

113+
# flags.username.summary
114+
115+
Username of the scratch org admin user. Overrides the value of the "username" option in the definition file, if set.
116+
117+
# flags.username.description
118+
119+
The username must be unique within the entire scratch org and sandbox universe. You must add your own logic to ensure uniqueness.
120+
121+
Omit this flag to have Salesforce generate a unique username for your org.
122+
123+
# flags.description.summary
124+
125+
Description of the scratch org in the Dev Hub. Overrides the value of the "description" option in the definition file, if set.
126+
127+
# flags.name.summary
128+
129+
Name of the org, such as "Acme Company". Overrides the value of the "orgName" option in the definition file, if set.
130+
131+
# flags.release.summary
132+
133+
Release of the scratch org as compared to the Dev Hub release.
134+
135+
# flags.release.description
136+
137+
By default, scratch orgs are on the same release as the Dev Hub. During Salesforce release transition periods, you can override this default behavior and opt in or out of the new release.
138+
99139
# prompt.secret
100140

101141
OAuth client secret of your personal connected app

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,4 @@
234234
"output": []
235235
}
236236
}
237-
}
237+
}

src/commands/org/create/scratch.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ export default class EnvCreateScratch extends SfCommand<ScratchCreateResponse> {
5151
char: 'f',
5252
summary: messages.getMessage('flags.definition-file.summary'),
5353
description: messages.getMessage('flags.definition-file.description'),
54-
exactlyOne: ['definition-file', 'edition'],
5554
}),
5655
'target-dev-hub': Flags.requiredHub({
5756
char: 'v',
@@ -78,7 +77,6 @@ export default class EnvCreateScratch extends SfCommand<ScratchCreateResponse> {
7877
'partner-group',
7978
'partner-professional',
8079
],
81-
exactlyOne: ['definition-file', 'edition'],
8280
}),
8381
'no-namespace': Flags.boolean({
8482
char: 'm',
@@ -115,6 +113,21 @@ export default class EnvCreateScratch extends SfCommand<ScratchCreateResponse> {
115113
description: messages.getMessage('flags.track-source.description'),
116114
allowNo: true,
117115
}),
116+
username: Flags.string({
117+
summary: messages.getMessage('flags.username.summary'),
118+
description: messages.getMessage('flags.username.description'),
119+
}),
120+
description: Flags.string({
121+
summary: messages.getMessage('flags.description.summary'),
122+
}),
123+
name: Flags.string({
124+
summary: messages.getMessage('flags.name.summary'),
125+
}),
126+
release: Flags.string({
127+
summary: messages.getMessage('flags.release.summary'),
128+
description: messages.getMessage('flags.release.description'),
129+
options: ['preview', 'previous'],
130+
}),
118131
};
119132
public async run(): Promise<ScratchCreateResponse> {
120133
const lifecycle = Lifecycle.getInstance();
@@ -123,9 +136,16 @@ export default class EnvCreateScratch extends SfCommand<ScratchCreateResponse> {
123136
if (!baseUrl) {
124137
throw new SfError('No instance URL found for the dev hub');
125138
}
126-
const orgConfig = flags['definition-file']
127-
? (JSON.parse(await fs.promises.readFile(flags['definition-file'], 'utf-8')) as Record<string, unknown>)
128-
: { edition: flags.edition };
139+
const orgConfig = {
140+
...(flags['definition-file']
141+
? (JSON.parse(await fs.promises.readFile(flags['definition-file'], 'utf-8')) as Record<string, unknown>)
142+
: {}),
143+
...(flags.edition ? { edition: flags.edition } : {}),
144+
...(flags.username ? { username: flags.username } : {}),
145+
...(flags.description ? { description: flags.description } : {}),
146+
...(flags.name ? { orgName: flags.name } : {}),
147+
...(flags.release ? { release: flags.release } : {}),
148+
};
129149

130150
const createCommandOptions: ScratchOrgCreateOptions = {
131151
hubOrg: flags['target-dev-hub'],

test/nut/scratchCreate.nut.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
import * as fs from 'fs';
88
import * as path from 'path';
9-
import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit';
9+
import { execCmd, genUniqueString, TestSession } from '@salesforce/cli-plugins-testkit';
1010
import { assert, expect } from 'chai';
1111
import { AuthFields, Messages, Global, StateAggregator } from '@salesforce/core';
1212
import { secretTimeout } from '../../src/commands/org/create/scratch';
@@ -42,9 +42,6 @@ describe('env create scratch NUTs', () => {
4242
it('non-existent config file', () => {
4343
execCmd('env:create:scratch -f badfile.json', { ensureExitCode: 1 });
4444
});
45-
it('config file AND edition', () => {
46-
execCmd('env:create:scratch -f config/project-scratch-def.json --edition developer', { ensureExitCode: 1 });
47-
});
4845
it('wait zero', () => {
4946
execCmd('env:create:scratch -f config/project-scratch-def.json --wait 0', { ensureExitCode: 1 });
5047
});
@@ -85,6 +82,17 @@ describe('env create scratch NUTs', () => {
8582
).jsonOutput?.result;
8683
expect(resp).to.have.all.keys(keys);
8784
});
85+
it('creates an org from config file with "override" flags ', () => {
86+
const expectedUsername = genUniqueString('%[email protected]');
87+
const resp = execCmd<ScratchCreateResponse>(
88+
`env:create:scratch -f config/project-scratch-def.json --json --username ${expectedUsername} --description "new one" --name TheOrg --wait 60`,
89+
{
90+
ensureExitCode: 0,
91+
}
92+
).jsonOutput?.result;
93+
expect(resp).to.have.all.keys(keys);
94+
expect(resp?.username).to.equal(expectedUsername);
95+
});
8896
it('creates an org with tracking disabled ', async () => {
8997
const resp = execCmd<ScratchCreateResponse>(
9098
'env:create:scratch --edition developer --no-track-source --json --wait 60',

0 commit comments

Comments
 (0)