Setting variables in TFS RMI tasks - tfs

TFS release management has a concept of variables. They're set in the release definition at design time. Is there a way for tasks to change variables so that other tasks see the changes?
The Windows SET command only affects the environment of the currently executing instance of cmd.exe, it doesn't affect the enclosing process' environment.
Passing info from step to step in a temp file in the working folder is possible, but crude.

I believe so. I have not tested this, but take a look at this VSO Build Task:
https://marketplace.visualstudio.com/items?itemName=jessehouwing.jessehouwing-vsts-variable-tasks
It has a task where it can set the variable. Here is the specific powershell script it calls:
https://github.com/jessehouwing/vsts-variable-tasks/blob/master/vsts-variable-set/vsts-variable-set.ps1
Line 22:
Write-Host "##vso[task.setvariable variable=$($VariableName);]$Value"
UPDATE:
I have since found Microsoft documentation here:
https://github.com/Microsoft/vsts-tasks/blob/master/docs/authoring/commands.md
Specifically:
vso[task.setvariable]value
variable=variable name (Required)
issecret=true (Optional)
Sets a variable in the variable service of taskcontext. The first task can set a variable, and following tasks are able to use the variable. The variable is exposed to the following tasks as an environment variable. When issecret is set to true, the value of the variable will be saved as secret and masked out from log. Secret variables are not passed into tasks as environment variables and must be passed as inputs.
Examples:
##vso[task.setvariable variable=testvar;]testvalue
##vso[task.setvariable variable=testvar;issecret=true;]testvalue

Related

date variable in TFS

I am trying to create a variable in TFS for my task for timestamp in format yyyymmdd. I know that I create a task specifically for this using bash or powershell. However, I am looking to find some existing variable or some way to create this variable without having to setup a task dedicated for itself.
So far I have tried to use $(Date:yyyymmdd) in my variables but it does not put values in it, it uses variable name as is.
For example, C:\Alpha\beta\$(Date:yyyymmdd) instead of C:\Alpha\beta\20191107
Can anyone help me with this ? Thanks a lot
Actually, it is hence not expanded. We do not have this kind of system or environment variable which get current date time and work every. You may have noticed you could use $(Date), however which is only available in the Build number format section. Others such as $(Rev:r) and $(DateOfYear) are the same, do not work outside the BuildNumberFormat-Settings..
Take a look at the list of all system and environment variables here: Predefined variables
As you have pointed out, you need to use a script in a PowerShell Task to set a variable in your build definition, a sample:
$date=$(Get-Date -Format 'yyyymmdd');
Write-Host "##vso[task.setvariable variable=time]$date"
Then you can use $(time) in your subsequent build tasks.
More details also take a look at this similar question: VSO(TFS) - get current date time as variable

Why one can set TFS predefined variables when they are said to be read-only?

According to https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=tfs-2018
These variables are automatically set by the system and read-only. (The exceptions are Build.Clean and System.Debug.)
Nonetheless, if one tries to create a vnext build with the following tasks
Inline Powershell - Write-Host $env:BUILD_SOURCEVERSION
Inline Powershell - Write-Host ("##vso[task.setvariable variable=build.sourceversion;]"+'someNewValue')
Inline Powershell - Write-Host $env:BUILD_SOURCEVERSION
Task 2 won't fail, and the last task will output something like
2018-10-24T07:37:23.1232438Z someNewValue
instead of the expected original source version (the value printed in the first task).
So,
Either I am misreading the docs / they are unclear on that account
Or is it some genuine defect in TFS that one should pursue with MS?
That's expected behavior.
The predefined variables are automatically set by the system and read-only.
However if you have defined a pipeline variable of the same name
as an environment variable (for example, PATH), your pipeline variable
value overrides the agent host's environment variable.
See Environment variables for details.
So, in your scenario actually you defined a new pipeline variable with the same name as the pre-defined one, but not really overwrite the predefined variable. And they can only be used in the pipelines...
UPDATE:
Well, the documentation is somewhat misleading about the Environment Variables and makes some slightly contradictory claims about their readonlyness. Actually all variables (*predefined, build, environment...) basically work as the environment variables mentioned here.
BTW, you can get all the available environment variables by get-childitem -path env:* in pipeline.*
PowerShell script for example:
$environmentVars = get-childitem -path env:*
foreach($var in $environmentVars)
{
$keyname = $var.Key
$keyvalue = $var.Value
Write-Output "${keyname}: $keyvalue"
}

TFS. Pass variable from triggered build to next task in a release

I want to pass variable between release tasks. (from triggered build to script)
Files:
Script1: (saves a env variable)
Write-Output ("##vso[task.setvariable variable=MyVar;]$MyVarValue")
Script2: (prints the env variable value)
Write-host $env:MyVar
Script3: (same as Script2)
Write-host $env:MyVar
First approach: build
MyBuild:
Script1
Script2
This is working properly, the second script writes the value of $env:MyVar created in the first.
Second Approach: release
- MyRelease:
Script1
Script2
Also works properly.
My problem comes when my release changes to:
MyRelease:
Triggered_build (MyBuild)
Script3
In that last case, the Script3 is not printing the $env:MyVar, so I guess that release uses a different environment than the used for the triggered build?
Is there a way to do something like that?
No way to do that directly with TFS.
I have read about variable groups, but is not possible to set the variables dynamically in execution time with a script.
The only solution found is using the plugin Variable (de|re)Hydration Tasks
Solution from: Is possible to pass a variable from a Build to a Release in TFS 2017?

How to change a tfs build variable in script

I'm using TFS2015 update 1. I want to pass information from one build step to the next, how is this possible?
That seems like a very simple task, but I can't figure out how that's suppose to work. Passing a variable to a build step is easy, but passing information from one step to the next seems to be impossible. I hope I'm wrong.
You can call the task.setvariable Logging Command, which sets a variable in the variable service of taskcontext. The first task can set a variable, and following tasks are able to use the variable. The variable is exposed to the following tasks as an environment variable.
Example:
##vso[task.setvariable variable=testvar;]testvalue

Can a workflow step access environment variables provided by an EnvironmentContributingAction?

A custom plugin we wrote for an older version of Jenkins uses an EnvironmentContributingAction to provide environment variables to the execution so they could be used in future build steps and passed as parameters to downstream jobs.
While attempting to convert our build to workflow, I'm having trouble accessing these variables:
node {
// this step queries an API and puts the results in
// environment variables called FE1|BE1_INTERNAL_ADDRESS
step([$class: 'SomeClass', parameter: foo])
// this ends up echoing 'null and null'
echo "${env.FE1_INTERNAL_ADDRESS} and ${env.BE1_INTERNAL_ADDRESS}"
}
Is there a way to access the environment variable that was injected? Do I have to convert this functionality to a build wrapper instead?
EnvironmentContributingAction is currently limited to AbstractBuilds, which WorkflowRuns are not, so pending JENKINS-29537 which I just filed, your plugin would need to be modified somehow. Options include:
Have the builder add a plain Action instead, then register an EnvironmentContributor whose buildEnvironmentFor(Run, …) checks for its presence using Run.getAction(Class).
Switch to a SimpleBuildWrapper which defines the environment variables within a scope, then invoke it from Workflow using the wrap step.
Depend on workflow-step-api and define a custom Workflow Step with comparable functionality but directly returning a List<String> or whatever makes sense in your context. (code sample)
Since PR-2975 is merged, you are able to use new interface:
void buildEnvVars(#Nonnull Run<?, ?> run, #Nonnull EnvVars env, #CheckForNull Node node)
It will be used by old type of builds as well.

Resources