$Variable is not expanding in Library definition in Jenkinsfile - jenkins

This Groovy Jenkinsfile script works
#Library('jenkins-library#master')_
pipeline {
agent { label 'my-host-01' }
stages {
...
...
But it don't work if I change the first line to use a variable $MY_BRANCH
#Library('jenkins-library#$MY_BRANCH')_
Got below error:
ERROR: Could not resolve $MY_BRANCH
hudson.plugins.git.GitException: Command "git rev-parse $MY_BRANCH^{commit}" returned status code 128:
stdout: $MY_BRANCH^{commit}
MY_BRANCH is a parameter to the job, so this variable is available, but its not getting expanded in Jeenkinsfile script, is there a different syntax to use?
My pipeline job is setup like below, the above code is in Jenkinsfile.

Related

Jenkins "unable to resolve class Declarative" error when building Python script

I began learning to use to Jenkins and wanted to make it run a Python script of mine automatically. I followed their tutorial and created a new Project called Pipeline Test.
I've also added the GitHub repo of a Python script I wanted to test (https://github.com/mateasmario/spam-bot).
As you can see, I've created a Jenkinsfile in that repo. Because my script is called spam-bot.py, I want my Jenkinsfile to run that script every time I click "Build now" inside Jenkins. This is the content of my Jenkinsfile:
Jenkinsfile (Declarative Pipeline)
pipeline {
agent { docker { image 'python:3.10.1-alpine' } }
stages {
stage('build') {
steps {
sh 'python spam-bot.py'
}
}
}
}
The problem is, whenever I click "Build now", my build fails and the console outputs the following error:
Started by user Mario Mateas
Obtained Jenkinsfile from git https://github.com/mateasmario/spam-bot.git
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 1: unable to resolve class Declarative
# line 1, column 26.
Jenkinsfile (Declarative Pipeline)
^
1 error
at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:958)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:605)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:554)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:142)
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:127)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:571)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:523)
at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:334)
at hudson.model.ResourceController.execute(ResourceController.java:99)
at hudson.model.Executor.run(Executor.java:432)
Finished: FAILURE
I looked up for this error on the internet, but didn't find any useful information, and that's why I decided to ask here.
I also don't have any Docker container configured. Do I need to configure one? I took a look over Jenkins' documentation for Docker, but didn't see any useful information for adding a Python image (as the one mentioned at the beginning of the Jenkinsfile) to the container.
Your Jenkinsfile contains invalid syntax on the first line, which is why the error is being thrown. Assuming you intended that first line to be a comment, you can modify the pipeline code to be:
// Jenkinsfile (Declarative Pipeline)
pipeline {
...
}
and your pipeline code will have valid syntax.

Jenkins pipeline store SSH credentials as parameter

I have the following pipeline code:
pipeline {
agent any
environment {
SSH_KEY_PARAMETER = credentials('SSH_KEY')
}
stages {
stage('Checkout') {
steps{
script{
git credentialsId: 'SSH_KEY_PARAMETER', url: 'git#github.com:SomeUser/PrivateRepo.git', branch: 'main'
}
}
}
}
}
Expected output is cloning the repo.
Actual output:
ERROR: Error fetching remote repo 'origin'
hudson.plugins.git.GitException: Failed to fetch from git#github.com:SomeUser/PrivateRepo.git
at hudson.plugins.git.GitSCM.fetchFrom(GitSCM.java:1001)
at hudson.plugins.git.GitSCM.retrieveChanges(GitSCM.java:1242)
at hudson.plugins.git.GitSCM.checkout(GitSCM.java:1302)
at org.jenkinsci.plugins.workflow.steps.scm.SCMStep.checkout(SCMStep.java:129)
at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:97)
at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:84)
at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: hudson.plugins.git.GitException: Command "git fetch --tags --force --progress -- git#github.com:SomeUser/PrivateRepo.git +refs/heads/*:refs/remotes/origin/*" returned status code 128:
stdout:
stderr: git#github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:2681)
at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandWithCredentials(CliGitAPIImpl.java:2102)
at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.access$500(CliGitAPIImpl.java:86)
at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$1.execute(CliGitAPIImpl.java:624)
at hudson.plugins.git.GitSCM.fetchFrom(GitSCM.java:999)
If I change the pipeline code to use the credential ID instead of the variable it works:
pipeline {
agent any
environment {
SSH_KEY_PARAMETER = credentials('SSH_KEY')
}
stages {
stage('Checkout') {
steps{
script{
git credentialsId: 'SSH_KEY', url: 'git#github.com:SomeUser/PrivateRepo.git', branch: 'main'
}
}
}
}
}
In my pipeline I need to manage a bunch of SSH keys depending on the environment, so I need to be able to parameterize the SSH key, am I missing something here or is it not possible to assign an SSH key as variable?
Your environment directive with use of the credentials helper method is syntactically correct. Your syntax for accessing the variable is incorrect. You are assigning a literal string value 'SSH_KEY_PARAMETER' to the credentialsId argument. The actual value also is stored in the env object, so you would access it with the appropriate key env.SSH_KEY_PARAMETER. The usage would then look like:
credentialsId: env.SSH_KEY_PARAMETER
However, the git step is expecting the credentials ID for that argument and not the actual credentials. Therefore, you need to also assign the value of the credentialsId in the environment directive instead:
SSH_KEY_PARAMETER = 'SSH_KEY'
Putting it all together, we have:
environment {
SSH_KEY_PARAMETER = 'SSH_KEY'
}
stages {
...
git credentialsId: env.SSH_KEY_PARAMETER, url: 'git#github.com:SomeUser/PrivateRepo.git', branch: 'main'
}

Jenkins pipeline error in handling json file

I'm newbie to Jenkins pipeline and writing a groovy script to parse a json file. However I'm facing an error which many have faced but none of the solutions worked for me. Below is my Jenkinsfile and error msg.
def envname = readJSON file: '${env.WORKSPACE}/manifest.json'
pipeline {
agent any
stages {
stage('Build') {
steps {
echo WORKSPACE
sh "ls -a ${WORKSPACE}"
}
}
}
}
[Pipeline] Start of Pipeline
[Pipeline] readJSON
[Pipeline] End of Pipeline
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 at
org.jenkinsci.plugins.pipeline.utility.steps.AbstractFileOrTextStepExecution.run(AbstractFileOrTextStepExecution.java:30)
I even tried readJSON file: '${WORKSPACE}/manifest.json but that didn't work too. I'm sure the mistake is with the first line since when removing that line, there execution is successful. The docs are pretty helpful but I'm not able to track down where exactly I'm going wrong that is why posted here.
UPDATE:
I tried the following methods def envname = readJSON file: "./manifest.json" and def envname = readJSON file: "${env.WORKSPACE}/manifest.json" and even tried them defining under the steps block. Nothing worked. Below is the error msg I recieved when I defined them under step block
WorkflowScript: 5: Expected a step # line 7, column 13
def envname =
^
Below is the official syntax doc of readJson and I can see that I'm using the correct syntax only. but still doesn't work as expected.
https://www.jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#readjson-read-json-from-files-in-the-workspace
'${env.WORKSPACE}/manifest.json' is interpolating the Groovy env map as a shell variable. You need to interpolate it as a Groovy variable like "${env.WORKSPACE}/manifest.json".
sh "ls -a ${WORKSPACE}" is interpolating the shell environment variable WORKSPACE as a Groovy variable. You need to interpolate it as a shell variable like sh 'ls -a ${WORKSPACE}'.
echo WORKSPACE is attempting to resolve the shell variable WORKSPACE as a first class Groovy variable expression. You need to use the Groovy env map instead like echo env.WORKSPACE.
As for the global variable indefinite type assignment on the first line: if it still throws the error above after making those fixes, then it may be due to invalid use of scripted syntax in a declarative syntax pipeline. You likely need to place it inside a step block within your pipeline in that case.
I've solved this myself with the help of "Matt Schuchard"'s below answer. I'm not sure whether this is the only way to solve but this worked for me.
pipeline {
agent any
stages {
stage('Json-Build') {
steps {
script {
def envname = readJSON file: "${env.WORKSPACE}/manifest.json"
element1 = "${envname.dev}"
echo element1
}
}
}
}
}

terraform fmt fails within a Jenkins pipeline

I am running
sh "terraform fmt -list=true -write=false -diff=true -check=true"
within a Jenkins pipeline, and got the following weird error message:
ERROR: Terraform Lint failed due to: hudson.AbortException: script returned exit code 3
Finished: FAILURE
If I just run the terraform fmt ... without the pipeline, then it is ok. Any suggestion on how I can fix this weird error?
As mentioned in the Release Notes for Terraform 0.10.5 (but not in the documentation), the -check parameter
makes it return a non-zero exit status if any formatting changes are required
When you run it locally, it will not output any error, but if you would afterwards check the exit code echo $?, it would be again 3.
In Jenkins, however, any sh step returning non-zero status is treated as failure. So you either remove the -check option, or you deal with it correctly, i.e.,
def fmtStatus = sh "terraform fmt -list=true -write=false -diff=true -check=true"
if (fmtStatus == 0) {
echo "All correct"
} else {
echo "Changes necessary"
}

Jenkins - export a scripted pipeline into a shared lib

We have a few similar apps that are deployed with a scripted pipeline which is basically C&P over all apps. I would like to move the whole pipeline into a Jenkins shared lib as hinted in the Jenkins docs.
So let's suppose that I have the following "pipeline" in var/standardSpringPipeline.groovy:
#!groovy
def call() {
node {
echo "${env.BRANCH_NAME}"
}
}
Then - the Jenkins file:
#Library('my-jenkins-lib#master') _
standardSpringPipeline
echo "Bye!"
Unfortunately this does not work for a reason that I do not understand. The Jenkins output is similar:
> git fetch --no-tags --progress ssh://git#***.com:7999/log/my-jenkins-lib.git +refs/heads/*:refs/remotes/origin/*
Checking out Revision 28900d4ed5bcece9451655f6f1b9a41a76256629 (master)
> git config core.sparsecheckout # timeout=10
> git checkout -f 28900d4ed5bcece9451655f6f1b9a41a76256629
Commit message: "NOJIRA: ...."
> git rev-list --no-walk 28900d4ed5bcece9451655f6f1b9a41a76256629 # timeout=10
[Pipeline] echo
Bye!
[Pipeline] End of Pipeline
Any clue why this does not work (see the output above) and what is the correct way to do that?
For no-arg methods, you cannot use optional parenthesis. From the Groovy documentation (emphasis mine):
Method calls can omit the parentheses if there is at least one parameter and there is no ambiguity:
println 'Hello World'
def maximum = Math.max 5, 10
Parentheses are required for method calls without parameters or
ambiguous method calls:
println()
println(Math.max(5, 10))
The standardSpringPipeline behaves like a method because of how it is compiled. If you add a echo "$standardSpringPipeline" it is a bit clearer that it is a compiled class that can be invoked.
To address your issue, just add parenthesis to the call:
standardSpringPipeline()

Resources