AzureKeyVault#2 Task & retrieve key vault value retrieval by variable? - azure-devops

So I have a variable in a variables.yaml file called keyVaultSecretToRetrieve. It can vary based on environment. Previously this pipeline was coded for single environment. So lets say the keyVaultSecretToRetrieve is "secret1". If in the task I put SecretsFilter: "secret1" and run the task and try to reference $(secret1) in the following task everything works great.
But my problem is that if I put it like the example below as SecretsFilter $(keyVaultSecretToRetrieve). How can I then retrieve the value? Its almost like I would want to do something like if it where possible $($(keyVaultSecretToRetrieve)).
I know my other option is to just run the command in a script using azure CLI which I tried but the build server says it does not have azure cli installed and I'd rather not mess with it and just wrap this up quickly. Not sure if there is some way to achieve what I want?
It's a windows build agent and the steps after this are mostly PowerShell. I wish the task just returns a data structure vs. dynamically named variables.... This is throwing me off it there is some trick I can do to make it work that I'm not aware of vs. just being forced to go the azure cli route or have the variable name coded in the variables name vs. as another variables.....
- task: AzureKeyVault#2
displayName: Retrieve from keyvault
inputs:
azureSubscription: $(serviceConnection)
KeyVaultName: $(keyVaultName)
SecretsFilter: $(keyVaultSecretToRetrieve)
RunAsPreJob: false

Based on your requirement, you need to use nested variable: $($(keyVaultSecretToRetrieve)). There is no built-in feature can support this requirement.
To achieve your requirement, you can use the Variable Set task from extension: Variable Toolbox.
For example:
steps
- task: VariableSetTask#2
inputs:
variableName: NewVariable
Value: '$($(keyVaultSecretToRetrieve))'
It will create a new variable based on the nested variable:$($(keyVaultSecretToRetrieve)). Then you can use the $(NewVariable) in the next tasks.

Related

Passing variables between release pipelines in azure (trigger azure pipeline extension)

I have a requirement to pass data between 2 release pipelines (to trigger 2nd pipeline on completion of 1st pipeline).
Can we pass variables dynamically between azure RELEASE pipelines using trigger an Azure DevOps pipeline extension?
I tried this blog but unable to find/understand if we can use "output variables" to pass data between azure release pipelines.
https://msftplayground.com/2019/02/trigger-a-pipeline-from-an-azure-devops-pipeline/
Thank you in advance!
Output variables are created by the pipeline and referenced by the other tasks in the pipeline, it means they are dynamic and refers to the result of a particular task.
These cannot be defined statically.
After running the task in the pipeline, output variables value can be known.
There are two different ways to create output variables :
By building support for the variable in the task itself
Setting the value ad-hoc in a script
Below example is defining a task with the name SomeTask that natively creates an output variable called out.
In a task within that same job, you can reference that variable using $(SomeTask.out).
steps:
- task: MyTask#1
name: SomeTask
- script: echo $(SomeTask.out)
For the detailed information regarding how to create output variables and pass between the pipelines, please refer azure devops output variables.

Azure DevOps Pipeline - Using YAML, how can I have the build number set to dynamically change, based on the version defined in a different file? [duplicate]

In Azure DevOps, I created a Build. In that Build I created a ProjectBuildNumber Pipeline variable that is Settable at queue time. That variable is then used under Options -> Build number format to set my build number displayed in Azure.
However, I am trying to make that ProjectBuildNumber variable settable in the code I am building/deploying. Is there a way I can have a Task in my Build to update that ProjectBuildNumber and update the Build number in Azure DevOps?
Is there a way I can have a Task in my Build to update that ProjectBuildNumber and update the Build number in Azure DevOps?
The answer is yes.
You could add a Inline Power-Shell task in your build definition to update the value of ProjectBuildNumber and then update the build number base on the it:
Write-Host "##vso[task.setvariable variable=ProjectBuildNumber;]YourUpdateValue"
Write-Host "##vso[build.updatebuildnumber]xxx.$(ProjectBuildNumber).xxx.xxx"
Check the Logging Command during the build for some more details:
Besides, if you want to update the value of a Pipeline Variable on the UI/web portal, you need the REST API (Definitions - Update) to update the value of the build pipeline definition variable from a build task.
There is a very similar thread, you can check the answer for the details:
How to modify Azure DevOps release definition variable from a release task?
Note:Change the API to the build definitions:
PUT https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=5.0
Hope this helps.
We can update Build Number in Azure Devops via two ways .
One from Option Section/Tab and 2nd Via PowerShell Scripts.
To update the build number from Power shell Script.. We need to add following script..
Write-Host "##vso[build.updatebuildnumber]$(VersionNumber).$(VersionRevision)"
Here we have used 2 variables : VersionNumber and VersionRevision.
We need to add 2 variables in PipeLine Configurations..
VersionNumber will be the desired number and VersionRevision is the counter number that will be updated every time, when ever we will create a new build.
Please check the complete demonstration from You tube video
https://youtu.be/WBmFTmzopiQ
Have created power shell task for that
# replace existing Build.BuildNumber with
# NAME_2.1.2.54_20211220.16_345
- task: PowerShell#2
displayName: 'Update Version Number'
inputs:
targetType: 'inline'
script: |
$lines = Get-ChildItem ".\Project\My Project\AssemblyInfo.vb"
$match = $lines | Select-String -Pattern "\<Assembly\:\s+AssemblyVersion\(""(\d+\.\d+\.\d+\.\d+)""\)\>"
$version = $match.Matches[0].Groups[1].Value
[Version]::Parse($version) # validate
$tag = "NAME_$($version)_$(Build.BuildNumber)_$(Build.BuildId)"
Write-Host "##vso[build.updatebuildnumber]$tag"
Check out the Microsoft documentation on this: Variables
Depending on your operating system you can add a Powershell/Batch/Bash Task and change the variable.
Edit: After some research it appears that the change of the variable will show up in the following task. Take a look at this issue Update environment variables using task.setvariable in a bash script does not work

Pipeline parameter overwrites variable value

I have a pipeline in Azure DevOps somewhat like this:
parameters:
- name: Scenario
displayName: Scenario suite
type: string
default: 'Default'
variables:
Scenario: ${{ parameters.Scenario }}
...
steps:
- script: echo Scenario is $(Scenario)
And I'm executing the pipeline via the VSTS CLI like this:
vsts build queue ... --variables Scenario=Test
When I run my pipeline, it seems that the parameter default value overwrites my cmd line specified variable value and I get the step output Scenario is Default. I tried something like Scenario: $[coalesce(variables['Scenario'], ${{ parameters.Scenario }})] but I think I got the syntax wrong because that caused a parsing issue.
What would be the best way to only use the parameter value if the Scenario variable has not already been set?
What would be the best way to only use the parameter value if the
Scenario variable has not already been set?
Sorry but as I know your scenario is not supported by design. The Note here has stated that:
When you set a variable in the YAML file, don't define it in the web editor as settable at queue time. You can't currently change variables that are set in the YAML file at queue time. If you need a variable to be settable at queue time, don't set it in the YAML file.
The --variables switch in command can only be used to overwrite the variables which are marked as Settable at queue time. Since yaml pipeline doesn't support Settable variables by design, your --variables Scenario=Test won't actually be passed when queuing the yaml pipeline.
Here're my several tests to prove that:
1.Yaml pipeline which doesn't support Settable variable at Queue time:
pool:
vmImage: 'windows-latest'
variables:
Scenario: Test
steps:
- script: echo Scenario is $(Scenario)
I ran the command vsts build queue ... --variables Scenario=Test123, the pipeline run started but the output log would always be Scenario is Test instead of expected Scenario is Test123. It proves that it's not Pipeline parameter overwrites variable value, instead the --variables Scenario=xxx doesn't get passed cause yaml pipeline doesn't support Settable variables.
2.Create Classic UI build pipeline with pipeline variable Scenario:
Queuing it via command az pipelines build queue ... --variables Scenario=Test12345(It has the same function like vsts build queue ... --variables Scenario=Test) only gives this error:
Could not queue the build because there were validation errors or warnings.
3.Then enable the Settable at queue time option of this variable:
Run the same command again and now it works to queue the build. Also it succeeds to overwrite the original pipeline variable with the new value set in command-line.
You can do similar tests like what I did to figure out the cause of the behavior you met.
In addition:
VSTS CLI has been deprecated and replaced by Azure CLI with the Azure DevOps extension for a long time. So now it's more recommend to use az pipelines build queue
instead.
Lance had a great suggestion, but here is how I ended up solving it:
- name: Scenario
displayName: Scenario suite
type: string
default: 'Default'
variables:
ScenarioFinal: $[coalesce(variables['Scenario'], '${{ parameters.Scenario }}')]
...
steps:
- script: echo Scenario is $(ScenarioFinal)
In this case we use the coalesce expression to assign the value of a new variable, ScenarioFinal. This way we can still use --variables Scenario=Test via the CLI or use the parameter via the pipeline UI. coalesce will take the first non-null value and effectively "reorder" the precedence Lance linked to here: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#expansion-of-variables
(Note that there need to be single quotes around the parameter reference '${{}}' because the ${{}} is simply converted to to the value, but then the coalesce expression doesn't know how to interpret the raw value unless it has the single quotes around it to denote it as a string)
Note that the ability to set parameters via the CLI is a current feature suggestion here: https://github.com/Azure/azure-devops-cli-extension/issues/972

Is it possible to create additional pipeline steps based on a variable?

Is it possible in Azure Devops YAML pipelines to dynamically create additional steps based on some variable data (without creating our own plugin)
The thing is I see that I want to iterate through several directories, but I don't want to just lump it all in a single step since it makes it harder to scan through to find an error.
Is it possible in Azure Devops YAML pipelines to dynamically create
additional steps based on some variable data (without creating our own
plugin)
No, Yaml pipelines(azure-pipeline.yml) are under Version Control. So what you want (for your original title) is to dynamically commit changes to the azure-pipeline.yml file when executing the pipeline. That's not a recommended workflow.
1.Instead you can consider using Azure Devops Conditions to dynamically enable/disable the additional steps.
Use a template parameter as part of a condition
Use the output variable from a job in a condition in a subsequent job
Or Use some predefined variables:
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
2.If you're not using Conditions, you can check conditional template as Simon suggests above.
Also, both #1 and #2 can work with new feature runtime parameters.
3.However, if the dynamic variable you mean comes from the result of components = result of ls -1 $(Pipeline.Workspace)/components command, above tips won't work for this situation. For this you can try something like this:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
# some logic to run `components = result of ls -1 $(Pipeline.Workspace)/components` and determine whether to set the WhetherToRun=true.
'Write-Host "##vso[task.setvariable variable=WhetherToRun]True"'
- task: CmdLine#2
inputs:
script: |
echo Hello world
condition: eq(variables['WhetherToRun'], 'True')
It is possible to include steps conditionally with an if statement.
I think the example of extending a template on the same page will give you a good indication of how to iterate through a list parameter and create / run a step based on each value.

Azure pipeline variable default values

I am writing azure pipelines and using variables from variable groups. As part of adding flexibility, we are trying to make most of the parts of pipeline configurable ( more variables). So, i was looking for a way to add default value to variable if it is not present in variable group.
The way we use is like below:
variables:
dockerId: $(docker_id)
imageName: $(DOCKER_IMAGE_NAME)
Is there option to specify default for the variable, if it doesn't find it from variable group. Something like below:
variables:
dockerId: $(docker_id:"defaultDockerId")
imageName: $(DOCKER_IMAGE_NAME:"defaultDockerImageName")
You cannot achieve this directly in azure pipeline. Azure pipeline doesnot have this feature currently and this syntax $(docker_id:"defaultDockerId") is not supported.
As workaround, you may have to write scripts in script tasks to assign the default value if the variables are not exist.
Please check out below python script:
The first python script task checks if the variable exists and set a default value for it, and define the variable using print("##vso[task.setvariable variable=variableName]value").
(Please note the variable variableTest value can only be referenced in the following tasks.)
- task: PythonScript#0
displayName: 'setDefaultValue'
inputs:
scriptSource: inline
script: |
import os
b = os.getenv("variableTest","default value for variableTest")
print("##vso[task.setvariable variable=variableTest]{b}".format(b=b))
- task: PythonScript#0
displayName: 'Run a Python script'
inputs:
scriptSource: inline
script: |
print("$(variableTest)")
Hope above helps!
The comment is correct, you cannot have defaults (unless you are using templates and parameters, which you might want to look at, but they are not exactly the thing you are after). You can either use an if condition if you know when the variable exists or not (in the yaml file) or use a script task like the comment suggests and calculate the value in the script task and emit it back to the pipeline.