How to replace variables of JSON file in Team Services? - azure-devops

I'm stuck with a release variable substitution of an angular project. I have a settings.json file which I would like to replace some variables:
{
test : "variable to replace"
}
I tried to find some custom task on the marketplace but all of the tasks seems to work only with xml files for the web.config.

I use the "Replace tokens" from the Marketplace https://marketplace.visualstudio.com/items?itemName=qetza.replacetokens
You define the desired values as variables in the Release Definition and then you add the Replace Tokens task and configure a wildcard path for all target text files in your repository where you want to replace values (for example: **/*.json). The token that gets replaced has configurable prefix and postfix (default are '#{' and '}#'). So if you have a variable named constr you can put in your config.json
{
"connectionstring": "#{constr}#"
}
and it will deploy the file like
{
"connectionstring": "server=localhost,user id=admin,password=secret"
}

The IIS Web App Deploy Task in VSTS Releases has JSON variable substitution under *File Transforms & Variable Substitution Options.
Provide a list of json files and JSONPath expressions for the variables that need replacing
For example, to replace the value of ‘ConnectionString’ in the sample below, you need to define a variable as ‘Data.DefaultConnection.ConnectionString’ in the build/release definition (or release definition’s environment).
{
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\SQLEXPRESS;Database=MyDB;Trusted_Connection=True"
    }
  }
}

You can add a variable in release variables Tab, and then use PowerShell task to update the content of your settings.json.
Assume the original content is
{
test : "old
}
And you want to change it to
{
test : "new"
}
So you can replace the variable in json file with below steps:
1. Add variable
Define a variable in release variable tab with the value you want to replace with (variable test with value new):
2. Add PowerShell task
Settings for powershell task:
Type: Inline Script.
Inline Script:
# System.DefaultWorkingDirectory is the path like C:\_work\r1\a, so you need specify where your appsettings.json is.
$path="$(System.DefaultWorkingDirectory)\buildName\drop\WebApplication1\src\WebApplication1\appsettings.json"
(Get-Content $path) -replace "old",$(test) | out-file $path

Related

How to replace value with more than one attribute in config file in Azure DevOps?

I have a file called entlib.config like below:
<loggingConfiguration name="Logging Application Block" tracingEnabled="true"
defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
<listeners >
<add name="Email TraceListener" toAddress="axx.xxx#xxx.com" fromAddress="axx.xxx#xxx.com" subjectLineStarter="xxxxx " subjectLineEnder="" smtpServer="xxx.com" smtpPort="xxx" formatter="Text Formatter"
Now,in this file needs to replace fromAddress, toAddress and subjectLineStarter attribute has a variables groups for azure pipeline... how to do this change ? can we do have an option to change any config file that has been created as xml to change more than one attribute ?
To replace the vaules in **.config file with the variables in Variable group, you can try the following methods:
1.You can use the XML variable substitution option in the Azure App service deploy task or IIS deploy task.
For more detailed steps, refer to this doc: XML variable substitution
2.You can use PowerShell script to modify attributes in the config file.
Here is the PowerShell script sample:
$entlibConfig = 'path\entlib.config'
Function updateConfig($config)
{
$doc = (Get-Content $config) -as [Xml]
$root = $doc.get_DocumentElement();
$activeConnection = $root.loggingConfiguration.listeners.SelectNodes("add"); #You need to define the correct location of the parameter
$activeConnection.SetAttribute("fromAddress", "$(fromAddress)");
$activeConnection.SetAttribute("toAddress ", "$(toAddress )“);
$activeConnection.SetAttribute("subjectLineStarter ", "$(subjectLineStarter )“);
$doc.Save($config)
}
updateConfig($entlibConfig)
3.When you add the mark: #{..}# in entlib.config file, you can try to use the Replace Token task from Replace Tokens Extension.
Refer to the example in this ticket:How to perform XML Element substitution in web.config using Replace Tokens?

Creating build Variables for azure devops build pipeline from external file through Terraform

I am creating Azure devops build pipeline through terraform and want my build variables to get passed through an external file while the build gets created. The same terraform code will be used to create pipelines of different templates, so accordingly the variables will also change, so inorder to make it reusable for all pipelines i want my terraform codes to take the build pipelines variables from external file and create it. Can't go with variable groups as well. So if any other process please advice.
Any help or advice would be really appreciated.
resource "azuredevops_build_definition" "build" {
project_id = azuredevops_project.project.id
name = "Sample Build Definition"
path = "\\ExampleFolder"
ci_trigger {
use_yaml = true
}
variable {
name = "PipelineVariable"
value = "Go Microsoft!"
}
variable {
name = "PipelineSecret"
secret_value = "ZGV2cw"
is_secret = true
}
the variables that above passed should instead get passed from external file.
You just need to define terraform variables for the values you require and use them in the resource:
variable "buildinfo"{ type = string default = "my value" }
and in the resource you just use:
.... value = var.buildinfo ....
you can pass the variable value for each run with a tfvars file or in your pipeline variables if you use a CI
you could do it like this:
Terraform:
variable "PipelineVariable"" {
}
Then define variables in the Pipeline like TF_VAR_PipelineVariable or in any stage you call a file (example file: .env) with source .env:
.env:
export TF_VAR_PipelineVariable=CONTENT

Azure DevOps: Getting variable value by concatenating other variables'value as task input

I have my release pipeline Variables tab set like:
I would like to access my123 variable in task's display name by concatenating initialVariable's result.
Outputs
I have tried so far referencing only initialVariable and it returned proper value in Job's display name.
But when I try to create my123 value by using initialVariable(=123), I am not getting proper value (was hoping that $(initialVariable) would convert to 123 and $(my123) would get proper "finalValue").
Azure DevOps: Getting variable value by concatenating other variables'value as task input
This is a known issue. Because the value of nested variables (like $(my$(initialVariable)) are not yet supported in the build/release pipelines.
Check my other thread for some details.
The workaround is add a Run Inline Powershell task to set the variable based on the input pipeline variables, just like Josh answered.
For you case, I test it by following Powershell scripts:
if ($(initialVariable)-eq "123")
{
Write-Host "##vso[task.setvariable variable=my123]finalvalue"
}
else
{
Write-Host "##vso[task.setvariable variable=my123]otherValue"
}
Then we could get the variable my123 based on the value of variable initialVariable in following task, I add command line task to display the value:
In the result, the value in the command line task is correct finalvalue. But the display name is still $(my123):
Important:
That is also the question in your comment. This behavior is expected. That because the variable in the display name is just to get the predefined value. It's static acquisition, not dynamic. The variable my123 is assigned when running powershell. The static variable my123 in the display name does not go in to the environment where the powershell code is running.
So, the variable my123 in the title could not get the value in the task powershell. But other task could use it very well.
Hope this answer clean your puzzle.
It's ugly, but...
Like I mentioned in my comment, I don't think you're going to get this to work in the UI by default.
Luckily you can use PowerShell to hack this together if your REALLY need the ability to address a variable name based on the value of another variable.
All the variables (secrets are handled a little differently) in your build or release pipeline definition are made available to your powershell script FILE (not inline) via environment variables (ie. $env:initialVariable).
Suppose your situation is thus:
selector = selectable1 //this is the value that can change
selectable1 = theFirstSelection
selectable2 = theSecondSelection
selectable3 = theThirdSelection
In this case (assuming I understand your request) you want to be able to change the value of the selector and force tasks to access the appropriate selectable variable.
So...
Define a new variable in your pipeline.
selector = selectable1 //this is the value that can change
selected = "" //this is the variable you use in your tasks
selectable1 = theFirstSelection
selectable2 = theSecondSelection
selectable3 = theThirdSelection
Write a VariableSelection.ps1 script. This powershell script will be what you need to run to assign the value of $(selected) before it gets used.
# VariableSelection.ps1
Write-Host "select variable: $env:selector"
$selectedValue = (gci env:"$env:selector").value
Write-Host "##vso[task.setvariable variable=selected]$selectedValue"
Note: it is my observation that if you write this script inline, it will not work b/c the environment variable functionality is different for scripts run from a file.
Given the value of $(selector) is selectable2, when the script is run, then the value of the $(selected) will be theSecondSelection.
Example in a Pipeline
Powershell
YAML
# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml
trigger:
- master
pool:
name: Hosted VS2017
variables:
- name: "selector"
value: "var1"
- name: "selected"
value: ""
- name: "var1"
value: "var1_value"
- name: "var2"
value: "var2_value"
steps:
- task: PowerShell#2
inputs:
filePath: '$(build.sourcesdirectory)/varSelector.ps1'
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
Write-Host "env:selected: $env:selected"
Write-Host "selected: $(selected)"
Results

How to update AssemblyVersion using Update Assembly Info plugin in VSTS?

I want to update the version number of my .exe file using Update Assembly Info plugin.
I am using the following configuration:
But, I keep getting an error
'$(Date:yyyy.MM.dd)$(Rev:.r)' is not a valid parameter for attribute 'AssemblyVersion'
The $(Date:yyyy.MM.dd) and $(Rev:.r) can’t be used as the build-in variable, it can be used in Build number format (Options tab).
The workaround is that:
Include $(Rev:.r) in Build number format, such as $(date:yyyyMMdd)$(rev:.r)
Add PowerShell task to add a new variable (Arguments: -bn $(Build.BuildNumber)
Script:
param(
[string]$bn
)
$d=Get-Date -Format "yyyyMMdd"
$r=$bn.split("{.}")[-1]
Write-Host "##vso[task.setvariable variable=currentVersion]$d$r"
Then use currentVersion variable in subsequent tasks, such as Update Assembly task.

Pass content from build back into Visual Studio Team Services Build

I am running build on Azure with a custom build agent (using Unity3d to be precise) I generate output of the build within a .txt file on the build machine and would like to include content within work items created during build.
Example:
Unity build fails and an error is logged to Build.log.
New bug is created with reference to build and the error message from the
logfile
Right now I am using a powershell script
$content = [IO.File]::ReadAllText("$(Build.Repository.LocalPath)\BuildProjectPC\Build.log")
Write-Host "##vso[task.setvariable variable=logContent;]$content"
To format the bug i use System.Description = $logContent but the content of the variable from PS does for some reason not end up in the bug item (it just contains "$logContent").
Any idea or direction how to fix this, respectively how to feed info back into vsts?
The variable value that used for creating work item is initialized before running build steps, so you can’t specify a dynamic variable or change the variable value during the build step that used for creating work item.
You can follow up these steps to verify it:
Open your build definition > Variable > Add a new variable (e.g. logContent, value: oldValue)
Select Options > Check Work Item on Failure > Additional Fields > System.Title $(logContent)
Add PowerShell build step: Write-Host "$(logContent)"
Add PowerShell build step: Write-Host "##vso[task.setvariable variable=logContent;]newValue"
Add PowerShell build step: Write-Host "$(logContent)"
Add PowerShell build step: [Environment]::Exit(1)
The log result:
Step 3 output oldValue
Step 5 output newValue
The created work item title oldValue.
The workaround for your requirement is that, you can create a work item and associated to build through PowerShell with Rest API (add PowerShell step at the end of other steps and Check Always run option).
Associate work item to build:
Request Type: Patch
Request URL: https://[your vsts account].visualstudio.com/DefaultCollection/_apis/wit/workitems/[work item id]?api-version=1.0
Content-Type:application/json-patch+json
Body:
[
{
"op": "add",
"path": "/relations/-",
"value": {
"rel": "ArtifactLink",
"url": "vstfs:///Build/Build/[build id]",
"attributes": {
"comment": "Making a new link for the dependency"
}
}
}
]
You can refer to this blog for PowerShell scripts to create and associate work item.
Build association with work Items in vNext
In the Additional Fields you need to reference the build/release definition variable with the following notation: $(logContent)
as shown here below: