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

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?

Related

Post-build Actions part does not see injected environment variable

A script generates a properties file to work-space in an Execute shell block in the Build section. This file is available at work-space after script execution and in case of Failed build (Conditional steps (multiple) block in the Build section) this properties file will be injected. My Jenkins job sends an E-mail (Editable Email Notification block) in case if Failed build and it should contains the variable from properties file but it doesn't see this variable. FYI: This block can use other environment variables.
I have cross-checked the properties file and it contains the required variable in every case.
Properties file in work-space:
Environment variable injection from properties file:
This Steps to to run if condition is met block contains more other actions and these work fine. It means the running can reach this block.
Editable Email Notification block in Post-build:
If I check the Environment Variables option in a build, I can see the variable:
But when I get the mail, it doesn't contain the variable:
Any idea how can I solve it or what should I change?
NOTE: The variable is unique and not really related to Gerrit so I cannot use another variable which comes form Gerrit. Just the name of var is a little tricky.
I have found the answer for my question. The Jenkins or the plugin has limitation. It cannot handle the Failure state. If the previous execute shell block is failed then the running won't reach the Conditional steps (multiple) block.
On the other hand, I have found a "workaround" for this problem.
1. step
You need to exit from the Execute shell block with a specific return code. Eg.: 111
2. step
You need to set the Exit code to set build unstable filed to your specific exit code. (You can find this field in advanced option of Execute shell block.) As you can see in the below picture.
3. step
Set the Conditional steps (multiple) block to handle the Unstable state. With this solution the running is able to run into Conditional steps (multiple) block.
4. step
Create an Execute shell block inside the Conditional steps (multiple) block after you prepare everything what you want in case of job failed. It means after this block your job status changes to Failed from Unstable.
Whit this solution you can handle the failed job and in the end you will get a real failed job (not unstable).
Not the most elegant solution but it works.

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"
}

Setting variables in TFS RMI tasks

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

Passing variable from shell to email-ext in Jenkins

I have Jenkins job that has execute shell part in which I have some variable
BUILD that is dynamically populated.
After build execution, I want to pass this variable to email-ext plugin Default Content to able to show it's value.
I've tried couple of ways without a success:
Passing this ${BUILD} value in Default Content is not recognized (Only Jenkins environment variables are visible in this context)
Defined new Jenkins global environment variable and tried to overwrite its initial value in shell context which apparently is not possible
Any idea on how to do this?
In my case, I'm not the administrator, then I can't install plugins. But can be done with a workaround.
In Content Token Reference help you can found an useful tool.
${PROPFILE,file="FILENAME",property="PROPERTYNAME"}
Expands to the value of a property in a property file. The filename is
relative to the build workspace root.
Then save values in a property file inside Build > Execute Shell:
rm -f ${WORKSPACE}/env.properties
touch ${WORKSPACE}/env.properties
store="/opt/current/store"
echo "store.folder=${store}" >> ${WORKSPACE}/env.properties
echo "${store}"
And read it from Post-build Actions > Editable Email Notification with:
${PROPFILE,file="env.properties",property="store.folder"}
Simple and easy:
In your "Execute Shell"
echo "test log" > /some/file/path/logFile.txt
Then in your "Editable Email Notification-Default Content"
${FILE,path="/some/file/path/logFile.txt"}
Build and you will receive a email with content "test log"
To see more email tokens, you can click the question mark beside "Content Token Reference" in "Editable Email Notification" section.
Use EnvInject Plugin to read the variable from a file, after you write that file in the "shell part".
In general, environment variables never go from child process back to parent process, this is basic feature of both Windows and Unix operating system families. Child always gets a copy of parent's environment, and if it modifies it, it modifies it's own copy (which is then copied to any child process if it launches any, etc). But to get changes back, some other method must be used, such as child writing desired changes to a file, which is then parsed by parent, which can then edit it's own environment based on it.
You can pass build parameters to email ext plugin by using:
${ENV,var="CAPITALIZED:VAR_NAME"}
In that way i see the variable value in the received mail.

The current build parameters/ENV Variables in different build steps

Is it possible to define a new build parameter/ENV variable in a build step so it was available in the next one?
Let's say I have 2 different "Execute shell" steps and want in the second step access the variable defined in the first one.
PS: the value for the variable is set in runtime - read from 3rd party resource, so I cannot harcode it, thus need to set it from the shell script.
The plugin EnvInject will do that for you.
It can be configured as pre-SCM step or as build steps. Put it in between your two existing build steps.
Update
In your case, it may be easier to just read the value of the "3rd party" file as part of your second build step:
var=$(<3rdpartyfile.txt)
After the above line, the contents of your 3rdpartyfile.txt will be available in environment variable var. You can now use $var as you would any other variable
You can also use something like
stage('stage-1') {
steps {
script{
env.variable = ${value};
}
}
}
Now you can use the variable env.variable throughout the pipeline

Resources