setting variable in jenkinsfile from git log command - jenkins-pipeline

I need to run following command in my jenkinsfile
steps
{
echo "Get source branch name in pull request"
script {
Def sourceBranchString= bat "git log --name-status HEAD^..HEAD | findstr 'from'"
echo ${sourceBranchString}
def sourceBranch = powershell "bin\\DeploymentUtils\\ReadPullRequestSourceBranch.ps1 ${sourceBranchString}"
echo $sourceBranch
}
}
First i need to set the variable sourceBranchString with the outputput from
bat "git log --name-status HEAD^..HEAD | findstr 'from'"
It seems to ignore the ^ in the git command, i have tried to escape it with \ but then it fails.
Then i want to call my powershell script with the sourceBranchString variable as
input parameter.
It errors out in the pipeline without any error message. I think im not getting the git command executed.
And im not shure i am using the right syntax for initialize the variable.
Can anybody help

Related

Jenkins groovy scripted pipeline variables not substituting correctly

I'm running a very simple pipeline to create maven projects, the pipeline is to run a single maven install command.
The trouble is substituting variables into the one-liner. I've tried various different things but stuck in a strange place. Take example pipeline below:
node {
stage('Set Vars') {
GIT_HASH = sh (script: "git log -n 1 --pretty=format:'%H'" , returnStdout: true)
echo "git hash is >>>>>>>> $GIT_HASH"
BUILD_NUM="${env.BUILD_NUMBER}"
echo "build no is >>>>>>>> ${BUILD_NUM}"
}
stage('Build Project') {
sh "mvn clean install -PrunInstallPackage -Duser=admin -Dpass=guessing -Dip=200.0.0.1 -Dport=4444 -Dhash=${GIT_HASH} -Dbuildnumber=${BUILD_NUM}"
}
}
I would expect to see the variables substitued in the mvn install command, this does not seem to work this way though.
This build results in:
sh "mvn clean install -PrunInstallPackage -Duser=admin -Dpass=guessing -Dip=200.0.0.1 -Dport=4444 -Dhash=${GIT_HASH}
Both echo commands print out correct output.
Why does the last command get cut off after the first variable substitution?
Also, for some unknown reason, I cannot substitute -Dbuildnumber=${env.BUILD_NUMBER}" directly into the maven command. Seems like something that a user should be able to do. What am I missing here?
Many thanks in advance
I am trying to remember how I solved same issues in the past..
Problem 1
You are using the GIT_HASH variable across two stages, so you have to declare it global to share it across them:
// Global variables declaration
GIT_HASH = null
// Pipeline code
node {
stage('Set Vars') {
GIT_HASH = sh (script: "git log -n 1 --pretty=format:'%H'" , returnStdout: true)
echo "git hash is >>>>>>>> $GIT_HASH"
BUILD_NUM="${env.BUILD_NUMBER}"
echo "build no is >>>>>>>> ${BUILD_NUM}"
}
stage('Build Project') {
sh "mvn clean install -PrunInstallPackage -Duser=admin -Dpass=guessing -Dip=200.0.0.1 -Dport=4444 -Dhash=${GIT_HASH} -Dbuildnumber=${BUILD_NUM}"
}
}
Problem 2
env.BUILD_NUMBER is a Groovy statement, instead mvn gets executed inside a shell instance by the sh command.
For that reason I suggest you to use the BUILD_NUM variable way.

git produces no output when called from script via cron (log/shortlog)

I've got a script git-test going to a local git repo and calling git shortlog to keep track of recent changes. For testing purposes, I just used these lines:
#!/bin/bash
cd /myrepo.git
result="$(/usr/bin/git shortlog -3)"
echo "$(date):$result" >> /tmp/git-log
the crontab entry is
* * * * * /home/username/git-test >> /tmp/cron-output 2>&1
After all the script IS WORKING called from console and IS WORKING from cron with doing a simple ls -lh instead of the git command. But it IS NOT WORKING called from cron with the git command. So the problem must be git.
I tried:
calling script from terminal -> doing fine, getting git short logs
calling script from cron, like above -> no git output in /tmp/git-log and no errors in /tmp/cron-output
calling script from cron, but doing a $(ls -lh)" instead of $(/usr/bin git shortlog -3) -> doing fine
calling script from cron, writing to a file directly with git shortlog -3 >> /tmp/git-log -> no git output in /tmp/git-log and no errors in /tmp/cron-output
putting the git cd /myrepo.git;git shortlog -3 >> /tmp/cron-output 2>&1 directly in crontab -> no output and no errors in /tmp/cron-output
Any Ideas what the problem might be?
Thank you!
git shortlog has a weird "feature". It is documented, right up front in the manual page, but the "feature" is so surprising that it is often missed:
If no revisions are passed on the command line and either standard
input is not a terminal or there is no current branch, git shortlog
will output a summary of the log read from standard input, without
reference to the current repository.
Your run from crontab has stdin redirected to a file (well, to /dev/null, but "not a terminal") so you hit this feature: git shortlog reads the log from stdin, and that's empty, so its output is empty.
The cure is to feed it the appropriate git log --pretty=short output, as seen in the SYNOPSIS line in the documentation.
(Why the "feature"? I have no idea. I don't understand this behavior at all.)

Jenkinsfile and BASH shell code - Why some comments lines are honored and some are ignored and giving errors

Jenkins version: 2.164.3
I have my Jenkinsfile and in one of the stage, I'm calling the following code but it gives me an error.
I don't see why it's giving me an error when syntax wise, it looks ok.
Jenkinsfile code snapshot:
stages {
stage("Checkout Dependent Code") {
steps {
sh '''
set +x
echo -e "\n-- Checking out dependent code:"
echo -e "\n-- Cloning Common Code.\n"
git clone -b ${COMMON_REPO_BRANCH} ${SSH_GIT_URL}/project/common_utilities.git
## Comment 1. Old repo
echo -e "\n-- Cloning Exporter Tool\n"
git clone -b ${TOOL_REPO_BRANCH} ${SSH_GIT_URL}/project/jira-exporter.git
## Comment 2. New - 3 new repos. Comment the code for now.
#echo -e "\n-- Cloning Some Exporter Tool Repos\n"
#for r in core client extractor;
#do
# echo -e "\n -- Cloning: ${r}"
# git clone -b ${TOOL_REPO_BRANCH} ${SSH_GIT_URL}/project/${r}.git
# echo
#done
echo -e "\n\n`echo -en "\n-- Current Directory: "; pwd; echo; ls -l`\n\n"
'''
}
}
}
The error message that I'm getting is:
10:38:38 -- Checking out dependent code:
10:38:38
10:38:38 -- Cloning Common Code.
10:38:38
10:38:38 Cloning into 'common_utilities'...
10:38:39
10:38:39 -- Cloning Exporter Tool
10:38:39
10:38:39 Cloning into 'jira-exporter'...
10:38:39 /jenkins_workspaces/workspace/development/project/my_jenkins_job/251#tmp/durable-f88d4c2a/script.sh: line 21: --: command not found
Question:
The first comment (Comment 1 line) in the shell script logic, is honored by Jenkinsfile and no syntax issue there and we can see the output the following echo and git command works (I can see in my workspace, git repository has been cloned successfully).
Starting 2nd comment Comment 2. line onwards, the next few lines are all commented out in Shell logic but script fails for a line (which is commented out) somewhere before the last echo line where I'm printing Current Directory: .. line and this last echo line is not printed at all (as error happened before reaching this last echo line. If all lines before this last echo line were commented, then why did I get an error. Running the shell code (from a file) works fine on the machine.
So after some digging, I found this:
The problem is \n and how it's treated in Groovy and Shell code.
In Jenkinsfile (Groovy) code, when it reads the code for the above mentioned
stage (in the post), it says, oh I got this SHELL sh ''' .... ''' code and I'll go parse this in my own fancy Groovy world and create a dynamic temporary shell script (aka ..#tmp/durable-f88d4c2a/script.sh).
First Groovy comes in (due to Jenkinsfile written in Groovy) and breaks all statements wrapped in sh ''' ... ''' code into a new line and then, Jenkins creates a dynamic .sh Shell script (to do the work).
This works if a command which was using \n was NOT commented out, but doesn't work if the command using \n was ACUTUALLY COMMENTED out.
To investigate the issue, I added the following line inside sh ''' ... ''' section after set +x line.
I added cat -n $0 (just after set +x line, to print the whole shell dynamic temp .sh script) and to see HOW Jenkinsfile Groovy logic actually parsed this visual looking sh ''' ... ''' code in my Jenkinsfile ---> into a true Shell .sh script before executing it.
I found that, it treated/broke/parsed sh ''' ... ''' section; for example, a line like:
echo -e "\n-- Cloning Exporter Tool\n" into the following code lines (in the dynamically created .sh script, created by Jenkins):
echo -e " on a line in that dynamic temprarory .sh script
then
-- Cloning Exporter Tool in another line, then
" in another line.
Now, the above code works fine as " double quotes are maintained and -- actually has a valid echo command which uses this -- characters to print on console output.
When the line was:
#echo -e "\n-- Cloning Exporter Tool\n" into the following code:
Groovy parsed it into a dynamic temp .sh file as:
#echo -e " on a line in that dynamic temprarory .sh script
then
-- Cloning Exporter Tool in another line, then
" in another line.
and here it barfs as expected (as per shell logic) and there's no COMMAND (wrapper like echo as it's commented out) for -- ... to work. Thus, we got -- command not found
10:38:38 19 ## Comment 2. New - 3 new repos. Comment the code for now.
10:38:38 20 #echo -e "
10:38:38 21 -- Cloning Some Exporter Tool Repos
10:38:38 22 "
Zeeesus!
Conclusion: You must use \n carefully in sh ''' ... ''' section of Jenkinsfile, either for comments or real code lines otherwise, you'll see <some character/word> command not found error. Or, better call the above code lines via a script available in some version control tool (GIT) (rather than putting all those code lines in Jenkinsfile itself).
I'm not sure what the exact issue, but try rewriting the script using more well-defined commands like printf.
stages {
stage("Checkout Dependent Code") {
steps {
sh '''
set +x
printf '\n-- Checking out dependent code:\n'
printf '\n-- Cloning Common Code.\n\n'
git clone -b "${COMMON_REPO_BRANCH}" ${SSH_GIT_URL}/project/common_utilities.git
## Comment 1. Old repo
printf '\n-- Cloning Exporter Tool\n'
git clone -b "${TOOL_REPO_BRANCH}" "${SSH_GIT_URL}/project/jira-exporter.git"
## Comment 2. New - 3 new repos. Comment the code for now.
#echo -e "\n-- Cloning Some Exporter Tool Repos\n"
#for r in core client extractor;
#do
# echo -e "\n -- Cloning: ${r}"
# git clone -b ${TOOL_REPO_BRANCH} ${SSH_GIT_URL}/project/${r}.git
# echo
#done
printf '\n\n\n-- Current Directory '
pwd
printf '\n'
ls -l
printf '\n\n'
'''
}
}
}

Getting Error while Passing variables extracted from shell in Jenkinsfile

I am setting up Jenkins pipeline, but getting an error while Passing variables extracted from the shell in the environment
pipeline {
agent any
environment {
PHP_CHANGE_SET = sh (script: "git diff-tree --no-commit-id --name-only -r HEAD | grep '.php'",returnStdout: true).trim()
}
I am getting mentioned ERROR
[Pipeline] { (Declarative: Post Actions)
[Pipeline] sh
Required context class hudson.FilePath is missing
Perhaps you forgot to surround the code with a step that provides this, such as: node
Error when executing failure post condition:
org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: Required context class hudson.FilePath is missing
at org.jenkinsci.plugins.workflow.steps.StepDescriptor.checkContextAvailability(StepDescriptor.java:260)
at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:262)
at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:178)
at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
I need PHP files name only which are in commit and store in variable
As mentioned in the comment, you cannot use it outside node block. If you really need to do this and this is the first thing you want for your job(A), what you can do is make another job (B) and there run this command in the directory you want and then trigger this job(A). You can have "PHP_CHANGE_SET" as a parameter which you can pass from job B.

Don't execute SVN "post commit hook" when a specific file is committed

Is there any way to not to run "post commit hook" or skip "post commit hook statement" when a specific file is committed?
This worked for me:
"C:\Program Files\VisualSVN Server\bin\svnlook" changed C:\Repositories\sbm2| findstr version.json && EXIT /B
#here my main part of post-commit-hook will begin
Thanks #uzsolt
You can use a test in your post-commit script. The svnlook changed repository_directory will show which files changed - can use grep or similar.
For example:
#!/bin/sh
/usr/bin/svnlook changed /svn/repo | grep -w ' yourfile$' && exit 0
# here begin the main part of your (original) hook

Resources