AWS Developer Blog

Deploying .NET Web Applications Using AWS CodeDeploy with Visual Studio Team Services

Today’s post is from AWS Solution Architect Aravind Kodandaramaiah.

We recently announced the new AWS Tools for Microsoft Visual Studio Team Services. In this post, we show you how you can use these tools to deploy your .NET web applications from Team Services to Amazon EC2 instances by using AWS CodeDeploy.

We don’t cover setting up the tools in Team Services in this post. We assume you already have a Team Services account or are using an on-premises TFS instance. We also assume you know how to push your source code to the repository used in your Team Services build. You can use the AWS tasks in build or in release definitions. For simplicity, this post shows you how to use the tasks in a build definition.

AWS CodeDeploy is a service that automates code deployments to any instance, including Amazon EC2 instances and instances running on-premises. AWS CodeDeploy makes it easier for you to rapidly release new features, helps you avoid downtime during deployment, and handles the complexity of updating your applications. You can use AWS CodeDeploy to automate deployments, eliminating error-prone manual operations. The service also scales with your infrastructure, so you can easily deploy to one instance or a thousand.

Setting up an AWS environment

Before we get started configuring a build definition within Team Services, we need to set up an AWS environment. Follow these steps to set up the AWS environment to enable deployments using the AWS CodeDeploy Application Deployment task with Team Services.

  1. Provision an AWS Identity and Access Management (IAM) user. See the AWS documentation for how to prepare IAM users to use AWS CodeDeploy. We’ll configure the access key ID and secret key ID of this IAM user within Team Services to initiate the deployment.
  2. Create a service role for AWS CodeDeploy. See the AWS documentation for details about how to create a service role for AWS CodeDeploy. This service role provides AWS CodeDeploy access to your AWS resources for deployment.
  3. Create an IAM instance profile for EC2 instances. See the AWS documentation for details about how to create IAM instance profiles. An IAM instance profile provides applications running within an EC2 instance access to AWS services.
  4. Launch, tag, and configure EC2 instances. Follow these instructions for launching and configuring EC2 instances to work with AWS CodeDeploy. We’ll use these EC2 Instances to run the deployed application.
  5. Create an Amazon S3 bucket to store application revisions. See the AWS documentation for details about creating S3 buckets.
  6. Create an AWS CodeDeploy application and a deployment group. After you configure instances, but before you can deploy a revision, you must create an application and deployment group in AWS CodeDeploy. AWS CodeDeploy uses a deployment group to identify EC2 instances that need the application to be deployed. Tags help group EC2 instances into a deployment group.

We’ve outlined the manual steps to create the AWS environment. However, it’s possible to completely automate creation of such AWS environments by using AWS CloudFormation, and this is the recommended approach. AWS CloudFormation enables you to represent infrastructure as code and to perform predictable, repeatable, and automated deployments. This enables you to control and track changes to your infrastructure.

Setting up an AWS CodeDeploy environment

In our Git repository in Team Services, we have an ASP.NET web application, the AWS CodeDeploy AppSpec file, and a few deployment PowerShell scripts. These files are located at the root of the repo, as shown below.

The appspec.yml file is a YAML-formatted file that AWS CodeDeploy uses to determine the artifacts to install and the lifecycle events to run. You must place it in the root of an application’s source code directory structure. Here’s the content of the sample appspec.yml file.

version: 0.0
os: windows
files:
  - source: \
    destination: C:\temp\WebApp\MusicWorld
  
hooks:
  BeforeInstall:
    - location: .\StageArtifact.ps1
    - location: .\CreateWebSite.ps1

AWS CodeDeploy executes the PowerShell scripts before copying the revision files to the final destination folder. These PowerShell scripts register the web application with IIS, and copy the application files to the physical path associated with the IIS web application.

The StageArtifacts.ps1 file is a PowerShell script that unpacks the Microsoft Web Deploy (msdeploy) web artifact, and copies the application files to the physical path that is associated with the IIS web application.

$target = "C:\inetpub\wwwroot\MusicWorld\" 

function DeleteIfExistsAndCreateEmptyFolder($dir )
{
    if ( Test-Path $dir ) {    
           Get-ChildItem -Path  $dir -Force -Recurse | Remove-Item -force –
							  recurse
           Remove-Item $dir -Force
    }
    New-Item -ItemType Directory -Force -Path $dir
}
# Clean up target directory
DeleteIfExistsAndCreateEmptyFolder($target )

# msdeploy creates a web artifact with multiple levels of folders. We only need the content 
# of the folder that has Web.config within it 
function GetWebArtifactFolderPath($path)
{
    foreach ($item in Get-ChildItem $path)
    {   
        if (Test-Path $item.FullName -PathType Container)
        {   
            # return the full path for the folder which contains Global.asax
            if (Test-Path ($item.fullname + "\Global.asax"))
            {
                #$item.FullName
                return $item.FullName;
            }
            GetWebArtifactFolderPath $item.FullName
        }
    }
}

$path = GetWebArtifactFolderPath("C:\temp\WebApp\MusicWorld")
$path2 = $path + "\*"
Copy-Item $path2 $target -recurse -force

The CreateWebSite.ps1 file is a PowerShell script that creates a web application in IIS.

New-WebApplication -Site "Default Web Site" -Name MusicWorld -PhysicalPath c:\inetpub\wwwroot\MusicWorld -Force

Setting up the build definition for an ASP.NET web application

The AWS CodeDeploy Application Deployment task in the AWS Tools for Microsoft Visual Studio Team Services supports deployment of any type of application, as long as you register the deployment script in the appspec.yml file. In this post, we deploy ASP.NET applications that are packaged as a Web Deploy archive.

We use the ASP.NET build template to get an ASP.NET application built and packaged as a Web Deploy archive.

Be sure to set up the following MSBuild arguments within the Build Solution task.

/p:WebPublishMethod=Package /p:PackageAsSingleFile=false /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactstagingdirectory)\\publish\\application"

Remove the Publish Artifacts task from the build pipeline, as the build artifacts will be uploaded into Amazon S3 by the AWS CodeDeploy Application Deployment task.

Now that our application has been built using MSBuild, we need to copy the appspec.yml file and the PowerShell deployment scripts to the root of the publish folder. This is so that AWS CodeDeploy can find the appspec.yml file at the root of the application folder.

Add a new Copy Files task. Choose Add Task, and then search for “Copy”. On the found task, choose Add to include the task in the build definition.

Configure this task to copy the appspec.yml file and the PowerShell scripts to the parent folder of the “packagelocation” defined within the Build Solution task. This step allows the AWS CodeDeploy Application Deployment task to zip up the contents of the revision bundle recursively before uploading the archive to Amazon S3.

Next, add the AWS CodeDeploy Application Deployment task. Choose Add Task, and then search for “CodeDeploy”. On the found task, choose Add to include the task in the build definition.

For the AWS CodeDeploy Application Deployment task, make the following configuration changes:

  • AWS Credentials – The AWS credentials used to perform the deployment. Our previous post on the Team Services tools discusses setting up AWS credentials in Team Services. We recommend that the credentials be those for an IAM user, with a policy that enables the user to perform an AWS CodeDeploy deployment.
  • AWS Region – The AWS Region that AWS CodeDeploy is running in.
  • Application Name – The name of the AWS CodeDeploy application.
  • Deployment Group Name – The name of the deployment group to deploy to.
  • Revision Bundle – The artifacts to deploy. You can supply a folder or a file name to this parameter. If you supply a folder, the task will zip the contents of the folder recursively into an archive file before uploading the archive to Amazon S3. If you supply a file name, the task uploads it, unmodified, to Amazon S3. Note that AWS CodeDeploy requires the appspec.yml file describing the application to be located at the root of the specified folder or archive file.
  • Bucket Name – The name of the bucket to which the revision bundle will be uploaded. The target Amazon S3 bucket must exist in the same AWS Region as the target instance.
  • Target Folder – Optional folder (key prefix) for the uploaded revision bundle in the bucket. If you don’t specify a target folder, the bundle will be uploaded to the root of the bucket.

Now that we’ve configured all the tasks, we’re ready to deploy to Amazon EC2 instances using AWS CodeDeploy. If you queue a build now, you should see output similar to this for the deployment.

Next, navigate to the AWS CodeDeploy console and choose Deployments. Choose the deployment that AWS CodeDeploy completed to view the deployment progress. In this example, the web application has been deployed to all the EC2 instances within the deployment group.

If your AWS CodeDeploy application was created with a load balancer, you can verify the web application deployment by navigating to the DNS name of the load balancer using a web browser.

Conclusion

We hope Visual Studio Team Services users find the AWS CodeDeploy Application Deployment task helpful and easy to use. We also appreciate hearing your feedback on our GitHub repository for these Team Services tasks.