Skip to content

Commit 4ee3093

Browse files
matthiasrolke-sageamtrack
authored andcommitted
fix: exit with error code when anyonmous apex failed to compile or run
BREAKING CHANGE: force:apex:execute now returns an error exit code (1) when the compilation or execution of the Anonymous Apex failed.
1 parent 249b9c8 commit 4ee3093

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

messages/execute.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@
55
"logLevelDescription": "logging level for this command invocation",
66
"logLevelLongDescription": "The logging level for this command invocation. Logs are stored in $HOME/.sfdx/sfdx.log.",
77
"executeCompileSuccess": "Compiled successfully.",
8-
"executeRuntimeSuccess": "Executed successfully."
9-
}
8+
"executeCompileFailure": "Compilation failed.",
9+
"executeRuntimeSuccess": "Executed successfully.",
10+
"executeRuntimeFailure": "Execution failed."
11+
}

src/commands/force/apex/execute.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
import { ApexExecuteOptions, ExecuteService, ExecuteAnonymousResponse } from '@salesforce/apex-node';
88
import { flags, SfdxCommand } from '@salesforce/command';
9-
import { Messages } from '@salesforce/core';
9+
import { Messages, SfError } from '@salesforce/core';
1010
import { AnyJson } from '@salesforce/ts-types';
1111
import { buildDescription, colorSuccess, colorError, logLevels } from '../../../utils';
1212

@@ -15,7 +15,9 @@ const messages = Messages.load('@salesforce/plugin-apex', 'execute', [
1515
'apexCodeFileDescription',
1616
'commandDescription',
1717
'executeCompileSuccess',
18+
'executeCompileFailure',
1819
'executeRuntimeSuccess',
20+
'executeRuntimeFailure',
1921
'logLevelDescription',
2022
'logLevelLongDescription',
2123
'longDescription',
@@ -63,8 +65,19 @@ export default class Execute extends SfdxCommand {
6365
};
6466

6567
const result = await exec.executeAnonymous(execAnonOptions);
68+
const formattedResult = this.formatJson(result);
6669
this.ux.log(this.formatDefault(result));
67-
return this.formatJson(result);
70+
if (!result.compiled || !result.success) {
71+
let err: SfError;
72+
if (!result.compiled) {
73+
err = new SfError(messages.getMessage('executeCompileFailure'), 'executeCompileFailure');
74+
} else {
75+
err = new SfError(messages.getMessage('executeRuntimeFailure'), 'executeRuntimeFailure');
76+
}
77+
err.setData(formattedResult);
78+
throw err;
79+
}
80+
return formattedResult;
6881
} catch (e) {
6982
return Promise.reject(e);
7083
}

test/commands/force/apex/execute.test.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,14 @@ describe('force:apex:execute', () => {
148148
test
149149
.withOrg({ username: 'test@org.com' }, true)
150150
.withConnectionRequest(() => Promise.resolve(soapCompileProblem))
151-
.stub(ExecuteService.prototype, 'getUserInput', () => 'System.assert(true)')
151+
.stub(ExecuteService.prototype, 'getUserInput', () => 'ThisStatementShouldntCompile')
152152
.stub(ExecuteService.prototype, 'buildExecRequest', () => {
153153
'fakeData';
154154
})
155155
.stdout()
156156
.command(['force:apex:execute', '--targetusername', 'test@org.com', '--json'])
157157
.it('runs default command with json flag and compile problem', (ctx) => {
158+
expect(process.exitCode).to.eql(1);
158159
const result = ctx.stdout;
159160
expect(result).to.not.be.empty;
160161
const resultJSON = JSON.parse(result);
@@ -165,7 +166,7 @@ describe('force:apex:execute', () => {
165166
test
166167
.withOrg({ username: 'test@org.com' }, true)
167168
.withConnectionRequest(() => Promise.resolve(soapResponse))
168-
.stub(ExecuteService.prototype, 'getUserInput', () => 'System.assert(true)')
169+
.stub(ExecuteService.prototype, 'getUserInput', () => 'System.assert(true);')
169170
.stub(ExecuteService.prototype, 'buildExecRequest', () => {
170171
'fakeData';
171172
})
@@ -180,13 +181,16 @@ describe('force:apex:execute', () => {
180181
test
181182
.withOrg({ username: 'test@org.com' }, true)
182183
.withConnectionRequest(() => Promise.resolve(soapCompileProblem))
183-
.stub(ExecuteService.prototype, 'getUserInput', () => 'System.assert(true)')
184+
.stub(ExecuteService.prototype, 'getUserInput', () => 'ThisStatementShouldntCompile')
184185
.stub(ExecuteService.prototype, 'buildExecRequest', () => {
185186
'fakeData';
186187
})
187188
.stdout()
189+
.stderr()
188190
.command(['force:apex:execute', '--targetusername', 'test@org.com'])
189191
.it('runs default command with compile issue in human readable output', (ctx) => {
192+
expect(process.exitCode).to.eql(1);
193+
expect(ctx.stderr).to.contain('Compilation failed.');
190194
const result = ctx.stdout;
191195
expect(result).to.not.be.empty;
192196
expect(result).to.eql(compileResponse);
@@ -195,13 +199,16 @@ describe('force:apex:execute', () => {
195199
test
196200
.withOrg({ username: 'test@org.com' }, true)
197201
.withConnectionRequest(() => Promise.resolve(soapRuntimeProblem))
198-
.stub(ExecuteService.prototype, 'getUserInput', () => 'System.assert(true)')
202+
.stub(ExecuteService.prototype, 'getUserInput', () => 'System.assert(false);')
199203
.stub(ExecuteService.prototype, 'buildExecRequest', () => {
200204
'fakeData';
201205
})
202206
.stdout()
207+
.stderr()
203208
.command(['force:apex:execute', '--targetusername', 'test@org.com'])
204209
.it('runs default command with runtime issue in human readable output', (ctx) => {
210+
expect(process.exitCode).to.eql(1);
211+
expect(ctx.stderr).to.contain('Execution failed.');
205212
const result = ctx.stdout;
206213
expect(result).to.not.be.empty;
207214
expect(result).to.eql(runtimeResponse);

0 commit comments

Comments
 (0)