Skip to content

Commit

Permalink
Add task def arn options
Browse files Browse the repository at this point in the history
  • Loading branch information
muzfuz committed Jul 6, 2023
1 parent 3fc15eb commit cb59e6a
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 68 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ name: "CodeQL"

on:
push:
branches: [master]
branches: [main]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
branches: [main]
schedule:
- cron: '0 0 * * 2'

Expand Down
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ inputs:
run-task-started-by:
description: "A name to use for the startedBy tag when running a task outside of a service. Will default to 'GitHub-Actions'."
required: false
run-task-use-arn:
description: "If true will use an existing ARN passed in to the `task-definition`. Be careful when using this to ensure that the container already has been deployed somewhere."
required: false
wait-for-task-stopped:
description: 'Whether to wait for the task to stop when running it outside of a service. Will default to not wait.'
required: false
Expand Down
44 changes: 26 additions & 18 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
const subnetIds = core.getInput('run-task-subnets', { required: false }) || '';
const securityGroupIds = core.getInput('run-task-security-groups', { required: false }) || '';
const containerOverrides = JSON.parse(core.getInput('run-task-container-overrides', { required: false }) || '[]');
core.info(`Running task with settings: ${containerOverrides}`)
core.info(`Running task with settings: ${JSON.stringify(containerOverrides[0])}`)
let awsvpcConfiguration = {}

if (subnetIds != "") {
Expand All @@ -44,7 +44,7 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
if (securityGroupIds != "") {
awsvpcConfiguration["securityGroups"] = securityGroupIds.split(',')
}

console.log(awsvpcConfiguration)
const runTaskResponse = await ecs.runTask({
startedBy: startedBy,
cluster: clusterName,
Expand Down Expand Up @@ -373,23 +373,31 @@ async function run() {
const forceNewDeployInput = core.getInput('force-new-deployment', { required: false }) || 'false';
const forceNewDeployment = forceNewDeployInput.toLowerCase() === 'true';

// Register the task definition
core.debug('Registering the task definition');
const taskDefPath = path.isAbsolute(taskDefinitionFile) ?
taskDefinitionFile :
path.join(process.env.GITHUB_WORKSPACE, taskDefinitionFile);
const fileContents = fs.readFileSync(taskDefPath, 'utf8');
const taskDefContents = maintainValidObjects(removeIgnoredAttributes(cleanNullKeys(yaml.parse(fileContents))));
let registerResponse;
try {
registerResponse = await ecs.registerTaskDefinition(taskDefContents).promise();
} catch (error) {
core.setFailed("Failed to register task definition in ECS: " + error.message);
core.debug("Task definition contents:");
core.debug(JSON.stringify(taskDefContents, undefined, 4));
throw(error);
const shouldUseTaskARNInput = core.getInput('run-task-use-arn', { required: false }) || 'false';
const shouldUseTaskARN = shouldUseTaskARNInput.toLowerCase() === 'true';

// Register the task definition or use passed in ARN
let taskDefArn;
if (shouldUseTaskARN) {
taskDefArn = taskDefinitionFile;
} else {
core.debug('Registering the task definition');
const taskDefPath = path.isAbsolute(taskDefinitionFile) ?
taskDefinitionFile :
path.join(process.env.GITHUB_WORKSPACE, taskDefinitionFile);
const fileContents = fs.readFileSync(taskDefPath, 'utf8');
const taskDefContents = maintainValidObjects(removeIgnoredAttributes(cleanNullKeys(yaml.parse(fileContents))));
let registerResponse;
try {
registerResponse = await ecs.registerTaskDefinition(taskDefContents).promise();
} catch (error) {
core.setFailed("Failed to register task definition in ECS: " + error.message);
core.debug("Task definition contents:");
core.debug(JSON.stringify(taskDefContents, undefined, 4));
throw(error);
}
taskDefArn = registerResponse.taskDefinition.taskDefinitionArn;
}
const taskDefArn = registerResponse.taskDefinition.taskDefinitionArn;
core.setOutput('task-definition-arn', taskDefArn);

// Run the task outside of the service
Expand Down
42 changes: 25 additions & 17 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
if (securityGroupIds != "") {
awsvpcConfiguration["securityGroups"] = securityGroupIds.split(',')
}

console.log(awsvpcConfiguration)
const runTaskResponse = await ecs.runTask({
startedBy: startedBy,
cluster: clusterName,
Expand Down Expand Up @@ -367,23 +367,31 @@ async function run() {
const forceNewDeployInput = core.getInput('force-new-deployment', { required: false }) || 'false';
const forceNewDeployment = forceNewDeployInput.toLowerCase() === 'true';

// Register the task definition
core.debug('Registering the task definition');
const taskDefPath = path.isAbsolute(taskDefinitionFile) ?
taskDefinitionFile :
path.join(process.env.GITHUB_WORKSPACE, taskDefinitionFile);
const fileContents = fs.readFileSync(taskDefPath, 'utf8');
const taskDefContents = maintainValidObjects(removeIgnoredAttributes(cleanNullKeys(yaml.parse(fileContents))));
let registerResponse;
try {
registerResponse = await ecs.registerTaskDefinition(taskDefContents).promise();
} catch (error) {
core.setFailed("Failed to register task definition in ECS: " + error.message);
core.debug("Task definition contents:");
core.debug(JSON.stringify(taskDefContents, undefined, 4));
throw(error);
const shouldUseTaskARNInput = core.getInput('run-task-use-arn', { required: false }) || 'false';
const shouldUseTaskARN = shouldUseTaskARNInput.toLowerCase() === 'true';

// Register the task definition or use passed in ARN
let taskDefArn;
if (shouldUseTaskARN) {
taskDefArn = taskDefinitionFile;
} else {
core.debug('Registering the task definition');
const taskDefPath = path.isAbsolute(taskDefinitionFile) ?
taskDefinitionFile :
path.join(process.env.GITHUB_WORKSPACE, taskDefinitionFile);
const fileContents = fs.readFileSync(taskDefPath, 'utf8');
const taskDefContents = maintainValidObjects(removeIgnoredAttributes(cleanNullKeys(yaml.parse(fileContents))));
let registerResponse;
try {
registerResponse = await ecs.registerTaskDefinition(taskDefContents).promise();
} catch (error) {
core.setFailed("Failed to register task definition in ECS: " + error.message);
core.debug("Task definition contents:");
core.debug(JSON.stringify(taskDefContents, undefined, 4));
throw(error);
}
taskDefArn = registerResponse.taskDefinition.taskDefinitionArn;
}
const taskDefArn = registerResponse.taskDefinition.taskDefinitionArn;
core.setOutput('task-definition-arn', taskDefArn);

// Run the task outside of the service
Expand Down
89 changes: 58 additions & 31 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ describe('Deploy to ECS', () => {
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('') // run-task
.mockReturnValueOnce('') // run-task-use-arn
.mockReturnValueOnce('/hello/appspec.json') // codedeploy-appspec
.mockReturnValueOnce('MyApplication') // codedeploy-application
.mockReturnValueOnce('MyDeploymentGroup'); // codedeploy-deployment-group
Expand Down Expand Up @@ -1216,14 +1217,12 @@ describe('Deploy to ECS', () => {

test('run task', async () => {
core.getInput = jest
.fn()
.mockReturnValueOnce('task-definition.json') // task-definition
.mockReturnValueOnce('') // service
.mockReturnValueOnce('') // cluster
.mockReturnValueOnce('') // wait-for-service-stability
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('true'); // run-task
.fn(input => {
return {
'task-definition': 'task-definition.json',
'run-task': 'true',
}[input];
});

await run();
expect(core.setFailed).toHaveBeenCalledTimes(0);
Expand All @@ -1236,20 +1235,19 @@ describe('Deploy to ECS', () => {

test('run task with options', async () => {
core.getInput = jest
.fn()
.mockReturnValueOnce('task-definition.json') // task-definition
.mockReturnValueOnce('') // service
.mockReturnValueOnce('somecluster') // cluster
.mockReturnValueOnce('') // wait-for-service-stability
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('true') // run-task
.mockReturnValueOnce('false') // wait-for-task-stopped
.mockReturnValueOnce('someJoe') // run-task-started-by
.mockReturnValueOnce('EC2') // run-task-launch-type
.mockReturnValueOnce('a,b') // run-task-subnet-ids
.mockReturnValueOnce('c,d') // run-task-security-group-ids
.mockReturnValueOnce(JSON.stringify([{ name: 'someapp', command: 'somecmd' }])); // run-task-container-overrides
.fn(input => {
return {
'task-definition': 'task-definition.json',
'cluster': 'somecluster',
'run-task': 'true',
'wait-for-task-stopped': 'false',
'run-task-started-by': 'someJoe',
'run-task-launch-type': 'EC2',
'run-task-subnets': 'a,b',
'run-task-security-groups': 'c,d',
'run-task-container-overrides': JSON.stringify([{ name: 'someapp', command: 'somecmd' }]),
}[input];
});

await run();
expect(core.setFailed).toHaveBeenCalledTimes(0);
Expand All @@ -1269,15 +1267,14 @@ describe('Deploy to ECS', () => {

test('run task and wait for it to stop', async () => {
core.getInput = jest
.fn()
.mockReturnValueOnce('task-definition.json') // task-definition
.mockReturnValueOnce('') // service
.mockReturnValueOnce('somecluster') // cluster
.mockReturnValueOnce('') // wait-for-service-stability
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('true') // run-task
.mockReturnValueOnce('true'); // wait-for-task-stopped
.fn(input => {
return {
'task-definition': 'task-definition.json',
'cluster': 'somecluster',
'run-task': 'true',
'wait-for-task-stopped': 'true',
}[input];
});

await run();
expect(core.setFailed).toHaveBeenCalledTimes(0);
Expand All @@ -1296,6 +1293,36 @@ describe('Deploy to ECS', () => {
});
});

test('run task with pre-existing ARN', async () => {
core.getInput = jest
.fn(input => {
return {
'task-definition': '123345758:task-definition:arn:123',
'service': 'service-456',
'cluster': 'cluster-789',
'wait-for-service-stability': 'true',
'run-task': 'true',
'run-task-use-arn': 'true',
'wait-for-task-stopped': 'true',
}[input];
});

await run();
expect(core.setFailed).toHaveBeenCalledTimes(0)
expect(mockEcsRegisterTaskDef).toHaveBeenCalledTimes(0);
expect(core.setOutput).toHaveBeenNthCalledWith(1, 'task-definition-arn', '123345758:task-definition:arn:123')
expect(mockRunTask).toHaveBeenCalledTimes(1);
expect(core.setOutput).toHaveBeenNthCalledWith(2, 'run-task-arn', ["arn:aws:ecs:fake-region:account_id:task/arn"])
expect(mockEcsWaiter).toHaveBeenNthCalledWith(1, 'tasksStopped', {
tasks: ['arn:aws:ecs:fake-region:account_id:task/arn'],
cluster: 'cluster-789',
"$waiter": {
"delay": 15,
"maxAttempts": 120,
},
});
});

test('error caught if AppSpec file is not formatted correctly', async () => {
mockEcsDescribeServices.mockImplementation(() => {
return {
Expand Down

0 comments on commit cb59e6a

Please sign in to comment.