From dfb3ec87663990db6a4581909efed61b9551da35 Mon Sep 17 00:00:00 2001 From: gaurav sharma Date: Fri, 28 Jul 2023 12:29:55 +0530 Subject: [PATCH 1/3] chore(action): update branding --- action.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index ed3ac13c..9c43a181 100644 --- a/action.yml +++ b/action.yml @@ -1,4 +1,5 @@ name: 'AWS Lambda Layer Release' +author: Gaurav Sharma description: 'Action lets you release your latest lambda layer version' inputs: access_key_id: # id of input @@ -33,4 +34,7 @@ inputs: default: '[]' runs: using: 'node16' - main: 'index.js' \ No newline at end of file + main: 'index.js' +branding: + icon: 'archive' + color: 'gray-dark' \ No newline at end of file From 402c063ae7f6f8f9e16751836b2cb7e939baca0d Mon Sep 17 00:00:00 2001 From: Gaurav Sharma Date: Tue, 14 May 2024 10:06:23 +0530 Subject: [PATCH 2/3] chore(readme): update supported nodejs runtime (#2) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1bfa8c68..37986c77 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Replace the placeholders with the appropriate values: - `layer_name`: Name of the layer where you want to publish this version. This layer name must already exist on AWS Lambda layers.`access_key_id` and `secret_access_key` must be allowed to interact with this layer.
- `archive`: Refers the path of the zip archive to upload as layer. The archive creation process is not part of this action since the build steps may vary from application to application and it should be taken care as a separate step. Refer below for a quick example to how to do this for a NodeJS application.
- `architectures`: String containing array of architectures that this new layer will support. Valid values are `[x_86_64 || arm64]`.
-- `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" || "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"]`
+- `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"]`
- `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. - `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. @@ -109,4 +109,4 @@ Contributions to this project are welcome. If you find any issues or want to add By using this custom GitHub Action, you can simplify the release process of your AWS Lambda layers, automate the handling of larger layers, and ensure all dependent Lambda functions are updated with the latest layer version. Happy coding! -> Stay tuned to wonderful tech content at https://theserverfault.com \ No newline at end of file +> Stay tuned to wonderful tech content at https://theserverfault.com From 31826c39061f6a683dcbbaabc7f55604c1962272 Mon Sep 17 00:00:00 2001 From: ktx-mega <85870293+ktx-mega@users.noreply.github.com> Date: Thu, 23 May 2024 19:24:37 +0200 Subject: [PATCH 3/3] 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 --- README.md | 1 + action.yml | 5 ++++- helper.js | 35 +++++++++++++++++++++++++++++++++-- index.js | 22 +++++++++++++++++++--- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 37986c77..a6df7380 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ Replace the placeholders with the appropriate values: - `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"]`
- `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. - `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. +- `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. This GitHub Action is distributed under the MIT License. See LICENSE for more information. diff --git a/action.yml b/action.yml index 9c43a181..f40bfc6e 100644 --- a/action.yml +++ b/action.yml @@ -32,9 +32,12 @@ inputs: description: "Optional Lambda function name(s) to update the layer to latest. String[]" required: false default: '[]' + auto_update: + description: "Optional Automatically update all Lambda functions using the layer to the latest layer version. Boolean" + required: false runs: using: 'node16' main: 'index.js' branding: icon: 'archive' - color: 'gray-dark' \ No newline at end of file + color: 'gray-dark' diff --git a/helper.js b/helper.js index 37075f29..e4e6df09 100644 --- a/helper.js +++ b/helper.js @@ -1,5 +1,5 @@ const { readFileSync, statSync } = require('fs'); -const { LambdaClient, PublishLayerVersionCommand, UpdateFunctionConfigurationCommand } = require('@aws-sdk/client-lambda'); +const { LambdaClient, PublishLayerVersionCommand, UpdateFunctionConfigurationCommand, ListFunctionsCommand } = require('@aws-sdk/client-lambda'); const { S3Client, PutObjectCommand, DeleteObjectCommand } = require('@aws-sdk/client-s3'); const non_error_response_codes = [200, 201, 204]; @@ -142,7 +142,38 @@ exports.refreshLambdaLayerVersion = async ({ FunctionName: functionName, Layers: [layerARN] }))); - const response = await Promise.all(commands); return response; +} + +/** + * List all the lambda functions that use the specified layer + */ +exports.listLambdaFunctionsWithLayer = async ({ + region, + accessKeyId, + secretAccessKey, + layerARN +}) => { + try { + const client = lambdaClient({ region, accessKeyId, secretAccessKey }); + + const allFunctions = []; + let nextMarker = null; + do { + const listFunctionsCommand = new ListFunctionsCommand({ Marker: nextMarker }); + const { Functions: functions, NextMarker: nextPageMarker } = await client.send(listFunctionsCommand); + + allFunctions.push(...functions); + nextMarker = nextPageMarker; + } while (nextMarker); + + const layerARNWithoutVersion = layerARN.split(':').slice(0, -1).join(':') + const matchinFunctions = allFunctions.filter((func) => func.Layers && func.Layers.some((layer) => layer.Arn.includes(layerARNWithoutVersion))) + const functionNames = matchinFunctions.map((func) => func.FunctionName); + return functionNames; + } catch (error) { + console.error("Error:", error); + return []; + } } \ No newline at end of file diff --git a/index.js b/index.js index 9b2c1963..4835a5fe 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,8 @@ const { publishS3LayerArchive, getArchiveSize, deleteTemporaryArchiveFromS3, - refreshLambdaLayerVersion + refreshLambdaLayerVersion, + listLambdaFunctionsWithLayer } = require('./helper'); @@ -20,10 +21,11 @@ const { const architectures = getInput('architectures') ? JSON.parse(getInput('architectures')) : []; const s3Bucket = getInput('s3_bucket'); const functionNames = JSON.parse(getInput('functions')); - + const autoUpdate = getInput('auto_update') || false; + console.log(runtimes, architectures); const creds = { region, accessKeyId, secretAccessKey }; - + const size = getArchiveSize(archive); console.log(`Archive size is ${size}`); let layerResponse; @@ -75,6 +77,20 @@ const { layerARN: layerResponse.LayerVersionArn }); } + if (autoUpdate) { + // find automatically all matching functions + const foundFunctionNames = await listLambdaFunctionsWithLayer({ + ...creds, + layerARN: layerResponse.LayerVersionArn, + }) + console.log('The following functions will be updated :', foundFunctionNames) + // trigger functions update + await refreshLambdaLayerVersion({ + ...creds, + functionNames: foundFunctionNames, + layerARN: layerResponse.LayerVersionArn + }); + } } catch (err) { setFailed(err.message); }