Azure pipeline with multiple environments - .net-core

My dotnetcore app has one appsettings.json per environment (appsettings.json and appsettings.Development.json for example) and I would like to take advantage of this on my pipeline.
I see 2 options for the pipeline:
Build Artifact for Dev -> Deploy on Dev -> Build Artifact for Prod -> Deploy on Prod
or
Build Artifact -> Deploy on Dev -> Deploy on Prod
For the first option, I could set the environment as a parameter for the build.
For the second option, how could I build the App only once, and set the environment according to the current deployment step? Taking advantage of the multiple appsettings.json I have.
And finally, are these approaches aligned with the best practices? If not, what would be the best practices for pipelines with multiple environments?

Generally we can generate a single artifact, then deploy the artifact to different environments and perform the different transformations at any environment within it's own stage release phase. That means we can change and override the settings which defined in the appsettings.json in each release environment.
Please refer to File transforms and variable substitution reference on how to do the transformation with .json files.
Besides, we can try to install the Replace Tokens extension, then use Replace Tokens task to load and change the settings defined in the appsettings.json file in each release environment/stage.
You can also transform the settings or use File Creator to create a new appsettings.jsonfile to overwrite the existing one.
Below blogs for your reference:
Replace appsetting tokens in config files with Build & Release
Management in VSTS (TFS)
Transform configurations in a .NET Core 2.2 Web API using Azure
DevOps
Using custom appsettings.json with ASP.NET Core integration
tests

You could go with Azure AppConfiguration and add it as an extra source for the configuration. This way your building/releasing process stays extremely simple.
See this documentation: https://learn.microsoft.com/en-us/azure/azure-app-configuration/enable-dynamic-configuration-dotnet-core
It's very powerful: you can select only part of the configuration (through filters), you can have feature flags, and you can have secrets (from linked key vaults).

Related

Failing test running successful in Azure DevOps Pipeline

I have a ASP.NET Web Forms project which is hosted on a Azure DevOps Repository. The Source Control is TFS.
I Created a continuous integration Pipeline in Azure Devops for the Repository.
Here is a Image of the Pipeline:
All the Task from the Pipeline are running correctly beside the VSTest-TestAssemblies Task.
My NUnit Test is failing in my local Visual Studio, as it should:
But when running my CI, it tells my that no test failed:
Here you can see my settings and the path to my tests of the VSTest-TestAssemblies Task:
This is what the Folder Structure of my Project looks like:
NR.TestAutomation
- NR.TestAutomation
- NR.TestAutomation.Tests
- bin
- obj
- DemoTests.cs
- NR.TestAutomation.Tests.csproj
- packages
- NR.TestsAutomation.sln
The Output of the CI Run tells me, that the folder exist and it even finds the test:
Source filter: **/*Tests/*.cs
SystemVssConnection exists true
vstest.console.exe "D:\a\9\s\NR.TestAutomation.Tests\DemoTests.cs"
Why are my failing tests not failing inside the Azure DevOps Pipeline?
You should specify the (output of the) TestProject to run, not the individual files that contain a test. The test runner cannot execute a .cs file.
So in short; the failing test doesn't run successful in an Azure DevOps pipeline... it doesn't run in the pipeline at all.
Test files
Run tests from the specified files. Ordered tests and webtests can be run by specifying the .orderedtest and .webtest files respectively. To run .webtest, Visual Studio 2017 Update 4 or higher is needed. The file paths are relative to the search folder. Supports multiple lines of minimatch patterns.
Source Visual Studio Test task - Arguments
Possibly interesting as well: more info on File matching patterns reference
EDIT:
what would be the proper Source Path to my tests?
Of course that depends on the name of your test project. Looking at your screenshots, you could use **/*.Tests.dll. This recursively matches all the assemblies where the name ends with .Tests.dll.
Since your project's name is NR.TestAutomation.Tests, the assembly should be named NR.TestAutomation.Tests.dll so it will match. It's also ready for future additions of test projects, as long as their name ends with .Tests.

Yaml pipeline. How to swap connstrings in Builds with Console App

I built a console app with .Net Core 3.1. I have it building using Yaml leaning heavily on the learn.microsoft.com documentation. The release is pushing to the correct box. But I have an appsettings.json file that has a conn string variable that is different between my TEST, QA and PROD regions. I knew how to do this with the xml file transforms in .NET and MVC but I can't get this to work. Any help would be great since I don't even know the term for what I am trying to do here.
How do you change the connectionstring in the appsettings.json based on a variable or do I have to create 3 branches each with settings and create 3 build and release pipelines?
Thank you.
In order to push to different environments you usually
Have seperate release pipelines that trigger from different branches.
You have one release pipeline with different stages that need pre-approval to move to the next stage TEST -> QA -> PROD.
In both cases you will make use of Stage.
There you need to add a task named "File transformation"
In the File Format select JSON
Now, any variable found in the appsettings.json file will be replaced by the variables you set in the pipeline.
Be careful because nested variables like
{
SerilogSettings: {
BatchSize: 100
}
}
need to be set with a "." instead like
SerilogSettings.BatchSize

How to differentiate Databases in ASP.Net Core 2.1 Application based on Enviroment?

I am building this ASP.Net Core MVC Application. Thing is I want to keep three different environments for my Databases, Like Development, Sandbox & Production. Is there any way I can mention that in my app setting file or will I need to manually specify in the deployment like I normally do? Like I am deploying a self-contained application on Elastic Beanstalk & for now, I have edited the appsettings.json file with the required database but that is just like one DB at a time.
"ConnectionStrings": {
"DefaultConnection": "Server = tcp:<Remote DB Server>,1433; Database = <DB>; User Id = <DB Username>; Password = <DB PASS>;"
TL:DR; Can I have multiple Connection strings as per the enviroment in my appsettings.json file?
As per the configuration by environment chapter of the official documentation, you have a few options for this:
To load configuration by environment, we recommend:
appsettings files (appsettings.<>.json). See Configuration: File configuration provider.
environment variables (set on each system where the app is hosted). See Configuration: File configuration provider and Safe storage of app secrets in development: Environment variables.
Secret Manager (in the Development environment only). See Safe storage of app secrets in development in ASP.NET Core.
The first option is a very common solution for environment-specific configuration and simply involves in additional appsettings.json files that include the environment name in the file name. The default templates already come with a appsettings.Development.json file that is only loaded for the Development environment. Similarly, you could create a appsettings.Sandbox.json and a appsettings.Production.json file that are loaded with the Sandbox and Production environment respectively.
The configuration files are loaded in addition to the normal appsettings.json file, so you can use that to specify general defaults and only overwrite environment-specific things in the environment-specific appsettings.<Environment>.json files.
Note that you should always try to avoid putting production secrets in files, especially those that are committed to source control. For those, you can also use environment variables to overwrite specific values. For example, an environment variable ConnectionStrings__DefaultConnection could contain the connection string for your application and would overwrite what is configured in one of the appsettings files.

How can I delete existing files when deploying an ASP.Net 5 Web App to Azure

I've got a web application in ASP.Net 5 with the source in VS Team Services. Using the Team Services build system, I'd like to deploy it directly to Azure for Continuous Deployment.
I've followed the steps here: https://msdn.microsoft.com/Library/vs/alm/Build/azure/deploy-aspnet5
However, when the website is deployed, only the new files are added and existing ones are overridden. Any deleted files are not removed. This means that extra controllers that were removed during refactoring (for example) still hang around.
Is there a way to force the deployment to wipe out any existing deployed website before putting the new one in place?
I've already run into an issue where the site is unable to deploy due to files being locked. I fixed this by wrapping the publish command in commands to start/stop the site:
Stop-AzureWebsite -Name $websiteName
. $publishScript -publishProperties $publishProperties -packOutput $packOutput
Start-AzureWebsite -Name $websiteName
In theory I could instead remove and create the website, but that seems a bit heavy handed...
Another option, using the publish profile:
Add this to your MSBuild parameters:
/p:SkipExtraFilesOnServer=False
Additional parameters here:
Valid Parameters for MSDeploy via MSBuild

Transform web.config on azure

The question is a follow up to this one: Generate Web.Debug config which could be debugged](Generate Web.Debug.config which could be debugged)
I have defined a transformation for web.debug.config. During compilation I see the following:
Transformed Web.config using C:\data\Main\WebRole\Web.Debug.config into
C:\data\Main\obj\obj\x64\Debug\WebRole.csproj\TransformWebConfig\ [...]
transformed\Web.config.
Checked Web.config in the specified location - it is correct (transformation succeeded)
But when I start the service in the azure emulator I get an alert that
Why does it happen? Looks that incorrect web.config is taken. Where should I specify the location of correct (transformed) file?
The key thing to realise with web.config Transforms (and is mentioned in the answer to your linked question) is that they are only part of the story.
When you build your sources, the transformed web.config file is built into the /obj/ folder, ready for deployment.
It is only the act of deploying your solution somewhere that puts the transformed config file into use - as noted in the docs:
When you deploy the Web application by using the selected build configuration and by using either a deployment package or one-click publish, the Web.config file is transformed according to your specifications.
How are you running the application after you build it? You need to publish or deploy it using one of the built in mechanisms that support web transforms to see those changes on your site.
If you are running the emulator against the original source files, they won't see the transformed web.config file - which is why typically the debug build doesn't have any transforms and you then turn off debugging with your Release build which is then deployed to production.
As you're trying to test this in the emulator you should be able to do the following:
In the Solution Explorer, ensure you've selected a file within the project that runs in the emulator.
From the Build menu, select "Publish [Project Name".
In the Publish Wizard, create a new "Profile" using the "Custom" publish target.
In the "Connection" pane select "File System" as the publish method, and give it a suitable target location.
In the "Settings" pane choose the appropriate configuration (in your case probably "Debug"), and set any other options that you'd like.
Then press "Publish", and the project should be built, and then deployed to the new file location.
You should then be able to start the emulator from this newly published location, which will be using your transformed web.config.
I have found this solution and it works perfectly
https://translate.google.co.il/translate?hl=en&sl=de&tl=en&u=http%3A%2F%2Fwww.sascha-dittmann.de%2Fpost%2FWebConfig-Transformation-im-Windows-Azure-Compute-Emulator.aspx&anno=2

Resources