Skip to content

Commit 31826c3

Browse files
authored
feat(update): automatic function update config (optional) (#1)
* [ADD] auto update feature * Update action.yml * [ADD] find functions with all layer versions * [ADD] find functions with all layer versions * [FIX] indentation * [FIX] indentation * [FIX] update README.md
1 parent 402c063 commit 31826c3

File tree

4 files changed

+57
-6
lines changed

4 files changed

+57
-6
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Replace the placeholders with the appropriate values:
5656
- `runtimes`: The list of valid runtimes that this layer can support. The valid values are `["nodejs" || "nodejs4.3" || "nodejs6.10" || "nodejs8.10" || "nodejs10.x" || "nodejs12.x" || "nodejs14.x" || "nodejs16.x" || "nodejs18.x"|| "nodejs20.x" || "java8" || "java8.al2" || "java11" || "python2.7" || "python3.6" || "python3.7" || "python3.8" || "python3.9" || "dotnetcore1.0" || "dotnetcore2.0" || "dotnetcore2.1" || "dotnetcore3.1" || "dotnet6" || "nodejs4.3-edge" || "go1.x" || "ruby2.5" || "ruby2.7" || "provided" || "provided.al2" || "nodejs18.x" || "python3.10" || "java17" || "ruby3.2" || "python3.11"]`<br/>
5757
- `s3_bucket`: An optional parameter for S3 Bucket Name In case if layer exceeds the allocated threshold size. We recommend to always provide with this value since if this value is present then action will try to upload layer via S3 automatically as failsafe mechanism for larger layers. Overcoming the limitation of direct AWS Lambda Layer size constraints over SDK.
5858
- `functions`: An Optional array of functions to refresh the layer to the latest uploaded version. It is recommended to pass down all the functions in this argument that uses this layer. Action will try to refresh all the dependent functions to use the latest layer version automatically.
59+
- `auto_update`: An optional boolean to automatically find and update all lambdas using the layer. With this option you don't have to manually specify the `functions` parameter. Use with caution as it might also facilitate the propagation of faulty layers. Disabled by default.
5960

6061
This GitHub Action is distributed under the MIT License. See LICENSE for more information.
6162

action.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@ inputs:
3232
description: "Optional Lambda function name(s) to update the layer to latest. String[]"
3333
required: false
3434
default: '[]'
35+
auto_update:
36+
description: "Optional Automatically update all Lambda functions using the layer to the latest layer version. Boolean"
37+
required: false
3538
runs:
3639
using: 'node16'
3740
main: 'index.js'
3841
branding:
3942
icon: 'archive'
40-
color: 'gray-dark'
43+
color: 'gray-dark'

helper.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const { readFileSync, statSync } = require('fs');
2-
const { LambdaClient, PublishLayerVersionCommand, UpdateFunctionConfigurationCommand } = require('@aws-sdk/client-lambda');
2+
const { LambdaClient, PublishLayerVersionCommand, UpdateFunctionConfigurationCommand, ListFunctionsCommand } = require('@aws-sdk/client-lambda');
33
const { S3Client, PutObjectCommand, DeleteObjectCommand } = require('@aws-sdk/client-s3');
44

55
const non_error_response_codes = [200, 201, 204];
@@ -142,7 +142,38 @@ exports.refreshLambdaLayerVersion = async ({
142142
FunctionName: functionName,
143143
Layers: [layerARN]
144144
})));
145-
146145
const response = await Promise.all(commands);
147146
return response;
147+
}
148+
149+
/**
150+
* List all the lambda functions that use the specified layer
151+
*/
152+
exports.listLambdaFunctionsWithLayer = async ({
153+
region,
154+
accessKeyId,
155+
secretAccessKey,
156+
layerARN
157+
}) => {
158+
try {
159+
const client = lambdaClient({ region, accessKeyId, secretAccessKey });
160+
161+
const allFunctions = [];
162+
let nextMarker = null;
163+
do {
164+
const listFunctionsCommand = new ListFunctionsCommand({ Marker: nextMarker });
165+
const { Functions: functions, NextMarker: nextPageMarker } = await client.send(listFunctionsCommand);
166+
167+
allFunctions.push(...functions);
168+
nextMarker = nextPageMarker;
169+
} while (nextMarker);
170+
171+
const layerARNWithoutVersion = layerARN.split(':').slice(0, -1).join(':')
172+
const matchinFunctions = allFunctions.filter((func) => func.Layers && func.Layers.some((layer) => layer.Arn.includes(layerARNWithoutVersion)))
173+
const functionNames = matchinFunctions.map((func) => func.FunctionName);
174+
return functionNames;
175+
} catch (error) {
176+
console.error("Error:", error);
177+
return [];
178+
}
148179
}

index.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ const {
55
publishS3LayerArchive,
66
getArchiveSize,
77
deleteTemporaryArchiveFromS3,
8-
refreshLambdaLayerVersion
8+
refreshLambdaLayerVersion,
9+
listLambdaFunctionsWithLayer
910
} = require('./helper');
1011

1112

@@ -20,10 +21,11 @@ const {
2021
const architectures = getInput('architectures') ? JSON.parse(getInput('architectures')) : [];
2122
const s3Bucket = getInput('s3_bucket');
2223
const functionNames = JSON.parse(getInput('functions'));
23-
24+
const autoUpdate = getInput('auto_update') || false;
25+
2426
console.log(runtimes, architectures);
2527
const creds = { region, accessKeyId, secretAccessKey };
26-
28+
2729
const size = getArchiveSize(archive);
2830
console.log(`Archive size is ${size}`);
2931
let layerResponse;
@@ -75,6 +77,20 @@ const {
7577
layerARN: layerResponse.LayerVersionArn
7678
});
7779
}
80+
if (autoUpdate) {
81+
// find automatically all matching functions
82+
const foundFunctionNames = await listLambdaFunctionsWithLayer({
83+
...creds,
84+
layerARN: layerResponse.LayerVersionArn,
85+
})
86+
console.log('The following functions will be updated :', foundFunctionNames)
87+
// trigger functions update
88+
await refreshLambdaLayerVersion({
89+
...creds,
90+
functionNames: foundFunctionNames,
91+
layerARN: layerResponse.LayerVersionArn
92+
});
93+
}
7894
} catch (err) {
7995
setFailed(err.message);
8096
}

0 commit comments

Comments
 (0)