Jenkins: Escaping % in parameterized jobs - jenkins

I'm trying to run this command from shell as a build step on a Windows machine:
for /R . %f in (*.bin) do copy "%f" "..\Release\"
After struggling for a while figuring out why it doesn't work, I noticed this is a parameterized build and that parameters are of the form %var%. I assume is trying to replace % with an empty value since there's nothing defined. It is translated to on the first loop:
for /R . f" "..\Release\Newer\"
I guess I could define a parameter like %f% = %f and it might do the trick, but seems unnecessary.

First, I assume you are using Windows environment (you should really specify), and as such it is not a "shell" build step, but "Execute Windows Batch Command" build step (if it's not, you need to use "Execute Windows Batch Command" build step)
Next, it's a peculiarity of Windows Batch, that when you run it from command line, you can use a single % in the FOR statement, however when you run it from a batch file (and the batch build step is a temporary batch file), you need to use %%. Note, this only applies to the FOR statement as it uses a special syntax for the variables.
So change your line to:
for /R . %%f in (*.bin) do copy "%%f" "..\Release\"

Related

How do I pass information from one step in a TFS 2017 build to a later Copy Files step

OK - I've read all about environment variables and how they can't be set and read by the same process (even this can't be read by a later step in the build):
Environment.SetEnvironmentVariable("Major_Build_Number", BaseReleaseNumber, EnvironmentVariableTarget.Machine)
So has anyone come up with a simple way to pass along info from one build step to another? In my first step I determine the build number (this is a fairly complex process believe it or not) and I need to pass that build number to the last build step (which is a Copy Files step) so that it can copy the build into a folder that's named with the build number. I've tried setting an environment variable, but unfortunately that can't be set and read from the same session. There's gotta be a simple way to do this. Yes I could write a PS or batch script to do it and store the value in a file or the registry, but I would prefer to use the Copy Files task and I can't figure out how to pass that value along.
I tried defining a variable in the build definition and storing the value there but I can't seem to change that value after it's set in the build definition.
BTW, this is an on-premises installation - not VSTS.
Anyone have any ideas?
Thanks Andy for your response. So I tried this in SetBuildNumberENVVar.ps1
param([Int32]$MajorBuildNumber=0,[Int32]$MinorBuildNumber=0)
Write-Host "##vso[task.setvariable variable=MajorBuildNumber]$MajorBuildNumber"
Write-Host "##vso[task.setvariable variable=MinorBuildNumber]$MinorBuildNumber"
I then run it from the command line:
c:\powershell .\SetBuildNumberENVVar.ps1 23 45
and then try to echo the variable:
echo %MajorBuildNumber%
%MajorBuildNumber%
and as you can see it doesn't appear to work. I tried this from a C# script:
int.TryParse("$(MajorBuildNumber)", out mbn);
and mbn = 0 after this runs.
Any idea what I'm doing wrong?
Generally you can use the predefined variale $(Build.BuildNumber) to name the folder, it can be used directly in entire build process. See Predefined variables for details.
If you customed the build number variable as you said : "I determine the build number (this is a fairly complex process believe it or not)". Then you can pass the value with the Logging Command: ##vso[task.setvariable]value:
Add a PowserShell task in you build definition
Copy and paste below script and save it as *.ps1 file
$value= "The value of the build number here"
Write-Host "##vso[task.setvariable variable=BuildNumber]$value"
Check in the PS file, then run the PS file in PowerShell task
After that, you can use the variable $BuildNumber directly in any tasks behind the PowserShell task.
You can reference my answer in another similar thread : Custom TFS Enviroment Variable doesn't read $(Date)
UPDATE:
You need to run the PowerShell script in TFS build process.
See below example:
I created two PS scripts, one to set the variables to pass the value, another to use the variables to create a folder named with the passed values:
PS1: PassBuildNumber
param([Int32]$MajorBuildNumber=0,[Int32]$MinorBuildNumber=0)
Write-Host "##vso[task.setvariable variable=MajorBuildNumber]$MajorBuildNumber"
Write-Host "##vso[task.setvariable variable=MinorBuildNumber]$MinorBuildNumber"
PS2 : Use the variables
Write-Host "The Major build number is:" $env:MajorBuildNumber
Write-Host "The Minor build number is:" $env:MinorBuildNumber
$foldername = $env:MajorBuildNumber + "." + $env:MinorBuildNumber
Write-Host "foldername:" $foldername
$path = "\\myshare\DirA\$foldername"
Write-Host "path:" $path
New-Item -Path $path -ItemType directory # Create a folder
Write-Host "##vso[task.setvariable variable=path]$path" # Set path as a variable to be used in Copy Task
Then you can use Copy Files task to copy files to that folder.

Custom TFS Enviroment Variable doesn't read $(Date)

I want to use a custom tfs variable like this:
MergedVersion: $(BuildVersion.Major).$(BuildVersion.Minor).$(Date:yy)$(DayOfYear)$(Rev:.r)
My problem is that $(Date), $(Rev:r) and $(DateOfYear) don't work outside the BuildNumberFormat-Settings.
My result is:
invalid version string: '1.0.$(Date:yy)$(DayOfYear)$(Rev:.r)'.
While with the buildnumberformat like shown here - works correctly:
Result $(Build.BuildNumber) is MyBuildName_1.0.18004.15
Some tokens are only available in the Build number format section, such as $(Date), $(Rev:r) and $(DateOfYear) you mentioned here. See Build definition options
As a workaround, to use $(Rev:r)you can set the build number format as $(Rev:r), then use the $(Build.BuildNumber) variable in your tasks.
To use $(Date:yy)$(DayOfYear), you can set the variables via PowerShell task as ChamindaC mentioned above.
Add a PowserShell task in you build definition
Copy and paste below script and save it as *.ps1 file
Check in the PS file, then run the PS file in PowerShell task
$time=$(Get-Date -Format 'yy') # you can set the date format based on your requirement
$doy = (Get-Date).DayofYear
Write-Host "##vso[task.setvariable variable=Date]$time"
Write-Host "##vso[task.setvariable variable=DayOfYear]$doy"
Then you can use the variables $(Date) and $(DayOfYear) in other build tasks.
Use following script in a PowerShell Task in your build definition
$date=$(Get-Date -Format 'yy');
Write-Host "##vso[task.setvariable variable=Today]$date"
Then you can use $(Today) in your subsequent build tasks. However, usage like $(Today:yy) with format is not possible as it is supported only in build number format.
Building on top of #ChamindaC and #Andy Li-MSFT's answers, and using Peter Groenewegen's Xpirit Run Inline Powershell and Azure Powershell build extension, I was able to retrieve the $(rev:r) from the build number:
In the following MSBuild task I reference that as $(Revision).

How to make a Java console output a environment variable in Jenkins?

I am new to Jenkins and even though I found a few similar questions, none of the solutions seemed to work for me the way I need it to. It might look like a basic problem to some but for me it's a very big deal that I'm struggling with.
Basically, I built a project that executes Java Selenium code, which displays session ID in Jenkins' Console Output and that's what I need to add to environment variables to be used in the projects triggered after completion of this one.
I tried some Groovy scripts but I don't think I understand enough how to work with it and so whatever I was given, wasn't what I hoped to get.
Has anyone done something similar to provide some tips on how to achieve that?
Many thanks
There are two options (in theory, one of them doesn't work, see 2. below) depending on whether the printing is under your control or not.
Printing is under your control:
Write the session ID to a properties file, e.g. from-build-log.properties:
sessionId=...
Add post-build action → Trigger parameterized build on other projects →
This plugin triggers builds on other projects, with parameters that are predefined, or supplied by the finished build.
Every parameter will be passed to the target project(s), even if the target is not parameterized, or if no property of that name is defined.
Add parameters → Parameters from properties file
Use properties from file: from-build-log.properties
Printing is not under your control:
Add post-build action → Post build task → :
This feature allows you to associate shell or a batch scripts that perform some tasks on Hudson depending on the build log output. If the log text matches somewhere in the build log file, the script will execute. [...]
Java Regex are allowed, and groups can be used as script parameters. If the text is "Last Build : #(\d+)" and the script is "script.sh", then if the log contains a line "Last Build : #4", the script "script.sh 4" will be called.
Tasks → Script → :
[...] References %1, .. %n are allowed, and will be replaced by the groups matched by the Regex. %0 is the whole match.
Unfortunately this doesn't to work since there is an issue known since 2013: [JENKINS-17268] Post build task plugin: Passing arguments does not work as documented.
Build → Execute Windows batch command → Command:
#echo( & echo CMD: sessionId=123456789
Post build task → Tasks:
Log text: sessionId=(\d+)
Script:
#echo( & echo sessionId='%1'(!) of '%0'
Console Output:
...
[Freestyle-project] $ cmd /c call C:\Windows\TEMP\hudson4684581005071706054.bat
CMD: sessionId=123456789
C:\Program Files (x86)\Jenkins\workspace\Freestyle-project>exit 0
Performing Post build task...
Match found for :sessionId=(\d+) : True
Logical operation result is TRUE
Running script : #echo( & echo sessionId='%1'(!) of '%0'
[Freestyle-project] $ cmd /c call C:\Windows\TEMP\hudson1525182929053902824.bat
sessionId=''(!) of 'C:\Windows\TEMP\hudson1525182929053902824.bat'
C:\Program Files (x86)\Jenkins\workspace\Freestyle-project>exit 0
POST BUILD TASK : SUCCESS
END OF POST BUILD TASK : 0
Finished: SUCCESS
%0 is not the "the whole match" but the script's name, as usual with Windows command line. %1 is empty.
A workaround is:
Add build step → Execute shell → Command:
sed -En 's/.*(sessionId=[0-9]+)/\1/p' \
../../jobs/${JOB_NAME}/builds/${BUILD_NUMBER}/log > from-build-log.properties
Add post-build action → Trigger parameterized build on other projects
Add parameters → Parameters from properties file
Use properties from file: from-build-log.properties

How to add multiple commands in series in "Execute Windows Batch Command" in Jenkins

I have a requirement where I need to run certain commands in series in order to build my project. Can I have give all the commands together in series in Jenkins? How am I supposed to do that. If I give it like as shown below :
How can give the commands so that it will execute one after the other. Please help me.
You can run a series of commands in windows command prompt using & operator.
So below will work from a single line command
env.bat & ant & forced-db.bat
I think it's better to execute separate build steps, like:
Windows batch step: env.bat
Ant build step: ant build ...
Windows batch step: force-db.bat

Set a Jenkins variable after reading console log line / value --OR-- using the variables used by scripts / commands what Jenkins calls

I DONT need the following:
How to set a Jenkins env variable or
How to use a environment variables in Jenkins / windows shell / ant / etc scripts.
What I need is opposite of that.
Summary:
1. I have a Jenkins job: ABC_Build
2. This job calls a .bat file (which calls an ANT code / target for packaging / building a
build). As we are creating a build, this job know what's the new build label name and
ANT is storing it in a variable called "new.build.label". File used is build.xml.
(A NOTE to novice users: If you want to call many Windows commands (.bat / .cmd or
commands which creates a windows shell) then, you should call it using "call
script.bat -Dparam1 -Dparam2...." way).
Now, this job calls an another .bat file (which calls an ANT code /target) and uses one
of the parameter value which gets generated by first .bat file / ANT package target
call (i.e. "new.build.label"). As this is a separate .bat command call to call a new
session of ANT code/target, I need to pass the value of "new.build.label" during the
call of this step. File used here is deploy.xml.
Basically, I'm trying to see how can I set a variable in Jenkins, either by using:
a. reading the console output of my Jenkins job as I'm echoing the value of
new build label in the standard output / console output.
b. any other way, where I can set a jenkins variable using "new.build.label" ANT
variable (once first .bat / ANT package target is finished) and I'm ready to call
the 2nd .bat / .cmd / ANT call for doing deployment. Unfortunately, I can't do both
package / deploy at the same time.
I'm also not interested in knowing WHY CAN'T I call target deploy from first ANT
session when I already know the value of "new.build.label" as my main request is:
HOW TO set a jenkins variable using a "variable" which was used by one of the scripts (ANT/Jelly/Groovy/Maven/etc) that Jenkins called.
You can pass environment variables among Jenkins build steps via EnvInject plugin. In your particular case the following is probably the best way:
The first ANT should echo new.build.label into a properties file that can be read by EnvInject plugin, e.g.:
<echo message="new.build.label=${new.build.label}" file="envars.props" />
Create an Inject environment variables build step and set "Properties File Path" to envars.props (make sure you are dealing with paths correctly). Then new.build.label will be available as an environment variable to the rest of your build steps.
By the way, I think it is not a good practice to call ANT from batch files in Jenkins. Use ANT build step instead.

Resources