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
Related
I'm using Octopus as part of our deployment for a .NET Core 3.1 Web API project.
log4net.config exists in .\Utility\Logs.
I'm trying to follow the pattern here:
https://help.octopus.com/t/transformation-best-practice-log4net-config-or-any-non-web-app-config/9906/4
As I understand it, this consists of three parts:
Create Log4Net.DeploymentTransform.config, with the variables in #{name} format - this has been done.
Turn on the "Substitute variables in files" feature, and point at the Log4Net.DeploymentTransform.config transformation file (variable replacement happens before transformation). That would result in the #{LogFileLocation} variable being replaced with whatever value was set for your LogFileLocation variable in the current scope.
This is done and is working.when my app is deployed, Log4Net.DeploymentTransform.config is there as well and the variable has been successfully set in it.
You'd also turn on the configuration transforms feature, and fill out the additional transforms section in the configuration transforms feature to identify your transform file (e.g. Log4Net.DeploymentTransform.config => log4net.config).
This is not working, the content of Log4Net.DeploymentTransform.config is not being copied on top of log4net.config, though they are in the same folder upon deployment.
Here is what I did in our "deploy step"
Which sure looks like what the article is saying to do.
What else should I check? Any idea why step 3 isn't occurring?
Your syntax looks correct for the files - have you checked to ensure that you have the xdt attributes set?
In the example forum post you shared, the log4net and appender elements are tagged with xmlns:xdt, xdt:Transform and xdt:Match attributes that help the XDT layer determine how to transform the files.
A quick example - I created a Log4NetConfigTest package with two files -
Utility/Logs/log4net.config
Utility/Logs/log4net.trasnform.config
I used the same sample code from the forum post as well.
Here's the set up for my package deployment configurations:
With that set up (and my LogFileLocation project variable set), I was able to see the following in my task log for the deployment:
Deploying package: C:\Octopus\Files\Log4NetConfigTest#S1.0.0#20004C95A0E0094490814B5A365DDAD2.zip
Transforming 'C:\Octopus\Applications\Development\Log4NetConfigTest\1.0.0_1\Utility\Logs\log4net.config' using 'C:\Octopus\Applications\Development\Log4NetConfigTest\1.0.0_1\Utility\Logs\log4net.transform.config'.
No matching appSetting, applicationSetting, nor connectionString names were found in: C:\Octopus\Applications\Development\Log4NetConfigTest\1.0.0_1\Utility\Logs\log4net.config
The task log confirmed that Octopus did apply the transformations, and once deployed, I confirmed that my new test log location was present and correct in both the base configuration and the transformation file.
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).
We have one ASP.Net solution with several projects. each project have build.pubxml with unique folder path.
For example:
In project Test we have this line inside the build.pubxml:
<publishUrl>C:\publish\SolutionName\Test</publishUrl>
In project Exam we have this line inside the build.pubxml:
<publishUrl>C:\publish\SolutionName\Exam</publishUrl>
In the build pipeline (in TFS) with have MSBuild step with this argument:
/p:PublishProfile=build.pubxml
After the build we got 2 folders - Test and Exam in C:\publish\SolutionName.
So far so good.
The problem is we have few branches, and we want to separate the publish folder for each branch, so we added .pubxml for each branch and in the build pipeline we specified the correct one. but is make are a lot of work on each new branch created and can cause mistakes.
We tried to pass the /p:publishUrl=C:\publish\BranchName in the MSBuild but then we got a one folder with all the content of Test and Exam and not two folders.
The idea is to have only one .pubxml file for each project with a parameter and pass the value in the pipeline, for example:
<publishUrl>C:\publish\$(Parameter)\Test</publishUrl>
And in the build we will pass the parameter according to the branch.
It is possible to do something like this?
It is possible to do something like this?
The answer is Yes. Since msbuild accepts Global Properties in command-line. If we define one Property in build.pubxml like <publishUrl>C:\PublishFolders\$(BranchID)\xxx(Test,Exam...)</publishUrl>, then we can simply pass the value in msbuild arguments like this:
Then we'll get Test and Exam folders under C:\PublishFolders\NewTest. Also we can choose to pass the pipeline predefined variables to the command like: /p:BranchID=$(Build.SourceBranch)...
This works for build in local machine, tfs and Azure Devops pipeline. Hope all above helps :)
I am building Integration tests in Visual Studio (2017) for Net Core applications built on VSTS and deployed from there. My projects are test projects, and right now my connection strings to the deployed API url, and the database are hardcoded, but I want to remove them from the code and place them in a VSTS build step that adds environment variables.
Right now, my Test .cs files look something like this:
[TestClass]
public class TestFeature
{
//Set up variables
private static string _connectionString = "server=localhost;port=5432;database=databaseName;user id=postgres;password=postgres";
[TestInitialize]
public void Initialize()
{
}
//And going into my test methods
}
How do I set up my project to read Environment Variables set from the Configuration on VSTS?
What research has dug up for me so far, is to Right Click on Properties of the test project, under Debug, set up Environment Variables with a key and value there.
Then I change my test project to take the GetEnvironmentVariable()
private static string _connectionString = Environment.GetEnvironmentVariable(nameOfVariable);
On the other side in VSTS, I'm trying to find a build step that will set the variable to be the connection string there. The best step I could find is "Set Variable".
However, this is not working for me. The program will not recognize the name of the new variable set in Environment Variables, to start.
You need to add your VSTS variables in the Variables tab.
Another option is to use Powershell to set them if you want to do it in a dynamic fashion using a Powershell script task.
Write-Host "##vso[task.setvariable variable=sauce]crushed tomatoes"
https://learn.microsoft.com/en-us/vsts/build-release/concepts/definitions/release/variables?tabs=powershell
The better way is building, deploying and testing together in a build definition, after the build succeed, then the pull request can be approved.
For this way, you can use the variable in current build (can add/update variable as Marcote said)
If you must do integration test in a separate build, you can set Trigger to Manual in Build validation of Pull Request policy, then you can queue build manually and specify variables’ values (Check Settable at queue time for the variables in build definition)
My asp.net application uses a resource file to point to some REST api endpoints. The apps behavior changes depending on the amount of data it gets back from those services.
I'd like to perform integration testing on my app but I'd like to use different resource files that have custom api endpoints depending on the scenario I'd like to check against. For instance, I'd like to be able to test the integration of my app if the end points return nothing, one item, or many items.
In my ninject bindings I have
var appSettings = StreamDeserializer.DeserializeFileFromResource<AppStartSettings>(Resources.appsettings);
Is there a way I can configure specflow to rebuild my application with a different resource file depending on the integration test scenario?
No, SpecFlow runs only when you execute your tests and so can not influence your build.
Could you parameterize in your code, which resourcefile is used so that it is decided at runtime?
Then you could write a step that changes this parameter.