Skip to content

Commit 541349d

Browse files
committed
feat: scratch org lifecycle events
1 parent 79fd7d3 commit 541349d

5 files changed

+35
-17
lines changed

src/exported.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,11 @@ export { PermissionSetAssignment, PermissionSetAssignmentFields } from './org/pe
105105
export { ScratchOrgCreateOptions, ScratchOrgCreateResult, scratchOrgCreate } from './org/scratchOrgCreate';
106106

107107
export { ScratchOrgInfo } from './org/scratchOrgTypes';
108-
export { ScratchOrgLifecycleEvent, scratchOrgLifecycleEventName } from './org/scratchOrgLifeCycleEvents';
108+
export {
109+
ScratchOrgLifecycleEvent,
110+
scratchOrgLifecycleEventName,
111+
scratchOrgLifecycleStages,
112+
} from './org/scratchOrgLifeCycleEvents';
109113

110114
// Utility sub-modules
111115
export * from './util/sfdc';

src/org/scratchOrgCreate.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export const scratchOrgCreate = async (options: ScratchOrgCreateOptions): Promis
109109
const logger = await Logger.child('scratchOrgCreate');
110110

111111
logger.debug('scratchOrgCreate');
112-
await emit({ stage: 'building request' });
112+
await emit({ stage: 'prepare request' });
113113
const {
114114
hubOrg,
115115
connectedAppConsumerKey,
@@ -178,7 +178,7 @@ export const scratchOrgCreate = async (options: ScratchOrgCreateOptions): Promis
178178
logger.debug(`scratch org username ${username}`);
179179

180180
const configAggregator = new ConfigAggregator();
181-
await emit({ stage: 'deploying', scratchOrgInfo: scratchOrgInfoResult });
181+
await emit({ stage: 'deploy settings', scratchOrgInfo: scratchOrgInfoResult });
182182

183183
const authInfo = await deploySettingsAndResolveUrl(
184184
scratchOrgAuthInfo,
@@ -192,6 +192,7 @@ export const scratchOrgCreate = async (options: ScratchOrgCreateOptions): Promis
192192
logger.trace('Settings deployed to org');
193193
/** updating the revision num to zero during org:creation if source members are created during org:create.This only happens for some specific scratch org definition file.*/
194194
await updateRevisionCounterToZero(scratchOrg);
195+
await emit({ stage: 'done', scratchOrgInfo: scratchOrgInfoResult });
195196

196197
return {
197198
username,

src/org/scratchOrgInfoApi.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ export const authorizeScratchOrg = async (options: {
190190
retry?: number;
191191
}): Promise<AuthInfo> => {
192192
const { scratchOrgInfoComplete, hubOrg, clientSecret, signupTargetLoginUrlConfig, retry: maxRetries } = options;
193-
await emit({ stage: 'authing', scratchOrgInfo: scratchOrgInfoComplete });
193+
await emit({ stage: 'authenticate', scratchOrgInfo: scratchOrgInfoComplete });
194194
const logger = await Logger.child('authorizeScratchOrg');
195195
logger.debug(`scratchOrgInfoComplete: ${JSON.stringify(scratchOrgInfoComplete, null, 4)}`);
196196

@@ -287,8 +287,9 @@ export const requestScratchOrgCreation = async (
287287

288288
await checkOrgDoesntExist(scratchOrgInfo); // throw if it does exist.
289289
try {
290-
await emit({ stage: 'requested' });
291-
return hubOrg.getConnection().sobject('ScratchOrgInfo').create(scratchOrgInfo);
290+
await emit({ stage: 'send request' });
291+
// return await will cause this catch block to run instead of the caller's catch block
292+
return await hubOrg.getConnection().sobject('ScratchOrgInfo').create(scratchOrgInfo);
292293
} catch (error) {
293294
// this is a jsforce error which contains the property "fields" which regular error don't
294295
const jsForceError = error as JsForceError;
@@ -323,13 +324,13 @@ export const pollForScratchOrgInfo = async (
323324
logger.debug(`polling client result: ${JSON.stringify(resultInProgress, null, 4)}`);
324325
// Once it's "done" we can return it
325326
if (resultInProgress.Status === 'Active' || resultInProgress.Status === 'Error') {
326-
await emit({ stage: 'ready', scratchOrgInfo: resultInProgress as unknown as ScratchOrgInfo });
327+
await emit({ stage: 'available', scratchOrgInfo: resultInProgress as unknown as ScratchOrgInfo });
327328
return {
328329
completed: true,
329330
payload: resultInProgress as unknown as AnyJson,
330331
};
331332
}
332-
await emit({ stage: 'pending', scratchOrgInfo: resultInProgress as unknown as ScratchOrgInfo });
333+
await emit({ stage: 'wait for org', scratchOrgInfo: resultInProgress as unknown as ScratchOrgInfo });
333334

334335
logger.debug(`Scratch org status is ${resultInProgress.Status}`);
335336
return {

src/org/scratchOrgLifecycleEvents.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,17 @@ import { ScratchOrgInfo } from './scratchOrgTypes';
1010
const emitter = Lifecycle.getInstance();
1111

1212
export const scratchOrgLifecycleEventName = 'scratchOrgLifecycleEvent';
13-
13+
export const scratchOrgLifecycleStages = [
14+
'prepare request',
15+
'send request',
16+
'wait for org',
17+
'available',
18+
'authenticate',
19+
'deploy settings',
20+
'done',
21+
] as const;
1422
export interface ScratchOrgLifecycleEvent {
15-
stage: 'building request' | 'requested' | 'pending' | 'ready' | 'authing' | 'deploying';
23+
stage: typeof scratchOrgLifecycleStages[number];
1624
scratchOrgInfo?: ScratchOrgInfo;
1725
}
1826

test/unit/org/scratchOrgInfoApiTest.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
} from '../../../src/org/scratchOrgInfoApi';
2525
import { ScratchOrgInfo } from '../../../src/org/scratchOrgTypes';
2626
import { Messages } from '../../../src/messages';
27+
import { SfError } from '../../../src/sfError';
2728

2829
Messages.importMessagesDirectory(__dirname);
2930
const messages = Messages.loadMessages('@salesforce/core', 'scratchOrgInfoApi');
@@ -138,9 +139,12 @@ describe('requestScratchOrgCreation', () => {
138139
const err = new Error('MyError');
139140
err.name = 'NamedOrgNotFound';
140141
stubMethod(sandbox, AuthInfo, 'create').rejects(err);
141-
const jsForceError = new Error('JsForce-Error') as JsForceError;
142-
jsForceError.errorCode = 'REQUIRED_FIELD_MISSING';
143-
jsForceError.fields = ['error-field'];
142+
const jsForceError = {
143+
...new Error('JsForce-Error'),
144+
errorCode: 'REQUIRED_FIELD_MISSING',
145+
fields: ['error-field'],
146+
} as JsForceError;
147+
144148
// @ts-ignore
145149
connectionStub.sobject.withArgs('ScratchOrgInfo').returns({
146150
create: sinon.stub().rejects(jsForceError),
@@ -150,10 +154,10 @@ describe('requestScratchOrgCreation', () => {
150154
try {
151155
await shouldThrow(requestScratchOrgCreation(hubOrg, TEMPLATE_SCRATCH_ORG_INFO, settings));
152156
} catch (error) {
153-
expect(error).to.exist;
154-
expect(error.message).to.include(
155-
messages.getMessage('SignupFieldsMissingError', [jsForceError.fields.toString()])
156-
);
157+
const e = error as SfError;
158+
expect(e).to.exist;
159+
expect(e).to.have.property('message');
160+
expect(e.message).to.include(messages.getMessage('SignupFieldsMissingError', [jsForceError.fields.toString()]));
157161
}
158162
});
159163

0 commit comments

Comments
 (0)