Jenkins function definition: call a batch file using function arguments - batch-file

Here is a chunk of code I have in a pipeline:
def doBuild(folder, script, scriptArguments = '') {
bat '''cd folder
call script scriptArgument'''
}
So basically, it is a windows command saying: move to this directory, and call this script.
Of course, during execution, the command will be executed as 'cd folder' and will fail.
How can I make sure the 'folder' is replaced by the value passed in argument ?
Edit:
Following the suggestion of Vitalii, I tried the following code:
/* Environment Properties */
repository_name = 'toto'
extra_repository_branch = 'master'
branch_to_build = "${env.BRANCH_NAME}"
version = "${branch_to_build}_v1.5.4.${env.BUILD_NUMBER}"
/* Methods definitions properties */
def doTag() {
dir(repository_name) {
String tagCommand = """git tag -m "Release tag ${env.BUILD_URL}" ${version}"""
String pushCommand = "git push --tags origin ${branch_to_build}"
bat '''
call $tagCommand
call $pushCommand'''
}
}
Here is the output:
C:\Jenkins\toto>call $tagCommand '$tagCommand' is not recognized
as an internal or external command, operable program or batch file.
C:\Jenkins\toto>call $pushCommand '$pushCommand' is not
recognized as an internal or external command, operable program or
batch file.
Thanks very much for your time

You can use string interpolation
bat """cd $folder
call $script $scriptArgument"""

So I did not think it was the case first but it was really had its answer in What's the difference of strings within single or double quotes in groovy?
Using single quotes, the text is considered as literrate. Using double code, it will interpret correctly the $tagCommand. A working version is:
/* Methods definitions properties */
def doTag() {
dir(repository_name) {
String tagCommand = """git tag -m "Release tag ${env.BUILD_URL}" ${version}"""
String pushCommand = "git push --tags origin ${branch_to_build}"
bat """call $tagCommand
call $pushCommand"""
}
}

Related

CakePHP 4 custom shell script on Command

Is there any way of running a shell command DIRECTLY on the Command Class for CAkePHP4?
I would like something like this.
class SyncProjectsCoursesCommand extends Command
{
public function execute(Arguments $args, ConsoleIo $io): int
{
// Custom MySQL shell command
$this->run("mysql -u qstimuser --password=$DPASS --database=tims2 --host=10.10.9.60 --execute='...'");
// Or customer .sh file on Linux bin
$this->run("custom-shell-command.sh")
return static::CODE_SUCCESS;
}
}
?>
Command::run() is used to run the current command, you don't call it yourself for any other purpose, it will get called when you run the command from the CLI.
There are no specific methods to run external executables, but CakePHP is still just PHP, so you can use the native PHP commands. Long story short, use PHP's native methods, like exec(), system(), passthru(), etc... (and don't forget to escape input that you pass to the CLI!):
$DPASS = escapeshellarg($DPASS);
$result = exec("mysql -u qstimuser --password={$DPASS} --database=tims2 --host=10.10.9.60 --execute='...'");
See also
PHP Manual > Function Reference > Process Control Extensions

Save commit message strng value in an envionment variable via Jenkins with bat (Windows) and using Pipeline?

I would like to save the value of some string (in this case the commit message from Git) as an environment variable for a multibranch pipeline in Jenkins. This is part of my my pipeline:
pipeline {
agent any
environment {
GIT_MESSAGE = """${bat(
script: 'git log --no-walk --format=format:%s ${%GIT_COMMIT%}',
returnStdout: true
)}""".trim()
}
stages {
stage('Environment A'){
steps{
bat 'echo %GIT_MESSAGE%'
bat '%GIT_MESSAGE%'
}
}
...
}
But after this, the echo %GIT_MESSAGE% is retruning:
echo D:\.jenkins\workspace\folder log --no-walk --format=format:GIT_COMMIT} 1>git
And naturally if I run it with bat '%GIT_MESSAGE%' it fails. I know part of the answer may lay in the way to pass the environment variable to the bat script ${%GIT_COMMIT%} but I do not seem to be able to figure out how.
Any ideas?
I just solved this issue. It had to do with the way groovy performs string interpolation. I left it working with single line strings (i.e. "...") but I am pretty sure it should work with multiline strings ("""...""").
This is the working solution for now:
pipeline {
agent any
environment {
GIT_MESSAGE = "${bat(script: "git log --no-walk --format=format:%%s ${GIT_COMMIT}", returnStdout: true)}".readLines().drop(2).join(" ")
}
stages {
stage('Environment A'){
steps{
bat 'echo %GIT_MESSAGE%'
bat '%GIT_MESSAGE%'
}
}
...
}
Notice that readLines(), drop(2) and join(" ") where necessary in order to get the commit message only without the path from which the command was run.
Also it was important to use "..." inside the script parameter of the bat function, otherwise interpolation does not happen and the environment variable GIT_COMMIT would have not been recognized.

How to perform Git command using variables in Batch via Jenkinsfile

I have the following Jenkinfile content that is able to create the tag name as I want and stored in the varibale 'tag'. How can I use that variable in a batch command here?
Note that Jenkins is on a Windows machine thus using bat command. Am all ears if there is a simple way I could switch to bash. But the main question is as follows. Thank you.
How can I use that 'tag' variable (which has correct value stored before I try to use it in a batch command)? Currently it is coming out with no value with my implementation below trying to echo it.
#!/usr/bin/groovy
pipeline{
agent any
stages {
stage('tag stage'){
steps {
gitTag()
}
}
}
}
def gitTag(){
String date = new Date().format('yyyyMMddhhmmss')
String branch = "${env.GIT_BRANCH}"
String tag = "v${date}-${branch}"
tag = tag.replaceAll('/', '-')
String message = "tagged via jenkins - ${tag}"
print message
bat 'echo Hello test'
bat 'echo from bat before tag %tag% after tag'
bat 'git tag -a %tag% -m "tagging with %message%"'
bat 'git push origin %tag%'
}
Seems due to single quote, groovy is not able to interpolate the variable. Also, use ${var} format. Following should do the trick:
def gitTag(){
String date = new Date().format('yyyyMMddhhmmss')
String branch = "${env.GIT_BRANCH}"
String tag = "v${date}-${branch}"
tag = tag.replaceAll('/', '-')
String message = "tagged via jenkins - ${tag}"
print message
bat "echo from bat before tag ${tag} after tag"
bat "git tag -a ${tag} -m \"tagging with ${message}\""
bat "git push origin ${tag}"
}
I would probably prefer to create the tag in an environment block, then reference the environment tag in my shell script.
def gitTagName(String branch) {
String date = new Date().format('yyyyMMddhhmmss')
String tag = "v${date}-${branch}".replaceAll('/', '-')
return tag
}
pipeline {
agent any
stages {
stage('tag and publish') {
// N.B. this could be inside the "pipeline" block too, depending on scope
environment {
tag = gitTagName(env.GIT_BRANCH)
}
steps {
bat """\
echo from bat before tag ${env.tag} after tag
git tag -a ${tag} -m "tagging with tagged via jenkins - ${tag}"
git push origin ${tag}"""
}
}
}
}
I would probably pull that batch script into your repository while you're at it, though that might be a little over-zealous.

Run command on local build, but not TFS build

My post-build event is:
"$(DevEnvDir)TF.exe" checkout "$(TargetPath)"
This checks out the target build assembly file. This is what I want, and it works great in VS.
On the build server, $(DevEnvDir) is equal to *Undefined*. So, I modified my post-build event to the following:
IF NOT "$(DevEnvDir)" == '*Undefined*' "$(DevEnvDir)TF.exe" checkout "$(TargetPath)"
The problem is, it still evaluates to see if $(DevEnvDir)TF.exe is an executable, and on the build server it evaluates to *Undefined*TF.exe, which throws this error:
'"*Undefined*TF.exe"' is not recognized as an internal or external command, operable program or batch file.
How can I conditionally execute this statement without it evaluating if the executable exists first?
To run a command conditionally like this, use PowerShell:
if ('$(DevEnvDir)' -ne '*Undefined*') { [System.Diagnostics.Process]::Start('$(DevEnvDir)TF.exe', 'checkout "$(TargetPath)"') }
And wrap it in a clean PS environment:
powershell -windowstyle hidden -nologo -noprofile if ('$(DevEnvDir)' -ne '*Undefined*') { [System.Diagnostics.Process]::Start('$(DevEnvDir)TF.exe', 'checkout "$(TargetPath)"') }

Creating a shortcut for a exe using a batch file

I know a topic already exists like that but I do not want to use a VB script.
I would hope you can create a shortcut using a command line in DOS.
Please post some example that would be great.
Thanks!
AA
You can't create a shortcut in a .bat file without invoking an external program.
However, every version of Windows since Win2k has a built in scripting language called Windows Script Host
Here is a small WSH script that I wrote a few years ago that can be called from a .bat file,
just save this text as shortcut.wsf, it contains useage information in the script.
<package>
<job id="MakeShortcut">
<runtime>
<description>Create a shortcut (.lnk) file.</description>
<named
name = "Target"
helpstring = "the target script"
type = "string"
required = "true"
/>
<named
name = "Args"
helpstring = "arguments to pass to the script"
type = "string"
required = "false"
/>
<unnamed
name = "basename"
helpstring = "basename of the lnk file to create"
type = "string"
required = "false"
/>
</runtime>
<script language="JScript">
if ( ! WScript.Arguments.Named.Exists("Target"))
{
WScript.Arguments.ShowUsage();
WScript.Quit(2);
}
target = WScript.Arguments.Named.Item("Target");
WScript.Echo("target " + target);
args = WScript.Arguments.Named.Item("Args");
WScript.Echo("args " + args);
base = WScript.Arguments.Unnamed.Item(0);
WScript.Echo("base " + base);
fso = WScript.CreateObject("Scripting.FileSystemObject");
//path = fso.GetParentFolderName(WScript.ScriptFullName);
path = fso.GetAbsolutePathName(".");
WScript.Echo("path = " + path);
Shell = WScript.CreateObject("WScript.Shell");
short = fso.BuildPath(path,base);
if ( ! fso.GetExtensionName(base))
short = short + ".lnk";
link = Shell.CreateShortcut(short);
link.TargetPath = fso.BuildPath(path, target);
if (args != null && args != "")
link.Arguments = args;
else
link.Arguments = base;
//link.Description = "Sound Forge script link";
//link.HotKey = "ALT+CTRL+F";
//link.IconLocation = fso.BuildPath(path, target) + ", 2";
//link.WindowStyle = "1"
//link.WorkingDirectory = path;
link.Save();
</script>
</job>
</package>
run it without any arguments to get useage
c:\> shortcut.wsf
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Create a shortcut (.lnk) file.
Usage: shortcut.wsf /Target:value [/Args:value] [basename]
Options:
Target : the target script
Args : arguments to pass to the script
basename : basename of the lnk file to create
mklink /D c:\vim "C:\Program Files (x86)\Vim"
More Info Here
And Cygwin's ln - s
http://en.wikipedia.org/wiki/Symbolic_link#Cygwin_symbolic_links
Creating a shortcut in the .lnk format is basically impossible from a batch file without calling an external program of some kind. The file spec can be found here, and a quick glace will explain.
Creating a .url format shortcut is quite easy as the format is a simple text file. The spec can be found here. This format has a few disadvantages, but may accomplish your goal.
you can get shortcut.exe from the resource kit.
It can now be done with Powershell, which arguably sucks somewhat less than VBscript. And powershell can be called from a .bat / .cmd file:
powershell "$s=(New-Object -COM WScript.Shell).CreateShortcut('%userprofile%\Desktop\mylink.lnk'); $s.TargetPath='C:\Path\to\your.exe'; $s.Save()"
See also here for another example: https://ss64.com/nt/shortcut.html#e
See also

Resources