How to use predefined variables in Azure DevOps PowerShell Task? - powershell

I'm trying to create a simple Azure DevOps Extension task which consists of a simple PowerShell script installing a dotnet tool and then running it like this:
dotnet tool install dotnet-stryker --tool-path $(Agent.BuildDirectory)/tools
$(Agent.BuildDirectory)/tools/dotnet-stryker
But when I try to run my task I get the following error:
##[error]System.Management.Automation.ParseException: At D:\a\_tasks\run-stryker_400ea42f-b258-4da4-9a55-68b174cae84c\0.14.0\run-stryker.ps1:17 char:25
##[debug]Processed: ##vso[task.logissue type=error;]System.Management.Automation.ParseException: At D:\a\_tasks\run-stryker_400ea42f-b258-4da4-9a55-68b174cae84c\0.14.0\run-stryker.ps1:17 char:25
+ $(Agent.BuildDirectory)/tools/dotnet-stryker
+ ~
You must provide a value expression following the '/' operator.
At D:\a\_tasks\run-stryker_400ea42f-b258-4da4-9a55-68b174cae84c\0.14.0\run-stryker.ps1:17 char:25
+ $(Agent.BuildDirectory)/tools/dotnet-stryker
+ ~~~~~~~~~~~~~~~~~~~~
Unexpected token 'tools/dotnet-stryker' in expression or statement.
at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
at System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace rs, Boolean performSyncInvoke)
at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync)
at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
at Microsoft.TeamFoundation.DistributedTask.Handlers.LegacyVSTSPowerShellHost.VSTSPowerShellHost.Main(String[] args)
##[error]LegacyVSTSPowerShellHost.exe completed with return code: -1.
I've tried to implement small changes in my code like exchanging \ for / and wrapping it in "" but I end up always getting the same result.
Note that this same code works just fine if I run it inside an Azure Pipeline as inline PowerShell.
What am I missing here?

In a PowerShell script (it inline) you need to use the following syntax:
$env:Agent_BuildDirectory
Reference: https://learn.microsoft.com/en-us/azure/devops/pipelines/release/variables?view=azure-devops&tabs=batch#using-default-variables

How to use predefined variables in Azure DevOps PowerShell Task?
You could try to pass this predefined variable as a input in the task.json file, like:
"inputs": [
{
"name": "BuildDirectory",
"type": "string",
"label": "The Build Directory",
"defaultValue": "$(Agent.BuildDirectory)",
"required": true,
"helpMarkDown": "The folder of the test project to execute(e.g. Sample.Tests.csproj)."
},
Then in the run-stryker.ps1 file:
param(
[string] $BuildDirectory
)

It ended up being that my issue was not related with Azure Devops variables, but with the fact that I was trying to run a string as if it was a Powershell command.
Solved it with a simple Invoke-Expression.
Invoke-Expression "$(Agent.BuildDirectory)/tools/dotnet-stryker"

Related

Azure DevOps Pipeline - Create a Synapse managed-private-endpoints to a Azure Storage Account

I am trying to create a 'Synapse Managed private endpoint' to an Azure storage account via a 'Azure cli' task as a step in a pipeline. I want to create the MPE automatically.
The pipeline step calls a power-shell script with parameters. The script is located in source control. Calling the script and passing in parameter values is working fine.
Within the powershell script the following happens...
Get the json template (see below) from source control - this step works.
In the powershell script subsitute the json fields enclosed in <...> with a the parameter values passed in to the power-shell script - this works fine. The converted json is shown in the below screenshot.NB: sensitive values have been readacted here but look correct...
The line in the power-shell that's raising the error is...
az synapse managed-private-endpoints create --workspace-name "$pSynapseWorkspaceName" --pe-name "$pPrivateEndpointName" --file $mpeArmJson --debug --verbose
I think it's to do with the json-string parmater $mpeArmJson and double-quotes - this is what I need help solving ???
The value of $mpeArmJson which the value at this point is (note sensitive values have been readacted here but look correct)...
{
"name": "dds2-datalake-endpoint",
"properties": {
"privateLinkResourceId": "/subscriptions/<redacted subscription id>/resourceGroups/dds2-data-tst-rg/providers/Microsoft.Storage/storageAccounts/dds2datatstdlksa",
"groupId": "dfs",
"fqdns": [
"<redacted-storage-account>.dfs.core.windows.net"
]
}
}
In my Azure devOps pipeline I have created a 'Azure Powershell' task. The task calls a PowerShell script stored in source-control - taking in parameters.
Inside the powershell script I am calling...
New-AzSynapseManagedPrivateEndpoint -WorkspaceName "$pSynapseWorkspaceName" -Name "$pPrivateEndpointName" -DefinitionFile "$tmpDir"
NB: the devOps pipeline runs under a Az 'service principal' which creates the Synapse workspace and in doing so gets the 'owner' and also a 'synapse admin.' permissions automatically set in IAM.
The 'service principal' also needs 'blob storage data contributor' on the main storage account linked to Synapse.

Read DevOps Variable as bool in ARM paramters

I am trying to read in a pipeline variable as a bool. I have the following parameters defined in json:
"parameters": {
"disableFunkyFunction": {
"value": "#{myVariables.disableFunkyFunction}#",
"type": "bool"
}...
}
In my Azure DevOps release pipeline, I have a pipeline variable called myVariables.disableFunkyFunction and the value for it is set to true. However, whenever I try and run the pipeline, it fails on the "Azure resource group deployment" step: Template parameter 'disableFunkyFunction' was provided an invalid value. Expected a value of type 'Boolean', but received a value of type 'String'. I have tried using a value of 1 instead, but to no avail.
The following works, but ideally I want to read the value from the DevOps pipeline variable, not hard code it in the parameters file:
"parameters": {
"disableFunkyFunction": {
"value": true,
"type": "bool"
}...
}
Any suggestions?
From the error message, it seems that the pipeline variable value hasn't been passed to ARM template file.
Since you have set the parameter value as #{myVariables.disableFunkyFunction}#, you can try to use the Replace Token task from Replace Tokens Extension.
Here are the steps:
Step1: Keep the parameter value as #{myVariables.disableFunkyFunction}#.
Step2: Use Replace token task to set the value.
Step3: Deploy the ARM template.
For example:
Note: You need to put the Replace token task before the ARM template deployment step.

Passing parameters using AZ CLI for ARM template deployment

I am trying to use az group deployment create to perform an ARM template deployment and I want to pass in parameters where the values are defined in variables. I can do a single parameter with no issues using the syntax below:
--parameters parameter1=$var1
But when I try to add additional parameters using the syntax below, it fails:
--parameters parameter1=$var1, parameter2=$var2
The syntax below fails as well since it will not use the values of the variables:
--parameters '{
"parameter1": { "value": "$var1" },
"parameter2": { "value": "$var2" }
}'
Does anyone know if what I am trying to do is possible and what the correct syntax would be?
I was fighting a combination of a corrupt shell and slightly incorrect syntax. The correct syntax for what I was trying to do is listed below:
--parameters parameter1=$var1 parameter2=$var2
Or, for a cleaning view when several parameters are involved:
--parameters parameter1=$var1 `
parameter2=$var2 `
parameter3=$var3

How to replace variables of JSON file in Team Services?

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

Starting Runbook via Azure API, Portal, or ISE Add-On yields "input parameter type mismatch" error

Given a simple runbook:
workflow test
{
[CmdletBinding()]
param([string] $NumericString)
write-output $NumericString
}
When starting it with a numeric value (ie: 5) via the Azure Portal as a new Job (published), via the Test Pane, or using the Azure Automation PowerShell ISE Add-On, the following error is returned and the execution Fails.
[edit] Just out of curiosity I tried some other values. 'true' or 'false' (without quotes in ise/the ui) will also cause the error (and are sent to the API inside quotes).[\edit]
The values provided for the root activity's arguments did not satisfy
the root activity's requirements: 'DynamicActivity': Expected an input
parameter value of type 'System.String' for parameter named 'Numeric'.
Parameter name: rootArgumentValues
AFAIK, this is not a factor when I've executed via a parent runbook, webhook, etc.
The PowerShell ISE Add-On issues this PUT request to the API:
(https://management.azure.com/subscriptions/<id>/resourceGroups/<rg>/providers/Microsoft.Automation/automationAccounts/<aa>/runbooks/<rb>/draft/testJob?api-version=2015-10-31)
{
"parameters": {
"Numeric": "5" <-- notice it's a string
}
}
This is a bug in the Automation portal and ISE add on. For portal, this should be fixed in a week or so. For ISE add on, can you please file a bug on this here: https://github.com/azureautomation/azure-automation-ise-addon/issues
This would appear to be a bug, similar to Azure Automation Error 'DynamicActivity': Expected an input parameter value of type
To mitigate the issue, just wrap your numeric value in quotes in the Portal or ISE Add-On
If you are starting runbooks outside of the formal SDKs, it appears you need to know about required extra escaping for sending Numeric or Boolean values for string parameters (in the least).
This is what the subsequent PUT request should look like (from ISE Add-On)
{
"parameters": {
"Numeric": "\"5\""
}
}