How to access file from node inside Jenkins shared library script - jenkins

I am calling a shared library groovy script from my Jenkins pipeline.
Using the pwd() method I can properly get the workspace path and I can even see the required file in the exact same location in the Jenkins node.
Still I am getting following error:
java.io.FileNotFoundException: C:\Jenkins\workspace\Demo\test\target\site\xyz\abc.csv (No such file or directory)
I have the groovy-scripts/vars/generateHtml.groovy shared library which is being called from the pipeline as generateHtml(). The relevant code snippet:
def call() {
def ws = pwd()
echo "path ${ws}: generateHtml>start"
def targetPath = "${ws}\\target\\"
def resultFile = targetPath + 'site\\xyz\\abc.csv'
def data = parseCsv(new File(resultFile).getText('UTF-8'))
...

Reading a file in Jenkins Pipelines goes via readFile. Don't use plain groovy for I/O.

Related

Groovy: Unable to read a json file from jenkins workspace

I have to read some input from report.json file which is in the jenkins workspace. I am using the following code to read the file but it says file not found error. I am running this script on Groovy Postbuild step.
import hudson.model.*
def fileContents = new File('C:\\jenkinstest_slave\\workspace\\Cypress\\mochawesome-report\\report.json').readLines()
def result = fileContents.findAll { it.contains('passPercent') }
manager.listener.logger.println("matching word from findAll method= " +result)
Error:
Groovy script failed:
java.io.FileNotFoundException
Can someone please help me to resolve this?

Jenkins pipeline script to copy or move file to another destination

I am preparing a Jenkins pipeline script in Groovy language. I would like to move all files and folders to another location. As Groovy supports Java so I used below java code to perform the operation.
pipeline{
agent any
stages{
stage('Organise Files'){
steps{
script{
File sourceFolder = new File("C:\\My-Source");
File destinationFolder = new File("C:\\My-Destination");
File[] listOfFiles = sourceFolder.listFiles();
echo "Files Total: " + listOfFiles.length;
for (File file : listOfFiles) {
if (file.isFile()) {
echo file.getName()
Files.copy(Paths.get(file.path), Paths.get("C:\\My-Destination"));
}
}
}
}
}
}
}
This code throws the bellow exception:
groovy.lang.MissingPropertyException: No such property: Files for
class: WorkflowScript
I tried with below code too, but it's not working either.
FileUtils.copyFile(file.path, "C:\\My-Destination");
Finally, I did try with java I/O Stream to perform the operation and the code is bellow:
def srcStream = new File("C:\\My-Source\\**\\*").newDataInputStream()
def dstStream = new File("C:\\My-Destination").newDataOutputStream()
dstStream << srcStream
srcStream.close()
dstStream.close()
But it's not working either and throws the below exception:
java.io.FileNotFoundException: C:\My-Source (Access is denied)
Can anyone suggest me how to solve the problem and please also let me know how can I delete the files from the source location after copy or move it? One more thing, during the copy can I filter some folder and files using wildcard? Please also let me know that.
Don't execute these I/O functions using plain Java/Groovy. Even if you get this running, this will always be executed on the master and not the build agents. Use pipeline steps also for this, for example:
bat("xcopy C:\\My-Source C:\\My-Destination /O /X /E /H /K")
or using the File Operations Plugin
fileOperations([fileCopyOperation(
excludes: '',
flattenFiles: false,
includes: 'C:\\My-Source\\**',
targetLocation: "C:\\My-Destination"
)]).
I assume I didn't hit the very right syntax for Windows paths here in my examples, but I hope you get the point.

File operations in Jenkins Pipeline

I have a pipeline flow defined as:
node("linux_label") {
println("hostname".execute().txt)
def filename = "${WORKSPACE}/submoduleinfo.txt"
stage("Submodule info") {
def submoduleString = sh script: "git -C ${WORKSPACE} submodule status > ${filename}", returnStdout: true
}
String fileContents = new File("$filename}").text
operateOnFile(fileContents)
}
At "new File" I will get an error saying no such file exists. after some troublehshooting I see that the hostname printout will output the jenkins master and not the node "linux_label" where the workspace resides.
Is this how Piepeline should work, i.e. all code that is not part of stage/steps/etc are executed on the jenkins master and not on the wanted node?
What would be a good workaround where I do an operation in one stage and want to operate on the file in the node {} domain?
That is how pipeline works. You can use readFile to read file from a workspace. Since you are using just a content of the file for your processing, this will work.
From tutorial:
readFile step loads a text file from the workspace and returns its
content (do not try to use java.io.File methods — these will refer to
files on the master where Jenkins is running, not in the current
workspace).
In one of our use case, we added some additional functions using Shared pipeline library.
Try this:
if (env['NODE_NAME'].equals("master")) {
return new hudson.FilePath(path);
} else {
return new hudson.FilePath(Jenkins.getInstance().getComputer(env['NODE_NAME']).getChannel(), path);
}

find env variables for a all builds for a job on jenkins

I need to monitor what are the changes going with a job on jenkins(update the changes to a file). Need to list the env variables of a job. JOB_NAME,BUILD_NUMBER,BUILD_STATUS,GIT_URL for that build(all the builds of a job). I didn't find out a good example with the groovy. What is the best way to fetch all the info?
build.getEnvironment(listener) should get you what you need
Depending on what you would like to achieve there are at least several approaches to retrieve and save environment variables for:
current build
all past builds
Get environments variables for current build (from slave)
Execute Groovy script
// Get current environment variables and save as
// a file in $WORKSPACE.
new File(".",'env.txt').withWriter('utf-8') { writer ->
System.getenv().each { key, value ->
writer.writeLine("${key}:${value}")
}
}
Using Groovy Plug-in.
Get environment variables for current build (from master)
Execute system Groovy script
// Get current environment variables and save as
// a file in $WORKSPACE.
import hudson.FilePath
def path = "env-sys.txt"
def file = null
if (build.workspace.isRemote()) {
file = new FilePath(build.workspace.channel, build.workspace.toString() + "/" + path)
} else {
file = new FilePath(build.workspace.toString() + "/" + path)
}
def output = ""
build.getEnvironment(listener).each { key, value ->
output += "${key}:${value}\n"
}
file.write() << output
Using Groovy Plug-in.
Environment variables returned by Groovy scripts are kept in map. If you don't need all of them, you can access individual values using standard operators/methods.
Get environment variables for all past builds (from master)
This approach expecst that you have installed EnvInject Plug-in and have access to $JENKINS_HOME folder:
$ find . ${JENKINS_HOME}/jobs/[path-to-your-job] -name injectedEnvVars.txt
...
ps. I suspect that one could analyze EnvInject Plug-in API and find a way to extract this information directly from Java/Groovy code.
Using EnvInject Plug-in.
To look for only specific variables you can utilize find, grep and xargs tools .
You can use below script to get the Environment Variables
def thread = Thread.currentThread()
def build = thread.executable
// Get build parameters
def buildVariablesMap = build.buildVariables
// Get all environment variables for the build
def buildEnvVarsMap = build.envVars
String jobName = buildEnvVarsMap?.JOB_NAME // This is for JOB Name env variable.
Hope it helps!

How to write connection script between Grails and Hadoop?

I need to copy the files which are generated within Grails to Hadoop dynamically. How will I write code for this in Grails? Whenever a file is generated it should be copied into Hadoop. If the incoming file already exists, it should get updated in Hadoop.
I used shell script to connect grails and hadoop.
I had all the commands to run hadoop jobs in myjob.sh (Workflow Script)
And i added the code to execute shell script in my controller
def scriptCom="/folderlocation/shellscript.sh"
println "[[Running $scriptCom]]"
def proc = scriptCom.execute()
def oneMinute = 60000
proc.waitForOrKill(oneMinute)
if(proc.exitValue()!=0){
println "[[return code: ${proc.exitValue()}]]"
println "[[stderr: ${proc.err.text}]]"
return null
}else{
println "[[stdout:$revisionid]]"
return proc.in.text.readLines()
}

Resources