Retrieve all properties of env in Jenkinsfile - groovy

I would like to print all available properties (and their values) in env object inside Jenkinsfile.
When I do
print env
I get:
org.jenkinsci.plugins.workflow.cps.EnvActionImpl#112cebc2
So it looks like toString is not implemented there, how can I access properties that are in this object if I don't know their names?

Make sure you're not running the pipeline script in sandboxed mode and you should be able to use:
env.getEnvironment()
Note, if you're running in sandbox mode in a pipeline, you should approve the method at the script approval page: http://jenkins-host/scriptApproval/

To retrieve all env properties using a Jenkinsfile written in either declarative or scripted DSL you can use:
sh 'env'
or
sh 'printenv'

As said over here: https://stackoverflow.com/a/42138466/618253
The declarative pipeline way of doing things:
node {
echo sh(returnStdout: true, script: 'env')
}

Related

Return a value from node.js script in azure pipeline?

In Azure Pipelines, I see that you can access the environment variables from scripts in node.js during a pipeline run. However, I want to actually return a value and then capture/use it.
Does anyone know how to do this? I can't find any references on how to do this in documentation.
For consistency's sake it'd be nice to use node scripts for everything and not go back and forth between node and bash.
Thanks
Okay I finally figured this out. Azure documentation is a bit confusing on the topic, but my approach was what follows. In this example, I'm going to make a rather pointless simple script that sets a variable whose value is the name of the source branch, but all lower case.
1) Define your variable
Defining a variable can be done simply (though there is a lot of depth to how variables are used and I suggest consulting Azure documentation on variable creation for more). However, at the top of your pipeline yaml file you can define it as such:
variables
lowerCaseBranchName: ''
This creates an empty variable for use across your jobs. We'll use this variable as our example.
2) Create your script
"Returning a value" from your script simply means outputting it via node's stdout, the output of which will be consumed by the task to set it as a pipeline variable.
An important thing to remember is that any environment variables from the pipeline can be used within node, they are just reformatted and moved under node's process.env global. For instance, the commonly used Build.SourceBranchName environment variable in azure pipelines is accessible in your node script via its alias process.env.BUILD_SOURCEBRANCHNAME. This uppercase name transformation should be uniform across all environment variables.
Here's an example node.js script:
const lowerCaseBranchName = process.env.BUILD_SOURCEBRANCHNAME.toLowerCase();
process.stdout.write(lowerCaseBranchName);
3) Consume the output in the relevant step in azure pipelines
To employ that script in a job step, call it with a script task. Remember that a script task is, in this case, a bash script (though you can use others) that runs node as a command as it sets the value of our variable:
- script: |
echo "##vso[task.setvariable variable=lowerCaseBranchName]$(node path/to/your/script)"
displayName: 'Get lower case branch name'
Breaking down the syntax
Using variable definition syntax is, in my opinion extremely ugly, but pretty easy to use once you understand it. The basic syntax for setting a variable in a script is the following:
##vso[task.setvariable variable=SOME_VARIABLE_NAME]SOME_VARIABLE_VALUE
Above, SOME_VARIABLE_NAME is the name of our variable (lowerCaseBranchName) as defined in our azure pipeline configuration at the beginning. Likewise, SOME_VARIABLE_VALUE is the value we want to set that variable to.
You could do an additional line above this line to create a variable independently that you can then use to set the env variable with, however I chose to just inline the script call as you can see in the example above usign the $() syntax.
That's it. In following tasks, the environment variable lowerCaseBranchName can be utilized using any of the variable syntaxes such as $(lowerCaseBranchName),
Final result
Defining our variable in our yaml file:
variables
lowerCaseBranchName: ''
Our nodejs script:
const lowerCaseBranchName = process.env.BUILD_SOURCEBRANCHNAME.toLowerCase();
process.stdout.write(lowerCaseBranchName);
Our pipeline task implementation/execution of said script:
- script: |
echo "##vso[task.setvariable variable=lowerCaseBranchName]$(node path/to/your/script)"
displayName: 'Get lower case branch name'
A following task using its output:
- script: |
echo "$(lowerCaseBranchName)"
displayName: 'Output lower case branch name'
This will print the lower-cased branch name to the pipline console when it runs.
Hope this helps somebody! Happy devops-ing!

How can I combine expressions and predefined variables to get my build repository name as an uppercase string?

I'm trying to get my build repository name as an uppercase string combining predefine variables and expressions on Azure Devops as follows:
variables:
repoNameUpper: $[upper(variables['Build.Repository.Name'])]
- script: |
echo $(repoNameUpper)
Yet I get no output from it, what am I doing wrong here?
Yes, I know I could set a variable to achieve what I need using a bash script, yet I think it would not be so cool.
It because the Build.Repository.Name is agent-scoped, and can be used as an environment variable in a script and as a parameter in a build task. in another words - is not known at plan compile time, only at job execution time.
You can find more info in this GitHub issue.

Accessing credentialId in git step of Jenkins workflow using variable

I am trying to supply a parameter as the credentialId under the git step of my workflow. I define the following variables as environment variables in my job folder:
stashProject=ssh://git#stash.finra.org:7999/rpt
gitProdCredential=289b9074-c29a-463d-a793-6e926174066c
I have the following lines my inline Groovy CPS DSL workflow script:
sh 'echo retrieving code using credential: ${gitProdCredential}'
git url: '${stashProject}/etl.git', credentialsId: '${gitProdCredential}', branch: 'feature/workflow'
You can see that the variables are being evaluated properly as the gitProdCredential is echo'd and the git retrieval does attempt to get from my correct URL, based on the following output:
retrieving code using credential: 289b9074-c29a-463d-a793-6e926174066c
hudson.plugins.git.GitException: Failed to fetch from ssh://git#stash.finra.org:7999/rpt/etl.git
stderr: Permission denied (publickey).
But you can also see it is not authenticating properly. If, however, I hardcode the gitProdCredential like so
git url:'${stashProject}/etl', credentialId: '289b9074-c29a-463d-a793-6e926174066c', branch: 'feature/workflow'
It runs just fine and clones my repo. So somehow the credentialId variable isn't being evaluated correctly in the git DSL function properly, even though it appears to be in the rest of the workflow. Please advise if I'm missing something.
This is mainly a Groovy issue.
'${gitProdCredential}'
is a literal string with the text ${gitProdCredential}. Probably you meant
"${gitProdCredential}"
or more simply just
gitProdCredential
since there is no point creating a string expression which interpolates a (String-valued) expression and includes nothing else. In this case however the variable is not a Groovy variable but an environment variable, so you needed to use
env.gitProdCredential
You were probably misled by the fact that
sh 'echo retrieving code using credential: ${gitProdCredential}'
works. But this works only because it is running a Bourne shell script
echo retrieving code using credential: ${gitProdCredential}
and this shell happens to allow environment variables to be expanded using a syntax similar to that which Groovy uses in GString.
As to the incidental expansion of '${stashProject}/etl.git', this is apparently happening in the Git plugin, and is arguably a bug (values passed from a Workflow script should be used as is): some Jenkins plugins expand environment variables in configuration inputs, again using a syntax similar to that used by Groovy.
In summary, what you meant to write was
git url: "${env.stashProject}/etl.git", credentialsId: env.gitProdCredential, branch: 'feature/workflow'
By the way, when using sufficiently new versions of the Credentials plugin, when creating a new credentials item (but not thereafter) you can click the Advanced button to specify a mnemonic ID, which makes working with scripted projects like Workflow more pleasant.

Jenkins + Build Flow, how to pass a variable from one job to another

I have a build flow scenario similar to the documentation example: two jobs, one running after the other.
b = build("job1")
build("job2", param1: b.????)
My job1 is a shell script that builds a package out of a checked out git repositoy and prints out the version of the built package.
I need to extract the version from job1 (parse output??) and make it available somehow as a parameter to job2. How can this be achieved? Please note that I can't know the version before running job1.
The problem with simply using export in a shell script build step is that the exported variables disappear when the shell script exits, they are not propagated up to the job.
Use the EnvInject plugin to create environment variables in your build. If you
write out a properties file as part of your build, EnvInject can read the file and inject variables as a build step. A properties file has a simple KEY=VALUE format:
MY_BUILD_VERSION=some_parsed_value
Once you have an environment variable set in your job, in the Build Flow
plugin, you can extract the variable's value and use it in subsequent jobs:
def version = build.environment.get( "MY_BUILD_VERSION" )
out.println String.format("Parameters: version: %s", version)
build( "My Second Build", MY_BUILD_VERSION: version )
When you run job1 export the version with name as system property.
export appVersion="stringOfVersion-123"
Then it depend if you know how long is version (count of numbers or others characters). If you know it you can parse variable from end in second build as new variable and use it.
How parse string you can find in this question with nice examples.
If job2 always should get some information from job1 you could use approach without parameters. job1 could publish artifact with version and job2 will use that artifact (with Copy Artifact Plugin for example). With that approach job2 could be executed also as standalone job.
For anyone else coming upon this, another solution is to use a scriptler script, where you pass in the .properties file path, and the script will add the properties to the list of job variables:
Properties properties = new Properties()
FilePath workspace = build.getWorkspace()
FilePath sourceFile = workspace.child(path)
properties.load(sourceFile.read())
properties.each { key, value ->
key = key.replace(".", "_").toUpperCase()
Job.setVariable(build, key, value)
println "Created Variable: " + key + "=" + value
}
This will convert any periods to underscores, and capitalize all letters. Using a scriptler script ensures that you have a method that works independent of the "plugin soup" you are using.

How to get specific information about the current build project in Jenkins with Groovy?

In Jenkins/Hudson, with the help of a Postbuild Groovy script, I would like to get one of the following:
an environment variable (e.g. current JOB_NAME, BUILD_NUMBER etc.)
the result of a specific build number of the current project
the build number of the last not successful build in the current project
At the moment I only found the following way, but it's rather limited:
def item = hudson.model.Hudson.instance.getItem("GroovyMultipleFailTest")
def build = item.getLastBuild()
build.getNumber()
Using Jenkins v2.17 this works for me:
echo "BUILD_NUMBER=${env.BUILD_NUMBER}"
${manager.build.getEnvironment(manager.listener)['BUILD_NUMBER'] }
Bo Persson had the best answer, but was a little short.
To access the environment variables from the build in the Groovy Postbuild, you can grab them from the build. This sample code is useful for dumping all of the BUILD's environment variables to the console:
manager.build.getEnvironment(manager.listener).each {
manager.listener.logger.println(it);
}
If you're using Groovy script within "Env Inject", you can get current build and current job by:
currentJob.getName()
currentBuild.toString()
an environment variable (e.g. current JOB_NAME, BUILD_NUMBER etc.)
String jobName = System.getenv('JOB_NAME')
The only way I got it to work for me was with build.properties.environment.BUILD_NUMBER
I tried various approaches in this article and others, and it looks like the only one put below and also build.properties.environment.BUILD_NUMBER (upvoted) are working for me in Jenkins Execute system Groovy Script build step groovy command type
EnvVars envVars = build.getEnvironment(listener)
def n = envVars.get('BUILD_NUMBER')

Resources