How to perform Git command using variables in Batch via Jenkinsfile - batch-file

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.

Related

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.

Unable to execute command with forward slash

I want to create a batch file to execute a set of Git commands to:
Fetch a new remote repository.
Create a local repository to track the remote and check the new local branch out.
Second Git command uses a forward slash (origin/[repositoryName]) and gives the following error:
"fatal: Missing branch name; try -b".
#ECHO OFF
SET /P branch = Enter remote branch name:
git fetch origin %branch%
git checkout --track origin/%branch%
First, git command fetches the remote repository.
Second git command gives error:
"fatal: "Missing branch name; try -b"
As mentioned in comments you should use the following piece of code:
#echo off
set /p "branch=Enter remote branch name: "
git fetch origin %branch%
git checkout --track origin/%branch%
which is slightly modified.
You don't need to scream in batch file :) it is a case insensitive language.
When you set variables don't add extra spaces around the =. Because then, interpreter interprets it as var<space> and <space>value.
Also, quote variable name and value in format like: set "var=value".

Retrieve output/status of a variable from batch file to jenkins pipeline

I am trying the retrieve the output/status of a variable available in bat to a jenkins pipeline by setting env variable initially as true.
My expectation is that based on the value of a variable assigned inside bat (i.e., status=false), next stage could not be executed since when expression is given in that stage:
pipeline {
agent any
environment{
STATUS='TRUE'
}
stages {
stage('test1') {
steps {
bat '''set status=FALSE
echo %status%'''
echo "$status"
}
}
stage('test2') {
when{
environment name: 'STATUS', value: 'TRUE'
}
steps {
input message: 'Push', ok: 'GO!!'
}
}
}
}
The output which I am currently getting is o/p: false for bat execution and next step provides the output as true.
The echo "$status" is in pipeline, where as the environment STATUS changes are done on the node. AFAIK this won't get reflected in the pipeline itself.
What you could do is use returnStdout: true and maintain this variable state in the pipeline
def script = '''set status=FALSE
echo %status%'''
def status = bat(script: script, returnStdout: true)
echo "$status"
Following hakamairi answer above, #echo off should be added to the beginning of the script string, otherwise returnStdout: true will return the command prompt as well.
Also, adding .trim() by the end of the bat script (after its closing bracket) might prove useful if using the value of the assigned status variable somewhere else, where line break by the end is undesirable.

Jenkins function definition: call a batch file using function arguments

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

Add batch variable to groovy email-ext pipeline

Not a pro on groovy or batch, but here goes.
I have a groovy script where a small part of it sends email when something fails in jenkins pipleine. Here is the catch code which sends email if something goes wrong.
catch (Exception e){
def buildNumber = env.BUILD_NUMBER
def buildurl = env.BUILD_URL
def buildjobname = env.JOB_NAME
bat 'for /f "delims=" %%a in (user_id.txt) do set USER_ID=%%a'
emailext body: "Failure in build number $buildNumber for the job name $buildjobname. See URL for more detail: $buildurl",
subject: "Failure in build number $buildNumber for the job name $buildjobname",
to:
}
As you can see I have a line which does some bat shell script where it stores the user_id content into the USER_ID variable by reading a file. Now I want to use the USER_ID variable in my to attribute (something like this: to: USER_ID) but it seems this is not the way to do it.
What am I misisng
Edit: I guess I have to use EnvInject plugin?
In a Jenkins pipelines code, you could use bat output to get your userId as a variable. Example :
catch (Exception e){
def buildNumber = env.BUILD_NUMBER
def buildurl = env.BUILD_URL
def buildjobname = env.JOB_NAME
def userId = bat script: 'for /f "delims=" %%a in (user_id.txt) do echo %%a', returnStdout: true
emailext body: "Failure in build number $buildNumber for the job name $buildjobname. See URL for more detail: $buildurl",
subject: "Failure in build number $buildNumber for the job name $buildjobname",
to: "${userId}"
}
I'm not so sure about how to output your userId using bat script (more familiar with shell script, sorry) but you get the idea...
Solved it by using the a jenkins plugin
readFile 'user_id.txt'
in groovy, you could acces environment variables like the following:
groovy -e "println System.env.LOGNAME"
so it might be possible (if USER_ID is an environment variable) that you could access the content of the variable like
to: System.env.USER_ID
but maybe in your jenkins env, the variable is already present?
to: env.USER_ID
?
Another possibility could be:
to: new File("user_id.txt").text.replace("\n", "")

Resources