How to persist Properties in jenkins pipeline? - jenkins

In my jenkins pipeline I am working with properties stored in file.
I can read properties from file and add new items to the map using this code, but I do not understand how to persist my changes.
node('hozuki-best-girl') {
def propertiesPath = "${env.hozuki_properties}"
def props = readProperties file: propertiesPath
props['versionCode'] = 100500
}
What should I do in order to persist my changes? There is no writeProperties method here https://jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#code-readproperties-code-read-properties-from-files-in-the-workspace-or-text

you can use yaml format instead of properties.
it also simple and human readable and in jenkins-pipeline there are read and write operations for yaml
or you can use this kind of code:
#NonCPS
def propsToString(Map map){
return new StringWriter().with{w-> (map as Properties).store(w, null); w; }.toString()
}
writeFile file: propertiesPath, text: propsToString(props)

The Phoenix AutoTest Plugin has a writeProperties step.

Related

How to println from a txt file in jenkins

So I have a file called "text1.txt" that has only one line -
version.build=846
I want to do something like this-
def svntag = ccsmp_v_ {version.build}
println $svntag
ccsmp_v_846
Is there any way to do this ?
You can read a file from the workspace using the methods from pipeline utility steps plugin.
For your case it would be best to use readProperties method, for example:
def properties = readProperties file: '<your properties file in the workspace>'
Then you can access the value with:
def svntag = "ccsmp_v_${properties['version.build']}"

Jenkinsfile shared params in source control

I'm new to jenkins and inherited a bunch of declarative pipelines of unknown code quality. Each pipeline uses folder properties to set shared default param values. This puts essential variables outside of source control, which kills our PR process and our history for debugging. For example
//pipelineA/Jenkinsfile
pipeline {
parameters {
string name: 'important_variable', defaultValue: folderProperty('important_variable')
}
//etc
}
//pipelineB/Jenkinsfile
pipeline {
parameters {
string name: 'important_variable', defaultValue: folderProperty('important_variable')
}
//etc
}
Then in the root folder a property important_variable is set to "Hello World"
Is there a way to get this into source control either by setting the folder property to extract the variable from a yaml, or by using shared libraries?
Thank you for any help!
In case anyone reads this, we ended up:
Create a bootstrap.groovy file
This file MUST go in a /vars directory at the absolute top of your repo
Using the Jenkins UI we went to the pipeline's parent directory > config and created a shared library called config-lib that points at our repo and automatically exposes the bootstrap.groovy file methods as long as the file is in the right place
The bootstrap.groovy file has a call method that returns a map with key value pairs for our default parameters. This method has to be named call
In the Jenkinsfile for the pipeline we include the following two lines:
#Library("config-lib") _
config = bootstrap()
The library decorator (note it ends with _) imports the config-lib methods defined in the jenkins ui
The bootstrap function calls the call method from the bootstrap.groovy file in that config-lib library
in the Jenkinsfile use the config map to populate the param default values
pipeline {
parameters {
string name: 'foo', defaultValue: config.foo
}
And it's done.
This video helped immensely: https://youtu.be/Wj-weFEsTb0

Access managed files, local files and remote files ssh during Jenkins pre-build stages

I have a parametrized build and I'd like to populate parameter values based on contents of files/directories on the local slave and/or on a remote box accessible via ssh.
It's not a problem to access local and remote files during build stages, but I need to make it work in an Active Choice Plugin (or something similar).
Apparently, sh function doesn't work, but some Java-like Groovy API is still available (as described here: https://wiki.jenkins.io/display/JENKINS/Active+Choices+Plugin)
jenkinsURL=jenkins.model.Jenkins.instance.getRootUrl()
def propFile=vPropFile //name of properties file
def propKey=vPropKey // name of properties key
def relPropFileUrl=vRelPropFileUrl // userContent/properties/
def propAddress="${jenkinsURL}${relPropFileUrl}$propFile"
def props= new Properties()
props.load(new URL(propAddress).openStream())
def choices=[]
props.get(propKey.toString()).split(",").each{
choices.add(it)
}
return choices
I wonder if it's possible to access managed files the same way or better yet to access something remotely using SSH.
Is there an API for that?
I couldn't find a solution that would allow to SSH during during Active Choices parameter script execution.
However, I was able to use configuration file(s) managed by Jenkins. Here's the code that can be run from the Active Choices parameter script:
def gcf = org.jenkinsci.plugins.configfiles.GlobalConfigFiles.get()
// Read different file based on referencedParameter ENVIRONMENT
def deploymentFileName = 'deployment.' + ENVIRONMENT + '.properties'
def deploymentFile = gcf.getById(deploymentFileName)
def deploymentProperties = new Properties();
deploymentProperties.load(new java.io.StringReader(deploymentFile.content))
def choices = []
// Make use of Properties object here to return list of choices
return choices
Later in the main Groovy Script of the pipeline it's possible to update file the same way, but the file has to be read/loaded again as the script context is different:
def gcf = org.jenkinsci.plugins.configfiles.GlobalConfigFiles.get()
def deploymentFile = gcf.getById(deploymentFileName)
def deploymentProperties.load(new java.io.StringReader(deploymentFile.content))
// Update deploymentProperties as necessary here.
def stringWriter = new java.io.StringWriter()
deploymentProperties.store(stringWriter, "comments")
// Content of the deploymentFile object is immutable.
// So need to create new instance and reuse the same file id to overwrite the file.
def newDeploymentFile = deploymentFile.getDescriptor().newConfig(
deploymentFile.id, deploymentFile.name, deploymentFile.comment, stringWriter.toString())
gcf.save(newDeploymentFile)
Of course, all necessary API permissions have to be granted in Jenkins.

Need help to read a json file using groovy and Jenkins

I am facing some issues reading a JSON file.
I am using Jenkins Active Choice Parameter to read value from a JSON file via groovy script. This is how my JSON file look.
{
"smoke": "Test1.js",
"default": "Test2.js"
}
I want my groovy script to print out smoke and default. Below is what my groovy code look like.
import groovy.json.JsonSlurper
def inputFile = new File(".\TestSuitesJ.json")
def InputJSON = new JsonSlurper().parseText(inputFile)
InputJson.each
{
return[
key
]
}
Above code is not working for me. Can someone please suggest a better groovy way?
Anyone in similar situation as me trying to import a JSON file at runtime. I used Active Choice parameter to solve my problem. There is an option to write groovy script in Active Choice Parameter plugin of Jenkins. There i have written below code to import a JSON file to achieve desired results.
import groovy.json.JsonSlurper
def inputFile = new File('.//TestSuitesJ.json')
def inputJSON = new JsonSlurper().parse(inputFile)
def keys = inputJSON.keySet() as List
Thanks #sensei to help me learn groovy.
You really should read the groovy dev kit page, and this in particular.
Because in your case parseText() returns a LazyMap instance, the it variable you're getting in your each closure represents a Map.Entry instance. So you could println it.key to get what you want.
A more groovy way would be:
inputJson.each { k, v ->
println k
}
In which case groovy passes your closure the key (k) and the value (v) for every element in the map.

Custom changelog in Jenkins Pipelines

I was wondering if it is possible to have a custom changelog appear for Jenkins Pipelines. Ideally, I'd like to propagate the downstream changelogs, but failing that I've tried to create a custom changelog derived from the downstream builds. However, it doesn't appear to work (with no option for viewing the pipeline's workspace either).
I was wondering if this is something that I'm just getting wrong or whether it's actually supported or not.
This is the sample code I'm testing with
node('master')
{
stage('Source')
{
build 'SourceBuild'
def rootDir = currentBuild.rawBuild.getRootDir().toString()
echo rootDir
def changelog = new File(rootDir, "changelog.xml")
PrintWriter writer = new PrintWriter(new FileWriter(changelog));
writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
writer.println("<changelog>");
writer.println(String.format("\t\t<user>%s</user>", 'User'));
writer.println(String.format("\t\t<comment>Change</comment>", 'Comment'));
writer.println("\t</changeset>");
writer.println("</changelog>");
writer.close();
}
}
Many thanks
In Jenkins pipeline, I noticed that there is a global variable named currentBuild. It has a readable property called changeSets. I would rather take this approach with pipeline instead of playing around with changelog.xml
stage('some name') {
def gitChangeSetList = currentBuild.changeSets
formatGitChangeLog(gitChangeSetList)
}
def formatGitChangeLog(GitChangeSetList changeSetList) {
def formatStr = ""
for (setItem in changeSetList) {
for (change in setItem.getLogs()) {
formatStr += "${change.getAuthor().getDisplayName()}: ${change.getMsg()}\n"
}
}
return formatStr
}
currentBuild.changeSets is of type GitChangeSetList. From the javadoc, we can derive various methods involved in GitChangeSet.

Resources