Skip to content

Commit d3a63cc

Browse files
authored
Fail action when Lambda function invocation fails (#6)
Previously, failed Lambda invocations would be reported as successful. This PR adds the input parameter `SUCCEED_ON_FUNCTION_FAILURE`, giving users the option to succeed in this action on function failure while changing the default action behavior to fail the action when the function fails.
1 parent 37bb5cf commit d3a63cc

File tree

9 files changed

+111
-20
lines changed

9 files changed

+111
-20
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist/* linguist-generated linguist-vendored=true

__tests__/index.spec.ts

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,19 @@ describe('invoke-aws-lambda', () => {
1111
[Props.Qualifier]: 'production',
1212
[ExtraOptions.HTTP_TIMEOUT]: '220000',
1313
[ExtraOptions.MAX_RETRIES]: '3',
14+
[ExtraOptions.SUCCEED_ON_FUNCTION_FAILURE]: 'false',
1415
[Credentials.AWS_ACCESS_KEY_ID]: 'someAccessKey',
1516
[Credentials.AWS_SECRET_ACCESS_KEY]: 'someSecretKey',
1617
REGION: 'us-west-2',
1718
};
18-
getInput.mockImplementation(
19-
(key: Partial<Props & Credentials & 'REGION'>) => {
20-
return mockedInput[key];
21-
}
22-
);
19+
20+
beforeAll(() => {
21+
getInput.mockImplementation(
22+
(key: Partial<Props & Credentials & 'REGION'>) => {
23+
return mockedInput[key];
24+
}
25+
);
26+
});
2327

2428
afterEach(() => {
2529
getInput.mockClear();
@@ -33,7 +37,7 @@ describe('invoke-aws-lambda', () => {
3337
Lambda.__setResponseForMethods({ invoke: handler });
3438

3539
await main();
36-
expect(getInput).toHaveBeenCalledTimes(12);
40+
expect(getInput).toHaveBeenCalledTimes(13);
3741
expect(setFailed).not.toHaveBeenCalled();
3842
expect(AWS.config.httpOptions).toMatchInlineSnapshot(`
3943
Object {
@@ -74,7 +78,7 @@ describe('invoke-aws-lambda', () => {
7478
`);
7579
});
7680

77-
it('fails when lambda throws an error', async () => {
81+
it('fails when lambda invocation throws an error', async () => {
7882
const handler = jest.fn(() => {
7983
throw new Error('something went horribly wrong');
8084
});
@@ -92,4 +96,68 @@ describe('invoke-aws-lambda', () => {
9296
expect(setFailed).toHaveBeenCalled();
9397
expect(setOutput).not.toHaveBeenCalled();
9498
});
99+
100+
describe('when the function returns an error', () => {
101+
beforeEach(() => {
102+
const handler = jest.fn().mockReturnValue({
103+
FunctionError: 'Unhandled',
104+
});
105+
106+
Lambda.__setResponseForMethods({ invoke: handler });
107+
});
108+
109+
it('should fail the action when SUCCEED_ON_FUNCTION_FAILURE is undefined', async () => {
110+
const overriddenMockedInput = {
111+
...mockedInput,
112+
[ExtraOptions.SUCCEED_ON_FUNCTION_FAILURE]: undefined,
113+
};
114+
115+
getInput.mockImplementation(
116+
(key: Partial<Props & Credentials & 'REGION'>) => {
117+
return overriddenMockedInput[key];
118+
}
119+
);
120+
121+
await main();
122+
123+
expect(setOutput).toHaveBeenCalled();
124+
expect(setFailed).toHaveBeenCalled();
125+
});
126+
127+
it('should fail the action when SUCCEED_ON_FUNCTION_FAILURE is false', async () => {
128+
const overriddenMockedInput = {
129+
...mockedInput,
130+
[ExtraOptions.SUCCEED_ON_FUNCTION_FAILURE]: 'false',
131+
};
132+
133+
getInput.mockImplementation(
134+
(key: Partial<Props & Credentials & 'REGION'>) => {
135+
return overriddenMockedInput[key];
136+
}
137+
);
138+
139+
await main();
140+
141+
expect(setOutput).toHaveBeenCalled();
142+
expect(setFailed).toHaveBeenCalled();
143+
});
144+
145+
it('should succeed the action when SUCCEED_ON_FUNCTION_FAILURE is true', async () => {
146+
const overriddenMockedInput = {
147+
...mockedInput,
148+
[ExtraOptions.SUCCEED_ON_FUNCTION_FAILURE]: 'true',
149+
};
150+
151+
getInput.mockImplementation(
152+
(key: Partial<Props & Credentials & 'REGION'>) => {
153+
return overriddenMockedInput[key];
154+
}
155+
);
156+
157+
await main();
158+
159+
expect(setOutput).toHaveBeenCalled();
160+
expect(setFailed).not.toHaveBeenCalled();
161+
});
162+
});
95163
});

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ inputs:
4343
MAX_RETRIES:
4444
description: Returns the maximum amount of retries to perform for a service request. By default this value is calculated by the specific service object that the request is being made to.
4545
required: false
46+
SUCCEED_ON_FUNCTION_FAILURE:
47+
description: Set to true if this action should succeed when the Lambda function executed returns an error
48+
required: false
4649
outputs:
4750
response: # id of output
4851
description: "response from lambda invocation"

dist/index.js

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/src/index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export declare enum ExtraOptions {
22
HTTP_TIMEOUT = "HTTP_TIMEOUT",
3-
MAX_RETRIES = "MAX_RETRIES"
3+
MAX_RETRIES = "MAX_RETRIES",
4+
SUCCEED_ON_FUNCTION_FAILURE = "SUCCEED_ON_FUNCTION_FAILURE"
45
}
56
export declare enum Credentials {
67
AWS_ACCESS_KEY_ID = "AWS_ACCESS_KEY_ID",

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "invoke-aws-lambda",
33
"repository": "[email protected]:gagoar/invoke-aws-lambda.git",
44
"license": "MIT",
5-
"version": "3.2.0",
5+
"version": "3.3.0",
66
"description": "Invoke AWS Lambda",
77
"main": "index.ts",
88
"husky": {

readme.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,17 @@ This action allows you to synchronously invoke a Lambda function and get the res
4747

4848
### Invocation
4949

50-
| Key | Type | Required | Description |
51-
| ---------------- | :------------------------------------------: | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
52-
| `FunctionName` | `string` | Yes | Name of the Lambda function to be invoked. |
53-
| `InvocationType` | `RequestResponse\|`<br>`Event\|`<br>`DryRun` | No | Default `RequestResponse`. See the [AWS Javascript SDK docs](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#invoke-property) for more info. |
54-
| `LogType` | `Tail\|None` | No | Default `None`. Set to `Tail` to include the execution log in the response. |
55-
| `Payload` | `string` | No | JSON that you want to provide to your Lambda function as input. |
56-
| `Qualifier` | `string` | No | Version or alias of the function to be invoked. |
57-
| `ClientContext` | `string` | No | Base64-encoded data about the invoking client to pass to the function. |
58-
| `HTTP_TIMEOUT` | `number` | No | Sets the socket to timeout after timeout milliseconds of inactivity on the socket. Defaults to two minutes (120000). See the [AWS Javascript SDK docs](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html) |
59-
| `MAX_RETRIES` | `number` | No | Returns the maximum amount of retries to perform for a service request. By default this value is calculated by the specific service object that the request is being made to. [AWS Javascript SDK docs](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#maxRetries-property) |
50+
| Key | Type | Required | Description |
51+
| ----------------------------- | :------------------------------------------: | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
52+
| `FunctionName` | `string` | Yes | Name of the Lambda function to be invoked. |
53+
| `InvocationType` | `RequestResponse\|`<br>`Event\|`<br>`DryRun` | No | Default `RequestResponse`. See the [AWS Javascript SDK docs](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#invoke-property) for more info. |
54+
| `LogType` | `Tail\|None` | No | Default `None`. Set to `Tail` to include the execution log in the response. |
55+
| `Payload` | `string` | No | JSON that you want to provide to your Lambda function as input. |
56+
| `Qualifier` | `string` | No | Version or alias of the function to be invoked. |
57+
| `ClientContext` | `string` | No | Base64-encoded data about the invoking client to pass to the function. |
58+
| `HTTP_TIMEOUT` | `number` | No | Sets the socket to timeout after timeout milliseconds of inactivity on the socket. Defaults to two minutes (120000). See the [AWS Javascript SDK docs](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html) |
59+
| `MAX_RETRIES` | `number` | No | Returns the maximum amount of retries to perform for a service request. By default this value is calculated by the specific service object that the request is being made to. [AWS Javascript SDK docs](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#maxRetries-property) |
60+
| `SUCCEED_ON_FUNCTION_FAILURE` | `boolean` | No | Set to true if this action should succeed when the Lambda function executed returns an error |
6061

6162
For more details on the parameters accepted by `Lambda.invoke()`, see the [AWS Javascript SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#invoke-property) docs
6263

src/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const apiVersion = '2015-03-31';
77
export enum ExtraOptions {
88
HTTP_TIMEOUT = 'HTTP_TIMEOUT',
99
MAX_RETRIES = 'MAX_RETRIES',
10+
SUCCEED_ON_FUNCTION_FAILURE = 'SUCCEED_ON_FUNCTION_FAILURE',
1011
}
1112

1213
export enum Credentials {
@@ -52,6 +53,7 @@ const setAWSConfigOptions = () => {
5253
AWS.config.maxRetries = parseInt(maxRetries, 10);
5354
}
5455
};
56+
5557
export const main = async () => {
5658
try {
5759
setAWSCredentials();
@@ -65,6 +67,15 @@ export const main = async () => {
6567
const response = await lambda.invoke(params).promise();
6668

6769
setOutput('response', response);
70+
71+
const succeedOnFailure =
72+
getInput(ExtraOptions.SUCCEED_ON_FUNCTION_FAILURE).toLowerCase() ===
73+
'true';
74+
if ('FunctionError' in response && !succeedOnFailure) {
75+
throw new Error(
76+
'Lambda invocation failed! See outputs.response for more information.'
77+
);
78+
}
6879
} catch (error) {
6980
setFailed(error.message);
7081
}

0 commit comments

Comments
 (0)