I have defined a var at the beginning of the pipeline and I try to change its value inside a stage but get the following error:
/home/jenkins/agent/workspace/eon-Docker-Build-Multibranch_dev#tmp/durable-d2c76925/script.sh: line 1: syntax error: bad substitution
my pipeline look something like this:
def FRONTEND_STATUS = "fail"
pipeline {
stage{
steps{
script {
FRONTEND_STATUS = 'success'
}
tried many syntax options but nothing works.
Related
I have a Jenkins declarative pipeline wherein I am trying to store the value returned from a method into environment variable as shown below.
steps {
script {
def job = getJob(JOB_NAME)
def param = getParam(job, "Ser")
echo param.getValue()
}
}
environment {
p_values = param.getValue()
}
But while running above script I am getting below error.
java.lang.IllegalArgumentException: One or more variables have some issues with their values: p_values
Could you please assist me here to resolve this issue?
I think the environment block will be executed prior to the script block.
You can try assign value to an new environment variable within script block, rather then in environment block as following:
script {
def job = getJob(JOB_NAME)
def param = getParam(job, "Ser")
echo param.getValue()
env.p_values = param.getValue()
}
Need help in getting the job status.
I tried the below code, but it is throwing
WorkflowScript: 9: Expected a step # line 9, column 1. def Status = build job: 'Job Regression'
Sample Script:
Pipeline{
agent
stages {
stage('Stg1') {
steps{
Script{
def Status = build job: 'Job Regression'
int build1=0
while(build1==0){
def BStatus = build job: 'JobB', propagate: false
if(BStatus == 'Success'){
build1=0
}```
Thanks in Advance
A few things here.
Perhaps it got lost in the formatting, but please indent your code properly - it will help you, and others, immensely in the future.
Jenkins DSL syntax almost always uses camelCase, and you haven't named some things properly. So your pipeline won't parse correctly the way you've entered it here.
Pipeline must be pipeline
Script must be script
The agent declarative requires an argument. agent any works in most cases, or you can specify labels or types, eg agent { label 'Windows' }
Also maybe lost in formatting, but you must close your braces.
When I fixed these minor issues, it looked like this, and passed validation using the VSCode Jenkins validator:
pipeline{
agent any
stages {
stage('Stg1') {
steps{
script{
def Status = build job: 'Job Regression'
int build1=0
while(build1==0){
def BStatus = build job: 'JobB', propagate: false
if(BStatus == 'Success'){
build1=0
}
}
}
}
}
}
}
Without knowing more about the problem you're coding for, it's hard to say if your actual script here is a good solution or not. What exactly are you trying to do? On the surface, it seems like it could go on forever? You might want to put a timeout on it.
A good place to start looking at your options is https://www.jenkins.io/doc/book/pipeline/syntax/ - the whole "book" is worth a read.
When i load another groovy file in Jenkinsfile it show me following error.
"Required context class hudson.FilePath is missing
Perhaps you forgot to surround the code with a step that provides this, such as: node"
I made a groovy file which contains a function and i want to call it in my Declarative Jenkinsfile. but it shows an error.
My Jenkinsfile--->
def myfun = load 'testfun.groovy'
pipeline{
agent any
environment{
REPO_PATH='/home/manish/Desktop'
APP_NAME='test'
}
stages{
stage('calling function'){
steps{
script{
myfun('${REPO_PATH}','${APP_NAME}')
}
}
}
}
}
Result--
org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: Required context class hudson.FilePath is missing
Perhaps you forgot to surround the code with a step that provides this, such as: node
Suggest me what is the right way to do it.
You either need to use a scripted pipeline and put "load" instruction inside the node section (see this question) or if you are already using a declarative pipeline (which seems to be the case), you can include it in "environment" section:
environment {
REPO_PATH='/home/manish/Desktop'
APP_NAME='test'
MY_FUN = load 'testfun.groovy'
}
We have to wrap with node {}, so that jenkins executors will execute on node, Incase if we would like to execute on any specific agent node, we can mention like node('agent name'){}
example here :
node {
def myfun = load 'testfun.groovy'
pipeline{
agent any
environment{
REPO_PATH='/home/manish/Desktop'
APP_NAME='test'
}
stages{
stage('calling function'){
steps{
script{
myfun('${REPO_PATH}','${APP_NAME}')
}
}
}
}
}
}
Loading the function in an initial script block inside the pipeline worked for me. Something like below:
def myfun
pipeline {
agent any
environment {
REPO_PATH='/home/manish/Desktop'
APP_NAME='test'
}
stages {
stage('load function') {
steps {
script {
myfun = load 'testfun.groovy'
}
}
}
stage('calling function') {
steps {
script {
myfun("${REPO_PATH}","${APP_NAME}")
}
}
}
}
}
I got this error message when I was calling a sh script that does not not exist in the repository / file system. Please look in the stack trace the following line:
at WorkflowScript.run(WorkflowScript:135)
The 135 marks the line in Jenkinsfile, on which the missing script or error is happening.
Another possibility is that due to earlier/underlying errors, the context has been removed for example by multiple executor machines. This happens if you are missing the node (e.g. script) -block, but especially at the post always -block. You can use the if -check also in other places. After this you get another error, that was causing this error message.
post {
always {
script {
//skip the step if context is missing
if (getContext(hudson.FilePath)) {
echo "It works"
}
}
}
}
See https://docs.cloudbees.com/docs/cloudbees-ci-kb/latest/troubleshooting-guides/how-to-troubleshoot-hudson-filepath-is-missing-in-pipeline-run
I would like to be able to wrap a 'stage' in Jenkins, so I can execute custom code at the start and end of a stage, so something like:
myStage('foo') {
}
I thought I could do this by using metaClass:
//Wrap stages to automatically trace
def originalMethod = this.metaClass.getMetaMethod("stage", null)
this.metaClass.myStage = { args ->
println "Beginning of stage"
println "Args: " + args
def result = originalMethod.invoke(delegate, args)
println "End of stage"
return result
}
But it appears the Groovy script itself is a Binding, which doesn't have a metaClass:
groovy.lang.MissingPropertyException: No such property: metaClass for class: groovy.lang.Binding
I'm still learning how Groovy and Jenkins Pipeline work, so perhaps I'm just missing something.
I am not familiar with the metaclass concept but I think that a simple solution to your problem is to define a wrapped stage as a function.
Here's an example of how you'd define such a function:
def wrappedStage(name, Closure closure) {
stage(name) {
echo "Beginning of stage"
def result = closure.call()
echo "End of stage"
return result
}
}
and this is how you would call it:
wrappedStage('myStage') {
echo 'hi'
}
The return value of wrappedStage would only make sense when the body of your stage actually returns something, for example:
If you call another job, eg:
wrappedStage('myStage') {
build job: 'myJob'
}
you will get back org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper which you can use to access info of the job you run, like result, variables etc
If you print something to the console, eg:
wrappedStage('myStage') {
echo 'hi'
}
you will get back null.
Note that in my example I am not printing args because the way I understand stage, it only takes 2 arguments; the stage name and the closure it should run. The name of the stage will already be printed in the log, and I don't know how much value you'd get from printing the code you're about to execute but if that's something you want to do, take a look at this.
If you have a more specific case in mind for what you'd want to wrap, you can add more params to the wrapper and print all the information you want through those extra parameters.
I have a Jenkinsfile in Groovy for a declarative pipeline and two created Jenkins variables with names OCP_TOKEN_VALUE_ONE and OCP_TOKEN_VALUE_TWO and the corresponding values. The problem comes when I try to pass a method variable and use it in an sh command.
I have the next code:
private def deployToOpenShift(projectProps, environment, openshiftNamespaceGroupToken) {
sh """/opt/ose/oc login ${OCP_URL} --token=${openshiftNamespaceGroupToken} --namespace=${projectProps.namespace}-${environment}"""
}
The problem is, the method deployToOpenShift has in the openshiftNamespaceGroupToken variable, a value that is the name of variable that has been set in Jenkins. It needs to be dynamic and the problem is that Jenkins don't resolve the Jenkins variable value, just the one passed as String, I mean, the result is:
--token=OCP_TOKEN_VALUE_ONE
If I put in the code
private def deployToOpenShift(projectProps, environment, openshiftNamespaceGroupToken) {
sh """/opt/ose/oc login ${OCP_URL} --token=${OCP_TOKEN_VALUE_ONE} --namespace=${projectProps.namespace}-${environment}"""
}
works perfect but is not dynamic that is the point of the method variable. I have tried with the """ stuff as you can see, but not working.
Any extra idea?
Edited with the code that calls the method:
...
projectProps = readProperties file: './gradle.properties'
openShiftTokenByGroup = 'OCP_TOKEN_' + projectProps.namespace.toUpperCase()
...
stage ('Deploy-Dev') {
agent any
steps {
milestone ordinal : 10, label: "Deploy-Dev Milestone"
deployToOpenShift(projectProps, 'dev', openShiftTokenByGroup)
}
}
I have got two different ways to do that. One is using evaluate from groovy like this:
def openShiftTokenByGroup = 'OCP_TOKEN_' + projectProps.namespace.toUpperCase()
evaluate("${openShiftTokenByGroup}") //This will resolve the configured value in Jenkins
The second one is the same approach but in the sh command with eval escaping the $ character:
sh """
eval \$$openShiftTokenByGroup
echo "Token: $openShiftTokenByGroup
"""
This will do the magic too and you'll get the Jenkins configured value.