In the initial installment of this series, we explored the deployment of ASP.NET Core applications utilizing an Amazon EC2 instance and AWS CodeDeploy, where every push to GitHub was directly deployed to the live environment without any validation. In this second part, we will delve into how to establish an AWS environment for our ASP.NET Core application that incorporates quality control while leveraging the scalability of the AWS cloud infrastructure.
You can find the relevant code and setup scripts for this post in the part2 branch of the aws-blog-net-exploring-aspnet-core repository.
Validating the Deployment
Previously, the appspec.yml
file instructed the InstallApp.ps1
script to execute during the ApplicationStart hook to extract the application and configure IIS. To ensure that the application is functioning correctly, we will modify the appspec.yml
file to invoke the ValidateInstall.ps1
script during the ValidateService hook.
version: 0.0
os: windows
files:
- source:
destination: C:ExploringAspNetCore
hooks:
ApplicationStop:
- location: .RemoveApp.ps1
timeout: 30
ApplicationStart:
- location: .InstallApp.ps1
timeout: 300
ValidateService:
- location: .ValidateInstall.ps1
timeout: 300
This script enables us to conduct tests to confirm our application is operating as expected. In the GitHub repository, I included several xunit tests within .SampleAppsrcSmokeTests
. The sample application is a simple “Hello World” web app, so the main test is to verify that a web request to the application returns a valid response. In a production scenario, you would ideally have a comprehensive suite of tests to execute during this validation phase.
Next, let’s examine ValidateInstall.ps1
to understand how the tests are executed.
sl C:ExploringAspNetCoreSampleAppsrcSmokeTests
# Restore the nuget references
& "C:Program Filesdotnetdotnet.exe" restore
# Run the smoke tests
& "C:Program Filesdotnetdotnet.exe" test
exit $LastExitCode
To execute the tests, navigate to the directory containing the tests, restore dependencies, and run the dotnet test
command. If any tests fail, dnx
will return a non-zero exit code, which will be relayed from the PowerShell script. AWS CodeDeploy will recognize the failed exit code and flag the deployment as unsuccessful. Logs from the test run can be accessed via the AWS CodeDeploy console for troubleshooting.
Utilizing AWS CodePipeline
Now that we are running smoke tests during deployments, we can identify failures effectively. To further safeguard against flawed deployments affecting users, it is advisable to implement a pipeline that includes a beta stage for running smoke tests. Only after a successful beta phase should we promote to production. This method provides continuous delivery with necessary safety checks. As highlighted in part 1, ASP.NET Core’s capability to run from source means there’s no need to configure a build step in our pipeline. Pipelines can source from either Amazon S3 or GitHub. To offer a complete example that can be established using only a PowerShell script, we will utilize S3 as the source for our pipeline. AWS CodePipeline will monitor S3 for new object versions to propagate through the pipeline. For details on configuring a GitHub repository, refer to the AWS CodePipeline User Guide.
Setup Script
The PowerShell script .EnvironmentSetupEnvironmentSetup.ps1
in the repository will set up the necessary AWS resources for deploying the application through a pipeline.
Note: To prevent charges for unused resources, be sure to execute .EnvironmentSetupEnvironmentTearDown.ps1
after testing.
The setup script provisions the following resources:
- An S3 bucket with a zipped archive as the initial deployment source.
- A t2.small EC2 instance for the beta environment.
- An Auto Scaling group with a load balancer using t2.medium instances.
- An AWS CodeDeploy application for beta utilizing the t2.small EC2 instance.
- An AWS CodeDeploy application for production leveraging the Auto Scaling group.
- AWS CodePipeline, with the S3 bucket as the source and both beta and production stages configured to utilize the respective AWS CodeDeploy applications.
Upon completion of the script, it will display the public DNS for both the beta EC2 instance and production load balancer. You can monitor the pipeline’s progress in the AWS CodePipeline console to verify the success of the deployments in both stages.
The application was successfully deployed to both environments as the smoke tests passed during the AWS CodeDeploy deployments.
Handling Failed Deployments
Now, let’s investigate what occurs when a deployment fails. We can induce a test failure by modifying the .SampleAppsrcSmokeTestsWebsiteTests.cs
test file to introduce an error.
[Fact]
public async Task PassingTest()
{
using (var client = new HttpClient())
{
var response = await client.GetStringAsync("http://localhost-not-a-real-host/");
Assert.Equal("Exploring ASP.NET Core with AWS.", response);
}
}
In the repository, the .DeployToPipeline.ps1
script can be executed to zip the archive and upload it to the designated S3 location for the pipeline. This action will initiate a deployment to the beta environment (which will fail due to the erroneous test).
A production deployment will not occur because of the failure at the beta stage, thus maintaining the integrity of the production environment. To discern what went wrong, you can review the deployment logs via the AWS CodeDeploy console.
Conclusion
With AWS CodeDeploy and AWS CodePipeline, we can establish a comprehensive continuous delivery framework for deploying ASP.NET Core applications. Be sure to check out the GitHub repository for sample code and setup scripts. For further insights, visit this blog post that delves deeper into the subject. In the next entry of this series, we will explore the cross-platform capabilities of ASP.NET Core. For authoritative information on this topic, consider this resource. Additionally, here is an excellent resource for further guidance.
Leave a Reply