diff --git a/command-snapshot.json b/command-snapshot.json index f99dd485..f284ef35 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -78,14 +78,18 @@ "async", "client-id", "definition-file", + "description", "duration-days", "edition", "json", + "name", "no-ancestors", "no-namespace", + "release", "set-default", "target-dev-hub", "track-source", + "username", "wait" ], "alias": ["env:create:scratch"] diff --git a/messages/create_scratch.md b/messages/create_scratch.md index 9c1bd2b0..1c96bc7b 100644 --- a/messages/create_scratch.md +++ b/messages/create_scratch.md @@ -4,7 +4,17 @@ Create a scratch org. # description -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. +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. + +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: + + * --description + * --name (equivalent to the "orgName" option) + * --username + * --release + * --edition + +If you want to set options other than the preceding ones, such as org features or settings, you must use a definition file. 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. @@ -14,9 +24,13 @@ You must specify a Dev Hub to create a scratch org, either with the --target-dev <%= config.bin %> <%= command.id %> --edition=developer --alias my-scratch-org -- 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: +- 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: + + <%= config.bin %> <%= command.id %> --target-dev-hub MyHub --definition-file config/project-scratch-def.json --set-default --duration-days 3 + +- Create a preview Enterprise edition scratch org; for use only during Salesforce release transition periods: - <%= config.bin %> <%= command.id %> --target-dev-hub=MyHub --definition-file config/project-scratch-def.json --set-default --duration-days 3 + <%= config.bin %> <%= command.id %> --edition=enterprise --alias my-scratch-org --target-dev-hub MyHub --release preview # flags.target-hub.summary @@ -44,7 +58,7 @@ Don't include second-generation managed package (2GP) ancestors in the scratch o # flags.edition.summary -Salesforce edition of the scratch org. +Salesforce edition of the scratch org. Overrides the value of the "edition" option in the definition file, if set. # flags.async.summary @@ -96,6 +110,32 @@ Create the scratch org with no namespace, even if the Dev Hub has a namespace. Number of days before the org expires. +# flags.username.summary + +Username of the scratch org admin user. Overrides the value of the "username" option in the definition file, if set. + +# flags.username.description + +The username must be unique within the entire scratch org and sandbox universe. You must add your own logic to ensure uniqueness. + +Omit this flag to have Salesforce generate a unique username for your org. + +# flags.description.summary + +Description of the scratch org in the Dev Hub. Overrides the value of the "description" option in the definition file, if set. + +# flags.name.summary + +Name of the org, such as "Acme Company". Overrides the value of the "orgName" option in the definition file, if set. + +# flags.release.summary + +Release of the scratch org as compared to the Dev Hub release. + +# flags.release.description + +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. + # prompt.secret OAuth client secret of your personal connected app diff --git a/package.json b/package.json index 77e03118..779aeda2 100644 --- a/package.json +++ b/package.json @@ -24,12 +24,10 @@ "@salesforce/prettier-config": "^0.0.2", "@salesforce/ts-sinon": "1.4.6", "@swc/core": "1.3.39", - "@types/chai-as-promised": "^7.1.5", "@types/shelljs": "^0.8.10", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.1", "chai": "^4.3.7", - "chai-as-promised": "^7.1.1", "eslint": "^8.38.0", "eslint-config-prettier": "^8.6.0", "eslint-config-salesforce": "^1.1.1", @@ -236,4 +234,4 @@ "output": [] } } -} \ No newline at end of file +} diff --git a/src/commands/org/create/scratch.ts b/src/commands/org/create/scratch.ts index 4a4b4d3a..8ef13505 100644 --- a/src/commands/org/create/scratch.ts +++ b/src/commands/org/create/scratch.ts @@ -51,7 +51,6 @@ export default class EnvCreateScratch extends SfCommand { char: 'f', summary: messages.getMessage('flags.definition-file.summary'), description: messages.getMessage('flags.definition-file.description'), - exactlyOne: ['definition-file', 'edition'], }), 'target-dev-hub': Flags.requiredHub({ char: 'v', @@ -78,7 +77,6 @@ export default class EnvCreateScratch extends SfCommand { 'partner-group', 'partner-professional', ], - exactlyOne: ['definition-file', 'edition'], }), 'no-namespace': Flags.boolean({ char: 'm', @@ -115,6 +113,21 @@ export default class EnvCreateScratch extends SfCommand { description: messages.getMessage('flags.track-source.description'), allowNo: true, }), + username: Flags.string({ + summary: messages.getMessage('flags.username.summary'), + description: messages.getMessage('flags.username.description'), + }), + description: Flags.string({ + summary: messages.getMessage('flags.description.summary'), + }), + name: Flags.string({ + summary: messages.getMessage('flags.name.summary'), + }), + release: Flags.string({ + summary: messages.getMessage('flags.release.summary'), + description: messages.getMessage('flags.release.description'), + options: ['preview', 'previous'], + }), }; public async run(): Promise { const lifecycle = Lifecycle.getInstance(); @@ -123,9 +136,16 @@ export default class EnvCreateScratch extends SfCommand { if (!baseUrl) { throw new SfError('No instance URL found for the dev hub'); } - const orgConfig = flags['definition-file'] - ? (JSON.parse(await fs.promises.readFile(flags['definition-file'], 'utf-8')) as Record) - : { edition: flags.edition }; + const orgConfig = { + ...(flags['definition-file'] + ? (JSON.parse(await fs.promises.readFile(flags['definition-file'], 'utf-8')) as Record) + : {}), + ...(flags.edition ? { edition: flags.edition } : {}), + ...(flags.username ? { username: flags.username } : {}), + ...(flags.description ? { description: flags.description } : {}), + ...(flags.name ? { orgName: flags.name } : {}), + ...(flags.release ? { release: flags.release } : {}), + }; const createCommandOptions: ScratchOrgCreateOptions = { hubOrg: flags['target-dev-hub'], diff --git a/test/nut/scratchCreate.nut.ts b/test/nut/scratchCreate.nut.ts index 615f5981..1fa0ef23 100644 --- a/test/nut/scratchCreate.nut.ts +++ b/test/nut/scratchCreate.nut.ts @@ -6,7 +6,7 @@ */ import * as fs from 'fs'; import * as path from 'path'; -import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; +import { execCmd, genUniqueString, TestSession } from '@salesforce/cli-plugins-testkit'; import { assert, expect } from 'chai'; import { AuthFields, Messages, Global, StateAggregator } from '@salesforce/core'; import { secretTimeout } from '../../src/commands/org/create/scratch'; @@ -42,9 +42,6 @@ describe('env create scratch NUTs', () => { it('non-existent config file', () => { execCmd('env:create:scratch -f badfile.json', { ensureExitCode: 1 }); }); - it('config file AND edition', () => { - execCmd('env:create:scratch -f config/project-scratch-def.json --edition developer', { ensureExitCode: 1 }); - }); it('wait zero', () => { execCmd('env:create:scratch -f config/project-scratch-def.json --wait 0', { ensureExitCode: 1 }); }); @@ -85,6 +82,17 @@ describe('env create scratch NUTs', () => { ).jsonOutput?.result; expect(resp).to.have.all.keys(keys); }); + it('creates an org from config file with "override" flags ', () => { + const expectedUsername = genUniqueString('%s@nut.org'); + const resp = execCmd( + `env:create:scratch -f config/project-scratch-def.json --json --username ${expectedUsername} --description "new one" --name TheOrg --wait 60`, + { + ensureExitCode: 0, + } + ).jsonOutput?.result; + expect(resp).to.have.all.keys(keys); + expect(resp?.username).to.equal(expectedUsername); + }); it('creates an org with tracking disabled ', async () => { const resp = execCmd( 'env:create:scratch --edition developer --no-track-source --json --wait 60', diff --git a/test/unit/org/list.test.ts b/test/unit/org/list.test.ts index 84b91549..38e48009 100644 --- a/test/unit/org/list.test.ts +++ b/test/unit/org/list.test.ts @@ -4,8 +4,7 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { expect, use as ChaiUse } from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; +import { expect } from 'chai'; import { TestContext } from '@salesforce/core/lib/testSetup'; import { AuthInfo, Connection, Org } from '@salesforce/core'; import { stubMethod } from '@salesforce/ts-sinon'; @@ -14,8 +13,6 @@ import OrgListMock = require('../../shared/orgListMock'); import { OrgListCommand } from '../../../src/commands/org/list'; import { OrgListUtil } from '../../../src/shared/orgListUtil'; -ChaiUse(chaiAsPromised); - describe('org:list', () => { // Create new TestContext, which automatically creates and restores stubs // pertaining to authorization, orgs, config files, etc... diff --git a/yarn.lock b/yarn.lock index 92b3002a..29731e3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1332,13 +1332,6 @@ "@types/node" "*" "@types/responselike" "^1.0.0" -"@types/chai-as-promised@^7.1.5": - version "7.1.5" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" - integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== - dependencies: - "@types/chai" "*" - "@types/chai@*", "@types/chai@^4.2.11": version "4.3.4" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" @@ -2269,13 +2262,6 @@ cardinal@^2.1.1: ansicolors "~0.3.2" redeyed "~2.1.0" -chai-as-promised@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" - integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== - dependencies: - check-error "^1.0.2" - chai@^4.2.0, chai@^4.3.7: version "4.3.7" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51"