The key to delivering software more rapidly and more frequently is having a continuous delivery process which makes deploying your application as easy as pushing a button. When it's easy to deploy your application, bugfixes and new features end up in production way faster and in a more agile way than the old fashion way of manually creating a package and handing it over to someone from the ops team who would then deploy it to the requested environment.
Delivering software the old fashion way is often prone to human error and takes a lot more time forcing developers to create bigger releases with a larger number of features and bugfixes which in turn also takes more time. This is obviously bad for business because end-users will have to wait much longer to be able to enjoy new releases, and in the meantime they could be getting frustrated by potential bugs which aren't going to be resolved very quickly.
The main goal is to be able to deploy our application by the click of a button. To do that, we're going to be using Jenkins and add a deployment process to our previous CI job to deploy our application to Microsoft Azure.
- Follow my previous blogpost to create a continuous integration job using Jenkins.
- Create a Microsoft Azure Account.
- Create a new Azure App Service in the Azure portal.
- Create a shared network location or setup an Artifact Repository to store the build artifact.
- Install the Promoted Builds plugin for Jenkins.
We're going to use the Promoted Builds plugin to create a build artifact of our application and deploy it to Azure via Web Deploy. Because the Azure App Service we've created already supports Web Deploy, there is no need to install it. In this case Azure is our production environment. I recommend also having a development, test and acceptance environment to be able to test and preview your application before it gets deployed to production.
Because we're creating a build artifact, it is wise to store that artifact in a binary repository or on a shared location. This way you're not only able to keep track of all your releases, but also to rollback a previous version. There are a few good repositories out there such as Archiva, Artifactory, Nexus and Package Drone. Here is a good comparison chart for you to decide which repository suits you best.
Step 1: Create a promotion process
Navigate using your favorite browser to the Jenkins job you've created and tick the
Promote builds when... checkbox. The following section appears:
In this case we're going to create the process of deploying our application to a production environment so the name of this process is going to be
Production. Tick the
Only when manually approved checkbox because we don't want to trigger the process automatically.
Typically you can tick the
Promote immediately once the build is complete checkbox for a development promotion process. This means that when a build is succeeded and all unit tests pass, a build artifact is created immediately and is then deployed to the development environment.
If you have multiple promotion processes, i recommend ticking the
When the following upstream promotions are promoted checkbox and fill in the previous promotion process name (e.g.
Acceptance) that has to be successfully executed before being able to approve the next promotion process. This way you will force your application being deployed to other environments first such as development, test and acceptance before reaching production. An example would be
Development > Test > Acceptance > Production.
Step 2: Create a build artifact
To create a build artifact click the
Add action button in the
Actions region of your promotion process and select
Build a Visual Studio project or solution using MSBuild:
This step is almost equal to our build step which we created in our CI process, but now we're going to create a web deploy package in stead of compiling the solution. To create that package, we have to add a few command line arguments:
/T:Clean;Build;Packageto create a Web Deploy package.
/p:Configuration=Releaseto use the release configuration.
/p:OutputPath="obj\Release"to put the artifact in the obj\Release folder of the current project.
/p:PrecompileBeforePublish=trueto precompile our application.
Step 3: Store the build artifact
Next we have to store our build artifact we've just created. In this case we will keep it simple and just copy it to a shared network location. Click the
Add action button again and select
Execute Windows batch command:
Because we're just copying the artifact to another location, i've created a
xcopy command that copies the build artifact to a specified network location and create a folder with the Jenkins build number.
Step 4: Deploy the build artifact
To be able to deploy to Azure via Web Deploy you first have to download the
Publish Profile of your Azure App Service. Go to the Azure Portal, navigate to your App Service and click the
Get Publish Profile button. You should get something like this:
<publishData> <publishProfile profileName="YourProject - Web Deploy" publishMethod="MSDeploy" publishUrl="yourproject.scm.azurewebsites.net:443" msdeploySite="YourProject" userName="$YourProject" userPWD="someRandomPassword" destinationAppUrl="http://yourproject.azurewebsites.net" SQLServerDBConnectionString="" mySQLDBConnectionString="" hostingProviderForumLink="" controlPanelLink="http://windows.azure.com" webSystem="WebSites"> <databases /> </publishProfile> <publishProfile profileName="YourProject - FTP" publishMethod="FTP" publishUrl="ftp://waws-prod-sn1-027.ftp.azurewebsites.windows.net/site/wwwroot" ftpPassiveMode="True" userName="YourProject\$YourProject" userPWD="someRandomPassword" destinationAppUrl="http://yourproject.azurewebsites.net" SQLServerDBConnectionString="" mySQLDBConnectionString="" hostingProviderForumLink="" controlPanelLink="http://windows.azure.com" webSystem="WebSites"> <databases /> </publishProfile> </publishData>
We are going to use the
Web Deploy profile in our next action. Because there is no MSDeploy plugin for Jenkins click
Add action and select
Execute Windows batch command:
This is a pretty large command using the MSDeploy executable, so let's go over the command line arguments:
-verb:syncto update our web application.
-source:package="YourProject\obj\Release\_PublishedWebsites\YourProject_Package\YourProject.zip"to use the build artifact for deployment.
-dest:auto,computerName='https://yourproject.scm.azurewebsites.net:443/msdeploy.axd?site=yourproject',UserName='$YourProject',Password='someRandomPassword',AuthType='Basic',includeAcls='false'to set the destination for our deployment using the data from the downloaded Publish Profile.
includeAclsis set to false because we don't want to deploy file ownership information.
-setParam:name='IIS Web Application Name',value='yourproject'to override the web application name with the one specified in the Azure App Service.
-disableLink:AppPoolExtensionto disable setting the AppPool because it is already set by Azure.
-disableLink:ContentExtensionto disable deploying the contents of optionally configured virtual directories.
-disableLink:CertificateExtensionto disable deploying optionally included certificates.
That's it for the production process. Once a build is completed and successfully passed the configured unit tests, the only thing you have to do to deploy your application is go to your build in Jenkins, click the
Promotion Status button in the left option pane and click the
Approve button of the promotion process you want to execute.
But what about rollback? A similar promotion process can be created. Instead of creating and copying a build artifact, we are only going to deploy an archived artifact.
Click the button
Add another promotion process and call it
Rollback production. Again tick the
Only when manually approved checkbox. But now we are going to add a parameter to our process by clicking the button
Add Parameter and selecting
Because we want to rollback a specific release, we're going to use the Jenkins build number to select an artifact from the shared network location. Again click
Add action and select
Execute Windows batch command:
Copy the MSDeploy command from Step 4 and change the
-source parameter to point to the artifact from the shared network location in stead of the one created in the obj folder:
-source:package="\\neworklocation\Production\#%BuildVersion%\YourProject.zip". As you can see, the
BuildVersion parameter is used in the path to point to the artifact created from that specific build. You can pass the parameter when approving your promotion process at the Promotion Status screen.
Instead of deploying to Azure, you could also deploy to a local server or even to a docker or windows container using an orchestration tool such as Microsoft Azure Service Fabric or Pivotal Cloud Foundry.
As i mentioned earlier, create several promotion processes for your environments. Be sure to archive artifacts if needed, as archiving development releases is not really necessary. Make promotion processes dependent on each other to ensure your application is always being deployed though your entire DTAP street before reaching production.