Managing Multiple Azure Web Site Environments using Visual Studio Publishing Profiles
This is the second post in the Real World Problems with Azure Web Sites. The first post summarized how one can manage multiple environments (development, staging, production, etc) using a Git repository with a branching strategy. Not everyone wants to use Git, and most would prefer to stay in their favorite IDE – Visual Studio 2012 – all day to do pretty much everything. My buddy Sayed Hashimi told me about Visual Studio profiles a few weeks ago and I’d been wanting to write up something on how it could work with Azure Web Sites. This post follows up on the idea of managing multiple Azure Web Sites, but rather than do it with Git, I’ll show you how to manage multiple sites with only Visual Studio’s awesome publishing-with-profiles features.
Set Up the Environments
The first step in the process is to have your multiple sites set up so that you have environmental isolation. In this case, I’m being thorough and requiring there are two gates prior to production release. All three of these sites are in the free zone, for this demonstration.
If this was fully realistic, the production zone would probably be at least shared or reserved, so that it had a domain name mapped to it. That’s the only site that would cost money, so the development and staging sites would have no impact on the cost I’ll incur for this setup.
Once the sites have been created I’ll go into each site’s dashboard to download the site’s publish settings profile. The publish settings files will be used from within Visual Studio to inform the IDE how to perform a web deploy up to my Azure Web Site environment.
Once I’ve downloaded each of these files I’ll have them all lined up in my downloads folder. I’ll be using these files in a moment once I’ve got some code written for my web site.
Now that I’ve got all my environments set up and have the publishing settings downloaded I can get down to business and write a little code.
Setting up the Web Application Project
I know I’ll have some environmental variances in the deployment details of this web application. I’ll want to use different databases for each environment, so I’ll need to have three different connection strings each site will have to be configured to use for data persistence. There’ll be application settings and details and stuff, so the first thing I’ll do in this simple ASP.NET MVC project is to prepare the different publishing profiles and the respective configuration for those environments.
To do this, I’ll just right-click my web project and select the Publish menu item. I’m not going to publish anything just yet, but this is the super-easiest way of getting to the appropriate dialog.
When the publishing dialog opens, I’ll click the Import button to grab the first environment’s publish settings files.
I’ll grab the first publish settings file I find in my downloads folder, for the site’s development environment.
Once I click Open, the wizard will presume I’m done and advance to the next screen. I’ll click the Profile link in the navigation bar at this point one more time, to go back to the first step in the wizard.
If, at any point during this process you’re asked if you want to saved the profile, click yes.
I’ll repeat the import process for the staging and production files. The idea here is, to get all of the publish settings files imported as separate profiles for the same Visual Studio web application project. Once I’ve imported all those files I’ll click the Manage Profiles button. The dialog below should open up, which will show me all of the profiles I’ve imported.
This part isn’t a requirement for you or a recommendation, but I don’t typically need the FTP profile so I’ll go through and delete all of the *FTP profiles that were imported. Again, not a requirement, just a preference, but once I’m done with it I’ll have all the web deploy profiles left in my dialog.
I’ll just click Close now that I’ve got the profiles set up. Now that the profiles are setup they’ll be visible under the Properties/PublishProfiles project node in Visual Studio. This folder is where the XML files containing publishing details are stored.
With the profile setup complete, I’m going to go ahead and set up the configuration specifics for each environment. By right-clicking on each *.pubxml file and selecting the Add Config Transform menu item, a separate *.config will be created in the project.
Each file represents the transformations I’ll want to do as I’m deploying the web site to the individual environment sites. Once I’ve added a configuration transformation for each profile, there’ll be a few nodes under the Web.config file I’ll have the opportunity of configuring specific details for each site.
Now that I’ve got the publish profiles and their respective configuration transformation files set up for each profile, I’ll write some code to make use of an application setting so I can check to make sure the per-profile deployment does what I think it’ll do.
Now, if you’re thinking to yourself this isn’t very practical, since I couldn’t allow my developers to have the ability of deploying to production and you’re compelled to blow off the rest of this post since you feel I’ve completely jumped the shark at this point, keep on reading. I bring it back down to Earth and even talk a little release-management process later on.
Environmental Configuration via Profiles
Now I’ll go into the Web.config file and add an appSetting to the file that will reflect the message I want users to see whenever they browse to the home page. This setting will be specific per environment, so I’ll use the transformation files in a moment to make sure each environment has its very own welcome message.
This is the message that would be displayed to a user if they were to hit the home page of the site. I need to add some code to my controller and view to display this message. It isn’t very exciting code, but I’ve posted it below for reference.
First, the controller code that reads from configuration and injects the message into the view.
Then I’ll add some code to the view to display the message in the browser.
When I browse the site I’ll get the obvious result, a simple hello message rendered from the configuration file on my local machine.
I’ll go into the development configuration profile file and make a few changes – I strip out the comments and stuff I don’t need, and then I add the message appSetting variable to the file and set the transformation to perform a replace when the publish happens. This basically replaces everything in the Web.config file with everything in the Web.MySite-Dev - Web Deploy.config file that has a xdt:Transformattribute set to Replace.
I do the same thing for the staging profile’s configuration file…
… and then for the production profile’s configuration file.
With the environmentally-specific configuration attributes set up in the profile transformations and the publish profiles set up, everything should work whenever I need to do a deployment to any of the environments. Speaking of which, let’s wrap this up with a few deployments to our new environments!
The final step will be to deploy the code for the site into each environment to make sure the profile configuration is correct. This will be easy, since I’ve already imported all of my environments’ configuration files. I’ll deploy development first by right-clicking the project and again selecting the Publish context menu item. When the publish wizard opens up I need to select the development environment’s profile from the menu.
Once the publish process completes the site will open up in my browser and I can see that the appropriate message is being displayed, indicating the configuration transformation occurred properly based on the publish profile I’d selected to deploy.
Next, I right-click the project and select Publish again, this time selecting the staging environment.
When the publish completes, the staging welcome message is displayed.
If I repeat the same steps for production, the appropriate message is displayed there, too.
In a few short steps, I’m able to set up a series of environments and publish profiles, that work together to allow me separate deployment environments, with little extra work or overhead. Since the profiles are linked to the configuration transformations explicitly, it all just works when I deploy the site.
As promised earlier in that blockquote up there, I want to stay with the “these are real world scenarios as much as possible based on my real-world experiences and questions I’ve been asked” mantra, I feel it’s necessary to get into the idea of release management insomuch as how it’d apply here. In the previous example I was using Git branches to gate releases. In this example, I’m not using any centralized build solution, but rather assuming there’s a source control environment in between the team members – developers, testers, release management, and so on – but that the whole team just chooses to use the Web Deploy awesomesauce built into Visual Studio.
Think of a company with aggressive timelines but who still take care to gate releases but choose not (for whatever reason) to set up a centralized build system. This company still feels strongly about managing the release process and about maintaining separate chains of testing and signoff responsibility as code is moved through the environments on the way to a production release, but they love using Visual Studio and Web Deploy to get things into the environments as quickly as possible.
The diagram below demonstrates one potential release cycle that could make use of the publish profile method of gating deployments through a series of environmental gates.
Assume the team has come to a few conclusions and agreements on how their release cycle will execute.
- All the team members are relatively technical and comfortable using Visual Studio with web application projects
- The team uses a source control method to share source code and to distribute it internally between team members
- The web application project checked into source control has with it the publish profile for deploying the site into the development Azure Web Site
- Testers maintain copies of the staging publish profile setting, are regarded as the owners of the staging environment, and are the only team members who can deploy code to the staging Azure Web Site
- Release managers maintain copies of the production publish settings files, are regarded as the owners of the production releases, and are the only team members who can deploy code to the production environment
- As developers, testers, and RM’s complete their respective testing phases in the environments they own and are ready to sign off, they escalate the deployment process to the next level
- Following escalation, the first general step is to test the previous environment for verification purposes, then to deploy to the next environment and to begin testing of the deployment in that environment
Luckily, this sort of situation is quite possible using publish profiles and free Azure Web Sites used as environmental weigh stations on the way to be deployed to a production site that’s deployed to multiple large reserved instances (for instance).
The convenient partnership between web publishing and Azure Web Sites shouldn’t be regarded as an indicator of it creating the potential for cowboy coding, but more considered a tool that when coupled with a responsible release cycle and effective deployment gating can streamline and simplify the entire SDLC when your business is web sites.
I hope this post has introduced you to a method of controlling your deployment environments, while also allowing you to do the whole thing from within Visual Studio. Later on, I’ll follow up this post with an example of doing this sort of thing using Team Foundation Services.
Hopefully, you have enough ammunition to get started with your very own Azure Web Site account today, for free, and you feel confident you’ll be able to follow your very own release management process, without the process or architecture slowing you down. If you have any questions about this approach or the idea in general, feel free to use the comments form below.