How to manage A LOT of similar configurations in TFS - deployment

I have an ASP .Net MVC application with 4 different publishing profiles: dev, test, demo and prod.
These publising profiles are build using the same two steps: NuGet restore followed by an MSBuild. Then, they are deployed to lots of different servers: a few dev servers (one server dev per team), one test server, one demo server and several production servers.
msbuild /p:Configuration="$(Configuration)"
/p:PlatformTarget="any cpu"
/p:DeployOnBuild="True"
/p:DeployTarget="MsDeployPublish"
/p:MSDeployServiceURL="$(MSDeployServiceURL)"
/p:DeployIISAppPath="portal"
/p:CreatePackageOnPublish="False"
/p:MsDeployPublishMethod="WMSVC"
/p:AllowUntrustedCertificate="True"
/p:UserName="Deploy_User_For_TFS"
/p:Password="P#ssw0rd"
/p:AutoParameterizationWebConfigConnectionStrings=False
/p:ExcludeFilesFromDeployment="Cache"
Currently I have 4 TFS Build configurations (one for every publishing profile) and a file where I have all the possible values for MSDeployServiceURL parameter.
There are two issues with this approach:
When we had to add a new parameter AutoParameterizationWebConfigConnectionStrings we had to change it in 4 places instead of one.
We have to have a shared file as the source for the parameters. it is not easy to understand where which value should be copied and people often make mistakes.
So I have two questions:
Is there any way to have a one universal template where I can specify only my parameters Configuration and list of possible MSDeployServiceURLs and have everything else stay the same? Having such a template should fix problem #1.
Is there a way to define a drop-down like variable, where the value could not be typed in by the user, but should be selected from a pre-defined list of values?

Is there any way to have a one universal template where I can specify
only my parameters Configuration and list of possible
MSDeployServiceURLs and have everything else stay the same? Having
such a template should fix problem #1.
You could simplify such that the release configuration creates a templated publish profile. Then using TFS's release management, you could update the publish profile with the appropriate values. Based on your description, it seems like you are trying to combine both the compilation and the release.
For example, in TFS you could have one build (for example, MyApp-Release) that builds the code in the release configuration. As part of that process, it passes in placeholders for things like the deploy URL. For example, /p:MSDeployServiceURL="$(MSDeployServiceURL)" would be /p:MSDeployServiceURL="__MSDeployServiceURL__".
In the TFS release, you'd have a step that the replaces tokens (if you need one, you can use Colin's ALM Corner Custom Build Tasks) in the publish profile. The replace token task would then update the __MSDeployServiceURL__ with the value from an release environment variable with the same name (minus the underscores). So your release would have a dev, test, demo, and prod environment and for each environment, there would be a variable named MSDeployServerURL in each with a different value and a replace tokens step.

Related

.NET 7, VS 2022 . Is it possible to define multiple deploy profiles each with different post build commands?

So for my work I handle a .NET 7 web application that changes in theme and behavior depending on what appsettings.json file group is present in app main folder.
These alterations changes do NOT depend on environment.
For now I just deploy all the files to the server and manually overwrite the appsettings.json group from the folder with the intended configuration.
I'm just wondering if it's possible to automate this process creating as many different deploy profiles, one that copies after build appsettings.json group from 'folderA' and one that copies the json group from 'folderB', etc...
I am aware of the post-build events on application project properties, but this events would be applied for all builds, and I don't see any textbox to set post deploy commands on deploy profile.
Am I missing something, or there is not way for script this behaviour with deploy tool?

Azure Webjobs app.config Release Transformations

I have a webjob and a webapp (both separate projects), I would like to build one artifact for all environments and do the transformations during the release step rather than build, as that way I have to create an artifact per environment. So I am creating two separate artifacts (one for webapp and one for webjob) per environment and applying the xml transforms during publish to the app service, now everything works fine, except that the transformed file for the webjob is placed in the root directory of the webapp, which is not what I intend to do. I would like the file to be placed as app_data\jobs\continous\myjob\myjob.exe.config
I've seen the slow cheeta and CTT transforms, but those are out of the scope of this question as they do transform only on build.
You can use Kudu api to run the commands to copy or delete files.
More information about how to call kudu api during build/relase, you can refer to: How to access Kudu in Azure using power shell script
You should transform during build and your transformation should happen as tokens in the build rather than actual target values. Then in deployment you can replace the token values with actual target environment values. That is the proper approach for packaging and deployment of any application type.
Steps should be
In build tokenize the configurations with transformation (use this extension task)
Package tokenized configurations as build output
At deployment apply target values to tokens (use replace tokens task comes with marketplace extension, which replaces values of defined configs with release variable values by mapping names automatically. in other words token should be the parameter name)
Here is an example done on a windows service. But it is applicable for webjobs (have tested this) as well and it is the proper solution.

Generate different artifacts team city

I have a project which I want to deploy via team city but when it builds I want to generate a number of different artifacts.
In my app.config file I have an app setting called "platform" which I want to change the value of for each artifact. For example on build I would get three artifacts, dev, test, staging which would have had the "platform" setting changed to the corresponding value.
I have created the powershell script and run it successfully outside of team city, but I have not been able to work out how to set the file directory where the app.config exists within team city.
Is there a system variable I can use to target the current builds app.config file? Or is there a different / better way that I can accomplish what I want to do?
Thanks
Or is there a different / better way that I can accomplish what I want to do?
While this sort of question can lead to an argument over which is better... Based on what you have described, I believe that Octopus Deploy would be a good fit. Octopus Deploy integrates very nicely with TeamCity, and it handles the transformation configurations that are required to allow deployment to each of your environments, i.e. Dev, Test, and Staging. You would simply configure these as Environments within your Octopus Configuration, and during installation, Octopus can modify the configuration files as required, based on variables that you define.
I would recommand to create 3 build steps inside your TeamCity configuration :
Inside the Parameters tab, you can define configuration parameters. Just define here the 3 values : ie: PlatformDev, PlatformTest, PlatformStaging
Using Visual Studio Runner
You might be using Visual Studio runner type. So, here you can add specific values from MSBuild properties:
Dev Step:
Passing the parameter Dev, and executing your code
/p:CustomPlatform="%PlatformDev%"
Test Step:
Passing the parameter Test, and executing your code.
/p:CustomPlatform="%PlatformTest%"
Staging Step:
Passing the parameter Staging, and executing your code.
/p:CustomPlatform="%PlatformStaging%"
Then, the value CustomPlatform would be accessible inside your MSBuild scripts.
Using Powershell hand-made scripts
If you are using a powershell script to run your compilation/artifact creation, you can just add this CustomPlatform as a parameter of your script, and use it directly.
Using XSLT
Another way to do this might be to use XSLT to transform you app.config file, using a specific value.

Using VSTS Release Management, how can I modify the configuration of an Azure Web App for each environment?

I'm using Visual Studio Team Services and I'm trying to set up Release Management to allow automated deployments for our Azure Web App to multiple environments. I would like the same source to be deployed to each environment, but with modified configuration settings.
I was hoping that I could create a single Build for my application, and then modify the configuration at deployment time for each environment. I'm aware that this can be done for appSettings and connectionStrings (either through Tokenization, or even managing those settings via the Azure portal), but I'd like to be able to make more general changes to the web.config file. For example, I want to be able to:
Update 'simple' settings such as appSettings/connectionStrings
Update multiple attributes on elements (like httpErrors)
Insert or rewrite sections of the config file itself (for example to add IIS rewrite rules, or to remove unwanted HTTP handlers for production)
Currently we achieve this by using config file transformations and separate publish profiles for each environment (manual deployment). I can't see a way to re-use this if I want a single release pipeline.
I'm hoping someone can help point me in the right direction. I'm also happy to accept alternative solutions - ultimately I just want to be able to deploy the same source (e.g. from the same commit in source control) to multiple environments, with different configuration, while keeping some kind of flow from dev, to test, to eventually production.
You can use Tokenization Task to update the files base on the environment variables.
More similar extensions: Replace Tokens and Colin's ALM Corner Build & Release Tools.

Environment specific EF6 Code First Migrations using VSTS Release

I have a project that uses Entity Framework 6.x, ASP .NET WebApi 5.x. Data Access is in a secondary project inside the solution. I want to use VSTS (aka Visual Studio Online) to build and release it as a website to environments for integration/dev, qa, stage, and production. There are some great videos on Channel 9 that deal with the generic high-level description. (for example https://channel9.msdn.com/Series/DevOps-Release-Management and https://channel9.msdn.com/Series/DevOps-Fundamentals/Infrastructure-as-Code) There are all kinds of articles and videos about how to do migrations from inside Visual Studio including generating scripts.
Searching around the web I don't even find any older resources or concrete examples of continuous deployment with code first migrations. There must be examples and best practices for methods other than auto-migrations or SQL scripts.
I have configured a Web Deployment Package publish profile. I use it via the PublishProfile msbuild.exe directive. The package is added to the artifacts and then deployed by the Azure Web App Deployment task in each Release environment. However once this package is built, I don't know of a way of changing the connection string in the build package for each time it is released to an environment.
There is probably something I am overlooking, but how should environment specific migrations be done with via VSTS Release?
For Code First Migration, you can "Write App_Start code to run Migrations" or "Write Web.config transforms to configure the MigrateDatabaseToLatestVersion initializer to run", refer to this article for details: http://blogs.msdn.com/b/webdev/archive/2014/04/09/ef-code-first-migrations-deployment-to-an-azure-cloud-service.aspx
For the connection string transformation with profile, you need to add a web.config file for the publish profile and then enter the connection string in this web.config. Refer to this link for details: http://awaitwisdom.com/publish-profile-config-transform/
I hate to answer my own questions here but, ultimately my research took me to the conclusion I am posting at length here. In sort, Web.config and Parameters.xml require some custom scripting that will require you to maintain your own deployment automation. These routes will still require you to additionally create your resource groups or manage them manually.
To avoid these complications and cobbling tools and scripts together, the whole operation can be achieved with two JSON files. These JSON deployment templates allow you to create or update your resource group when your deployment runs. They also allow you to automate setting appsettings and connectionstrings that overwrite your Web.config values in the same manner as you can through the Azure Portal.
the steps: (1) Add the two JSON files to the project setting the name of you connection string on line 88 (2) Add a Azure Resource Group Deployment task to the Release environment. (3) Set Template (WebSite.json) and Template Parameters (WebSite.parameters.json) paths in the task. (4) Set Override Template parameters to -hostingPlanName "myHostingPlan" -webSiteName "myWebsiteName" -connectionString "the-actual-connection-string" (5) make sure you are using the same website name in your Azure App Deployment task.
This does depend on having your code first migrations run via App_Start or something similar. I took the first part of #Eddie's suggestion since App_Start is easy to deal with and doesn't seem to run too often.
As a bonus you can add environment variables for any of this configuration so you can clone the environment and then just change the variables. This ultimately makes your application or api connection string a Release variable.