In this module, you'll enhance the AWS CodePipeline that you built in Module 2 to add integration tests, and a Beta environment in which to test them.
To add integration tests to the pipeline, a second test application has been introduced to the Unicorn API project. Like the Unicorn API, the Test application consists of Lamdba Functions and a SAM CloudFormation template (test-sam.yaml
). In addition to the Lambda Functions and SAM template updates to the Unicorn API, the AWS CodeBuild buildspec.yml
has been modified to include a second set of commands that mirror the original application deployment. These commands install test dependencies, package the test SAM template, and include the test output SAM template as an additional artifact.
The integration test use a library for API testing, hippie, which includes a DSL for the easy description of HTTP requests. The test/test.js
defines a series of requests that excercise the Unicorn API REST resources, which are chained together using Javascript Promises. Below is a code snippet showing the chained Promises to execute the test cases. If all tests pass successfully, the function uses the injected CodePipeline Job Id to send a success callback, signaling the CodePipeline to transition. If any of the tests fail, a failure callback is sent, signaling the CodePipeline to halt.
exports.lambda_handler = (event, context, callback) => {
var api = event.api_url + '/unicorns/';
var unicorn = build_unicorn();
Promise.resolve()
.then(result => {
return list_unicorns(api, unicorn);
})
.then(result => {
return update_unicorn(api, unicorn);
})
.then(result => {
return view_unicorn_found(api, unicorn);
})
.then(result => {
return view_unicorn_not_found(api, unicorn);
})
.then(result => {
return remove_unicorn(api, unicorn);
})
.then(result => {
console.log('SUCCESS');
complete_job(event.job_id, result, callback);
})
.catch(reason => {
console.log('ERROR: ' + reason.test_name + ' | ' + reason.message);
fail_job(event.job_id, reason, context.invokeid, callback);
});
};
The test.js
script is focused on defining and executing the API integration tests. The test/setup.js
script is responsible for querying the CloudFormation Stack to auto-discover the API URL to send to the test.js
for test execution. After the API URL is discovered, the setup.js
script asynchronously invokes the test.js
Lambda Function, injecting the CodePipeline Job Id and API URL, as seen in the code snippet below.
exports.lambda_handler = (event, context, callback) => {
var job_id = event["CodePipeline.job"].id;
var stack_name = event["CodePipeline.job"].data.actionConfiguration.configuration.UserParameters;
get_api_url(stack_name).then(function(api_url) {
return invoke_test(job_id, api_url);
}).catch(function(err) {
fail_job(job_id, err, context.invokeid, callback);
});
};
In this module, you will update the CodePipeline you built in Module 2 with two new stages that are ordered between the Build and Prod stages. Like the Prod stage, the new Test stage will include two actions that use the test output SAM template artifact from CodeBuild to Create and Execute a CloudFormation Change Set to deploy the Lambda functions as a new CloudFormation Stack.
Following the Test stage, you will add a Beta stage that includes two actions that creates a new CloudFormation Stack for the Unicorn API in a new environment for testing. After the CloudFormation has been deployed, a third action will invoke a Lambda function from the Test application to drive integration tests against the Beta Unicorn API. If the tests pass, the pipeline will transition to the Prod stage to complete the Unicorn API changes in the Prod environment.
Below is an image depicting the CodePipeline upon completion:
Each of the following sections provide an implementation overview and detailed, step-by-step instructions. The overview should provide enough context for you to complete the implementation if you're already familiar with the AWS Management Console or you want to explore the services yourself without following a walkthrough.
If you're using the latest version of the Chrome, Firefox, or Safari web browsers the step-by-step instructions won't be visible until you expand the section.
CodeStar generates IAM Roles and Policies that control access to AWS resources. In this module, we will add permissions to Roles using IAM Managed Policies to support the customizations we will make to the CodePipeline pipeline by adding additional deployment environments and serverless unit testing.
-
In the AWS Management Console choose Services then select IAM under Security, Identity & Compliance.
-
Select Role in the left navigation, type
CodeStarWorker-uni-api-Lambda
in the filter text box, and click the Role name link in the Role table. -
On the Role Summary page, click the Attach Policy button in the Managed Policies section of the Permissions tab.
-
Type
AWSCodePipelineCustomActionAccess
in the filter text box, select the checkbox next to the AWSCodePipelineCustomActionAccess Managed Policy. -
Type
AWSCloudFormationReadOnlyAccess
in the filter text box, select the checkbox next to the AWSCloudFormationReadOnlyAccess Managed Policy. -
Type
AmazonDynamoDBFullAccess
in the filter text box, select the checkbox next to the AmazonDynamoDBFullAccess Managed Policy, and click the Attach Policy button. -
Type
AWSLambdaRole
in the filter text box, select the checkbox next to the AWSLambdaRole Managed Policy, and click the Attach Policy button. -
The Role Summary will now include the AWSCodePipelineCustomActionAccess, AWSCloudFormationReadOnlyAccess, and AWSLambdaRole policies in the list of Managed Policies.
-
In the AWS Management Console choose Services then select IAM under Security, Identity & Compliance.
-
Select Role in the left navigation, type
CodeStarWorker-uni-api-CodePipeline
in the filter text box, and click the Role name link in the Role table. -
On the Role Summary page, click the Attach Policy button in the Managed Policies section of the Permissions tab.
-
Type
AWSCodePipelineReadOnlyAccess
in the filter text box, select the checkbox next to the AWSCodePipelineReadOnlyAccess Managed Policy. -
Type
AWSLambdaRole
in the filter text box, select the checkbox next to the AWSLambdaRole Managed Policy and click the Attach Policy button. -
The Role Summary will now include the AWSCodePipelineReadOnlyAccess and AWSLambdaRole policies in the list of Managed Policies.
-
Click Edit Policy for the
CodeStarWorkerCodePipelineRolePolicy
in the Inline Policies section. -
Update the allowed CloudFormation Resource pattern in the policy (substitute your AWS Region and AccountId) a click Apply Policy.
Before:
arn:aws:cloudformation:{region}:{accountId}:stack/awscodestar-uni-api-lambda/*
After:
arn:aws:cloudformation:{region}:{accountId}:stack/awscodestar-uni-api-lambda*
-
Each module has corresponding source code used to seed the CodeStar CodeCommit Git repository to support the workshop. To seed the CodeCommit Git repository, click on the Launch Stack button for your region below:
Region Launch US East (N. Virginia) US West (N. California) US West (Oregon) EU (Ireland) EU (Frankfurt) Asia Pacific (Sydney) -
The CloudFormation template has been prepopulated with the necessary fields for this module. No changes are necessary
-
Select the I acknowledge that AWS CloudFormation might create IAM resources. checkbox to grant CloudFormation permission to create IAM resources on your behalf
-
Click the Create button in the lower right corner of the browser window to create the CloudFormation stack and seed the CodeCommit repository.
-
There will be a short delay as the Git repository seeded with the new source code. Upon successful completion, the CloudFormation will show Status
CREATE_COMPLETE
.
Now that the CodeCommit Git repository has been seeded with new source code, you will need to fetch the changes locally so that you may modify the code. Typically, this is accomplished using the git pull
command, however for the workshop we have replaced the repository with a new history and different Git commands will be used.
Using your preferred Git client, run the commands on your local uni-api Git repository:
git fetch --all
git reset --hard origin/master
-
In the AWS Management Console choose Services then select CodeStar under Developer Tools.
-
Select the
uni-api
project -
Click on the AWS CodePipeline details link at the bottom of the Continuous deployment tile on the right of the browser window.
-
On the CodePipeline page, click Edit.
-
Choose
+Action
belowTest
. -
In the Add action dialog, select
Deploy
for the Action category. -
Enter
GenerateChangeSet
for the Action name. -
Select
AWS CloudFormation
for the Deployment provider. -
Select
Create or replace a change set
for Action mode -
Enter
awscodestar-uni-api-lambda-test
for Stack name -
Enter
pipeline-changeset
for Change set name -
Enter
uni-api-BuildArtifact::test-template-export.yml
for Template -
Select
CAPABILITY_IAM
for Capabilities -
Enter
CodeStarWorker-uni-api-CloudFormation
for Role name -
Expand the Advanced section and enter
{ "ProjectId": "uni-api" }
for Parameter overrides -
Enter
uni-api-BuildArtifact
for Input artifacts #1 -
Choose Add Action
-
Choose
+Action
belowGenerateChangeSet
. -
In the Add action dialog, select
Deploy
for the Action category. -
Enter
ExecuteChangeSet
for the Action name. -
Select
AWS CloudFormation
for the Deployment provider. -
Select
Execute a change set
for Action mode -
Enter
awscodestar-uni-api-lambda-test
for Stack name -
Enter
pipeline-changeset
for Change set name -
Choose Add Action
The pipeline should look like the following screenshot after adding the new Test stage.
-
Scroll to the top of the pipeline and choose
Save pipeline changes
-
Choose
Save and Continue
when prompted by the Save Pipeline Changes dialog.
The addition of the Test stage is complete. You will now validate the Test stage is working by triggering the pipeline execution, and then monitoring the completion of the pipeline.
-
Choose the Release change button to start the pipeline.
-
Choose Release when prompted by the dialog box.
-
From the AWS Management Console, click on Services and then select CodePipeline in the Developer Tools section.
-
Choose
uni-api-Pipeline
from the list of pipelines. -
Observe that each stage's color will turn blue during execution and green on completion. Following the successful execution of all stages, the pipeline should look like the following screenshot.
-
In the AWS Management Console choose Services then select CodeStar under Developer Tools.
-
Select the
uni-api
project -
Click on the AWS CodePipeline details link at the bottom of the Continuous deployment tile on the right of the browser window.
-
On the CodePipeline page, click Edit.
-
Choose
+Action
belowBeta
. -
In the Add action dialog, select
Deploy
for the Action category. -
Enter
GenerateChangeSet
for the Action name. -
Select
AWS CloudFormation
for the Deployment provider. -
Select
Create or replace a change set
for Action mode -
Enter
awscodestar-uni-api-lambda-beta
for Stack name -
Enter
pipeline-changeset
for Change set name -
Enter
uni-api-BuildArtifact::template-export.yml
for Template -
Select
CAPABILITY_IAM
for Capabilities -
Enter
CodeStarWorker-uni-api-CloudFormation
for Role name -
Expand the Advanced section and enter
{ "ProjectId": "uni-api", "CustomSuffix": "-beta" }
for Parameter overrides -
Enter
uni-api-BuildArtifact
for Input artifacts #1 -
Choose Add Action
-
Choose
+Action
belowGenerateChangeSet
. -
In the Add action dialog, select
Deploy
for the Action category. -
Enter
ExecuteChangeSet
for the Action name. -
Select
AWS CloudFormation
for the Deployment provider. -
Select
Execute a change set
for Action mode -
Enter
awscodestar-uni-api-lambda-beta
for Stack name -
Enter
pipeline-changeset
for Change set name -
Choose Add Action
-
Choose
+Action
belowExecuteChangeSet
. -
In the Add action dialog, select
Invoke
for the Action category. -
Enter
InvokeLambdaTestFunction
for the Action name. -
Select
AWS Lambda
for the Deployment provider. -
Enter
uni-api-test-setup
for Function name. -
Enter
awscodestar-uni-api-lambda-beta
for User parameters. -
Choose Add Action
The pipeline should look like the following screenshot after adding the new Test stage.
-
Scroll to the top of the pipeline and choose
Save pipeline changes
-
Choose
Save and Continue
when prompted by the Save Pipeline Changes dialog.
The addition of the Beta stage is complete. You will now validate the Beta stage is working by triggering a release of the current change.
-
Choose the Release change button to start the pipeline.
-
Choose Release when prompted by the dialog box.
-
From the AWS Management Console, click on Services and then select CodePipeline in the Developer Tools section.
-
Choose
uni-api-Pipeline
from the list of pipelines. -
Observe that each stage's color will turn blue during execution and green on completion. You should see that the
InvokeLambdaTestFunction
action in theBeta
stage fails, causing the stage to turn red, like the following image. -
Choose the Details link in the failed action to see the details of the failed job.
The test_list_unicorns
integration test has failed! Next, let's locate and fix the bug.
- On your workstation, open the
uni-api/app/list.js
file and naviagte to line 17, which should look like the following code snippet:
docClient.scan(params, function(error, data) {
// Comment or Delete the following line of code to remove simulated error
error = Error("something is wrong");
-
Comment or delete Line 17 to fix the code bug
-
Save the
uni-api/app/list.js
file.
-
Using your Git client, add the local changes to the Git index, and commit with a message. For example:
%> git add . %> git commit -m "Fix bug"
-
Using your Git client, push the Git repository updates to the origin. For example:
%> git push origin
-
From the AWS Management Console, click on Services and then select CodePipeline in the Developer Tools section.
-
Choose
uni-api-Pipeline
from the list of pipelines. -
Observe that each stage's color will turn blue during execution and green on completion. You should see that the
InvokeLambdaTestFunction
in theBeta
stage passes, causing the stage to turn green, like the following image.
Following the successful execution of all stages, the pipeline should look like the following screenshot.
Congratulations, you've successfully completed the Multiple Environment CI/CD Pipeline Module!