From f607d715fc98341f90063507bc6177649f44c7df Mon Sep 17 00:00:00 2001 From: Jerome Wolff Date: Wed, 13 Nov 2024 20:39:45 +0100 Subject: [PATCH] Remove AWS SDKv2 --- README.md | 2 +- action.yml | 2 +- dist/index.js | 67 +++++++++++++++++++++++++---------------------- index.js | 67 +++++++++++++++++++++++++---------------------- package-lock.json | 19 ++++++++++++-- 5 files changed, 89 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 9f5a226..611b389 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ Will pass the following command to the container on the AWS ECS Fargate task: | tail-logs | If set to true, will try to extract the logConfiguration for the first container in the task definition. If `override-container` is passed, it will extract the logConfiguration from that container. Tailing logs is only possible if the provided container uses the `awslogs` logDriver. | `false` | true | | task-wait-until-stopped | Whether to wait for the task to stop before finishing the action. If set to false, the action will finish immediately after the task reaches the `RUNNING` state (fire and forget). | `false` | true | | task-start-max-wait-time | How long to wait for the task to start (i.e. reach the `RUNNING` state) in seconds. If the task does not start within this time, the pipeline will fail. | `false` | 120 | -| task-stopped-max-wait-time | How long to wait for the task to stop (i.e. reach the `STOPPED` state) in seconds. The task will not be canceled after this time, the pipeline will just be marked as failed. | `false` | 300 | +| task-stop-max-wait-time | How long to wait for the task to stop (i.e. reach the `STOPPED` state) in seconds. The task will not be canceled after this time, the pipeline will just be marked as failed. | `false` | 300 | | task-check-state-delay | How long to wait between each AWS API call to check the current state of the task in seconds. This is useful to avoid running into AWS rate limits. **However**, setting this too high might cause the Action to miss the time-window your task is in the "RUNNING" state (if you task is very short lived) and can cause the action to fail. | `false` | 6 | diff --git a/action.yml b/action.yml index 035bbf0..f31bd9e 100644 --- a/action.yml +++ b/action.yml @@ -74,7 +74,7 @@ inputs: required: false default: 120 - task-stopped-max-wait-time: + task-stop-max-wait-time: description: >- How long to wait for the task to stop (i.e. reach the `STOPPED` state) in seconds. The task will not be canceled after this time, the pipeline will just be marked as failed. diff --git a/dist/index.js b/dist/index.js index 05501ab..0751527 100644 --- a/dist/index.js +++ b/dist/index.js @@ -56480,7 +56480,7 @@ const main = async () => { // Inputs: Waiters const taskWaitUntilStopped = core.getBooleanInput('task-wait-until-stopped', {required: false}); const taskStartMaxWaitTime = parseInt(core.getInput('task-start-max-wait-time', {required: false})); - const taskStoppedMaxWaitTime = parseInt(core.getInput('task-stopped-max-wait-time', {required: false})); + const taskStopMaxWaitTime = parseInt(core.getInput('task-stop-max-wait-time', {required: false})); const taskCheckStateDelay = parseInt(core.getInput('task-check-state-delay', {required: false})); // Build Task parameters @@ -56558,31 +56558,11 @@ const main = async () => { core.setOutput('task-id', taskId); core.info(`Starting Task with ARN: ${taskArn}\n`); - try { - core.debug(`Waiting for task to be in running state. Waiting for ${taskStartMaxWaitTime} seconds.`); - await waitUntilTasksRunning({ - client: ecs, - maxWaitTime: taskStartMaxWaitTime, - maxDelay: taskCheckStateDelay, - minDelay: taskCheckStateDelay, - }, {cluster, tasks: [taskArn]}); - } catch (error) { - core.setFailed(`Task did not start successfully. Error: ${error.name}. State: ${error.state}.`); - return; - } - - // If taskWaitUntilStopped is false, we can bail out here because we can not tail logs or have any - // information on the exitCodes or status of the task - if (!taskWaitUntilStopped) { - core.info(`Task is running. Exiting without waiting for task to stop.`); - return; - } - - // Get CWLogsClient + // Create CWLogsClient let CWLogClient = new CloudWatchLogsClient(); - // Only create logFilterStream if tailLogs is enabled, and we wait for the task to stop in the pipeline - if (tailLogs) { + // Only create StartLiveTailCommand if tailLogs is enabled, and we wait for the task to stop in the pipeline + if (tailLogs && taskWaitUntilStopped) { core.debug(`Logging enabled. Getting logConfiguration from TaskDefinition.`) let taskDef = await ecs.describeTaskDefinition({taskDefinition: taskDefinition}); taskDef = taskDef.taskDefinition @@ -56611,13 +56591,15 @@ const main = async () => { const logGroupIdentifier = `arn:aws:logs:${logRegion}:${accountId}:log-group:${logGroup}`; core.debug(`LogGroupARN for '${container.name}' is: '${logGroupIdentifier}'.`); + // We will use the full logStreamName as a prefix filter. This way the SDK will not crash + // if the logStream does not exist yet. const logStreamName = [container.logConfiguration.options['awslogs-stream-prefix'], container.name, taskId].join('/') // Start Live Tail try { const response = await CWLogClient.send(new StartLiveTailCommand({ logGroupIdentifiers: [logGroupIdentifier], - logStreamNames: [logStreamName] + logStreamNamePrefixes: [logStreamName] })); await handleCWResponseAsync(response); @@ -56632,10 +56614,30 @@ const main = async () => { } try { - core.debug(`Waiting for task to finish. Waiting for ${taskStoppedMaxWaitTime} seconds.`); + core.debug(`Waiting for task to be in running state. Waiting for ${taskStartMaxWaitTime} seconds.`); + await waitUntilTasksRunning({ + client: ecs, + maxWaitTime: taskStartMaxWaitTime, + maxDelay: taskCheckStateDelay, + minDelay: taskCheckStateDelay, + }, {cluster, tasks: [taskArn]}); + } catch (error) { + core.setFailed(`Task did not start successfully. Error: ${error.message}.`); + process.exit(1); + } + + // If taskWaitUntilStopped is false, we can bail out here because we can not tail logs or have any + // information on the exitCodes or status of the task + if (!taskWaitUntilStopped) { + core.info(`Task is running. Exiting without waiting for task to stop.`); + process.exit(0); + } + + try { + core.debug(`Waiting for task to finish. Waiting for ${taskStopMaxWaitTime} seconds.`); await waitUntilTasksStopped({ client: ecs, - maxWaitTime: taskStoppedMaxWaitTime, + maxWaitTime: taskStopMaxWaitTime, maxDelay: taskCheckStateDelay, minDelay: taskCheckStateDelay, }, { @@ -56643,12 +56645,14 @@ const main = async () => { tasks: [taskArn], }); } catch (error) { - core.setFailed(`Task did not stop successfully. Error: ${error.name}. State: ${error.state}.`); + core.setFailed(`Task did not stop successfully. Error: ${error.message}.`); } // Close LogStream and store output - CWLogClient.destroy(); - core.setOutput('log-output', logOutput); + if (typeof CWLogClient !== 'undefined') { + CWLogClient.destroy(); + core.setOutput('log-output', logOutput); + } // Describe Task to get Exit Code and Exceptions core.debug(`Process exit code and exception.`); @@ -56688,10 +56692,9 @@ async function handleCWResponseAsync(response) { } } catch (err) { // If we close the connection, we will get an error with message 'aborted' which we can ignore as it will - // just show as an error in the logs. + // just show as an error in the GHA logs. if (err.message === 'aborted') { core.debug("CWLiveTailSession aborted."); - return; } diff --git a/index.js b/index.js index bb1e9ba..7104bfd 100644 --- a/index.js +++ b/index.js @@ -32,7 +32,7 @@ const main = async () => { // Inputs: Waiters const taskWaitUntilStopped = core.getBooleanInput('task-wait-until-stopped', {required: false}); const taskStartMaxWaitTime = parseInt(core.getInput('task-start-max-wait-time', {required: false})); - const taskStoppedMaxWaitTime = parseInt(core.getInput('task-stopped-max-wait-time', {required: false})); + const taskStopMaxWaitTime = parseInt(core.getInput('task-stop-max-wait-time', {required: false})); const taskCheckStateDelay = parseInt(core.getInput('task-check-state-delay', {required: false})); // Build Task parameters @@ -110,31 +110,11 @@ const main = async () => { core.setOutput('task-id', taskId); core.info(`Starting Task with ARN: ${taskArn}\n`); - try { - core.debug(`Waiting for task to be in running state. Waiting for ${taskStartMaxWaitTime} seconds.`); - await waitUntilTasksRunning({ - client: ecs, - maxWaitTime: taskStartMaxWaitTime, - maxDelay: taskCheckStateDelay, - minDelay: taskCheckStateDelay, - }, {cluster, tasks: [taskArn]}); - } catch (error) { - core.setFailed(`Task did not start successfully. Error: ${error.name}. State: ${error.state}.`); - return; - } - - // If taskWaitUntilStopped is false, we can bail out here because we can not tail logs or have any - // information on the exitCodes or status of the task - if (!taskWaitUntilStopped) { - core.info(`Task is running. Exiting without waiting for task to stop.`); - return; - } - - // Get CWLogsClient + // Create CWLogsClient let CWLogClient = new CloudWatchLogsClient(); - // Only create logFilterStream if tailLogs is enabled, and we wait for the task to stop in the pipeline - if (tailLogs) { + // Only create StartLiveTailCommand if tailLogs is enabled, and we wait for the task to stop in the pipeline + if (tailLogs && taskWaitUntilStopped) { core.debug(`Logging enabled. Getting logConfiguration from TaskDefinition.`) let taskDef = await ecs.describeTaskDefinition({taskDefinition: taskDefinition}); taskDef = taskDef.taskDefinition @@ -163,13 +143,15 @@ const main = async () => { const logGroupIdentifier = `arn:aws:logs:${logRegion}:${accountId}:log-group:${logGroup}`; core.debug(`LogGroupARN for '${container.name}' is: '${logGroupIdentifier}'.`); + // We will use the full logStreamName as a prefix filter. This way the SDK will not crash + // if the logStream does not exist yet. const logStreamName = [container.logConfiguration.options['awslogs-stream-prefix'], container.name, taskId].join('/') // Start Live Tail try { const response = await CWLogClient.send(new StartLiveTailCommand({ logGroupIdentifiers: [logGroupIdentifier], - logStreamNames: [logStreamName] + logStreamNamePrefixes: [logStreamName] })); await handleCWResponseAsync(response); @@ -184,10 +166,30 @@ const main = async () => { } try { - core.debug(`Waiting for task to finish. Waiting for ${taskStoppedMaxWaitTime} seconds.`); + core.debug(`Waiting for task to be in running state. Waiting for ${taskStartMaxWaitTime} seconds.`); + await waitUntilTasksRunning({ + client: ecs, + maxWaitTime: taskStartMaxWaitTime, + maxDelay: taskCheckStateDelay, + minDelay: taskCheckStateDelay, + }, {cluster, tasks: [taskArn]}); + } catch (error) { + core.setFailed(`Task did not start successfully. Error: ${error.message}.`); + process.exit(1); + } + + // If taskWaitUntilStopped is false, we can bail out here because we can not tail logs or have any + // information on the exitCodes or status of the task + if (!taskWaitUntilStopped) { + core.info(`Task is running. Exiting without waiting for task to stop.`); + process.exit(0); + } + + try { + core.debug(`Waiting for task to finish. Waiting for ${taskStopMaxWaitTime} seconds.`); await waitUntilTasksStopped({ client: ecs, - maxWaitTime: taskStoppedMaxWaitTime, + maxWaitTime: taskStopMaxWaitTime, maxDelay: taskCheckStateDelay, minDelay: taskCheckStateDelay, }, { @@ -195,12 +197,14 @@ const main = async () => { tasks: [taskArn], }); } catch (error) { - core.setFailed(`Task did not stop successfully. Error: ${error.name}. State: ${error.state}.`); + core.setFailed(`Task did not stop successfully. Error: ${error.message}.`); } // Close LogStream and store output - CWLogClient.destroy(); - core.setOutput('log-output', logOutput); + if (typeof CWLogClient !== 'undefined') { + CWLogClient.destroy(); + core.setOutput('log-output', logOutput); + } // Describe Task to get Exit Code and Exceptions core.debug(`Process exit code and exception.`); @@ -240,10 +244,9 @@ async function handleCWResponseAsync(response) { } } catch (err) { // If we close the connection, we will get an error with message 'aborted' which we can ignore as it will - // just show as an error in the logs. + // just show as an error in the GHA logs. if (err.message === 'aborted') { core.debug("CWLiveTailSession aborted."); - return; } diff --git a/package-lock.json b/package-lock.json index 2f296ff..e57ca32 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3370,6 +3370,20 @@ "dev": true, "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "dev": true, @@ -4417,9 +4431,10 @@ "license": "MIT" }, "node_modules/micromatch": { - "version": "4.0.7", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, - "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1"