How to manipulate variable in Jenkins pipeline - sed

been trying several trial and errors on where or how to cut the string in the variable and assign to a new variable to be used by jenkins stage. Normally just removing -TEST Jenkins pipeline indicated below:
properties([
[$class: 'RebuildSettings', autoRebuild: false, rebuildDisabled: false],
parameters([choice(choices: ['SQA-ENV-CLONE', 'DEV-ENV-CLONE'],
description: 'Select the ENV', name: 'ENV')])])
pipeline {
agent any
stages {
stage('VALIDATE ENVIRONMENT') {
def ACTIVE = sh(returnStdout: true, script: "echo $ENV | sed -e 's/-CLONE//g'")
steps {
echo 'Checking 1st the ${ACTIVE}'
}
}
}
}
Error I'm getting
Running in Durability level: MAX_SURVIVABILITY
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 6: Not a valid stage section definition: "def ACTIVE = sh(returnStdout: true, script: "echo $ENV | sed -e 's/-CLONE//g'")". Some extra configuration is required. # line 6, column 9.
stage('VALIDATE ENVIRONMENT') {
^
1 error
at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1085)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
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:131)
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:125)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:560)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:521)
at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:330)
at hudson.model.ResourceController.execute(ResourceController.java:97)
at hudson.model.Executor.run(Executor.java:429)
Finished: FAILURE
Lets say I choose "DEV-ENV-CLONE" as the value I'm expecting to have a successful build with this output:
Checking 1st the DEV-ENV

You need move the def ACTIVE = sh(...) into pipeline step script, They are Groovy script, only can be wrapped by script step.
stage('VALIDATE ENVIRONMENT') {
steps {
script {
ACTIVE = sh(
returnStdout: true,
script: "echo $ENV | sed -e 's/-CLONE//g'"
).trim()
}
echo "Checking 1st the ${ACTIVE}"
}
}

Related

How to view script output (specifically PowerShell) from a Jenkinsfile?

I'm pretty new to Jenkins, so not totally clear on how to assign/read variables.
I have a jenkinsfile with a couple stages and a bunch of steps. In one of the steps, I want to run a PowerShell script but it isn't accomplishing the intent. The problem is, when I'm in Jenkins and I go to the Console Output to troubleshoot why the PowerShell script isn't working, I don't see any of the output from the powershell script, I just see this:
[Pipeline] {
[Pipeline] powershell (Test PowerShell Script)
[Pipeline] }
Here's a trimmed-down version of my code:
stages {
stage('Stage 1') {
agent { node {
label "Windows"
customWorkspace "D:\\Path"
}}
steps {
dir('Directory') {
withCredentials(
[usernameColonPassword(
credentialsId: 'credential1',
variable: 'BasicCred'
)]
) {
powershell(
label: 'Test PowerShell Script',
returnStdout: true,
script: 'echo Test'
)
}
}
}
}
}
I tried using the code provided in this Jenkins article:
steps {
dir('Directory') {
withCredentials(
[usernameColonPassword(
credentialsId: 'credential1',
variable: 'BasicCred'
)]
) {
def msg = powershell(
label: 'Test PowerShell Script',
returnStdout: true,
script: 'echo Test'
)
println msg
}
}
}
This threw an error:
WorkflowScript: 135: Expected a step # line 135, column 25.
def msg = powershell(
^
I also tried putting it inside a node:
steps {
dir('Directory') {
node {
withCredentials(
[usernameColonPassword(
credentialsId: 'credential1',
variable: 'BasicCred'
)]
) {
def msg = powershell(
label: 'Test PowerShell Script',
returnStdout: true,
script: 'echo Test'
)
println msg
}
}
}
}
But it threw an error that the node is missing a label, and when I tried adding a label it threw another error.
So what's the right way to go about this? I just want to capture the output from the PowerShell script and see it so I can troubleshoot why it isn't working.

Not able to run an exe in jenkins pipeline using powershell

I am trying to execute a process which is written in c# through jenkins pipeline during the build and deployment process.
It is a simple executable which takes 3 arguments, when it gets called from jenkins pipeline using a powershell function it doesn't write any logs which are plenty within the code of this exe, also it does not show anything on the pipeline logs as to what happened to this process. Whereas the logs output is clean before and after the execution of this process i.e. "Started..." & "end" gets printed in the jenkins build log.
When i try to run the same exe on a server directly with the same powershel script it runs perfectly fine. Could you please let me know how can i determine whats going wrong here or how can i make the logs more verbose so i can figure out the root cause.
Here is the code snippet
build-utils.ps1
function disable-utility($workspace) {
#the code here fetches the executable and its supporting libraries from the artifactory location and unzip it on the build agent server.
#below is the call to the executable
Type xmlPath #this prints the whole contents of the xml file which is being used as an input to my exe.
echo "disable exe path exists : $(Test-Path ""C:\Jenkins\workspace\utils\disable.exe"")" // output is TRUE
echo "Started..."
Start-Process -NoNewWindow -Filepath "C:\Jenkins\workspace\utils\disable.exe" -ArgumentList "-f xmlPath 0" #xmlPath is a path to a xml file
echo "end."
}
jenkinsfile
library {
identifier: 'jenkins-library#0.2.14',
retriever: legacySCM{[
$class: 'GitSCM',
userRemoteConfigs: [[
credtialsId: 'BITBUCKET_RW'
url: <htps://gitRepoUrl>
]]
]}
}
def executeStep(String stepName) {
def butil = '.\\build\\build-utils.ps1'
if(fileExists(butil))
{
def status = powershell(returnStatus: true, script: "& { . '${butil}'; ${stepName}; }")
echo status
if(status != 0) {
currentBuild.Result = 'Failure'
error("$StepName failed")
}
}
else
{
error("failed to find the file")
}
}
pipeline {
agent {
docker {
image '<path to the docker image to pull a server with VS2017 build tools>'
lable '<image name>'
reuseNode true
}
}
environment {
#loading the env variables here
}
stages {
stage {
step {
executeStep("disable-utility ${env.workspace}")
}
}
}
}
Thanks a lot in advance !
Have you changed it ? go to Regedit [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System Set "EnableLUA"= 0

how to pass variable from powershell script to an other step?

I use Jenkins and pipeline Jenkinsfile with a Windows agent. I want set a veriable from powershell in a 1st step and use this value in a 2nd step after.
my pipeline is:
def MSVERSION
pipeline {
stages {
stage('Clean workspace') {
steps {
deleteDir()
}
}
stage('package') {
steps {
script {
def stdout = powershell(returnStdout: true, script: '''
$MSVERSION="1234"
write-host "MSVERSION is $MSVERSION"
''')
println stdout
}
}
}
stage('deploy') {
steps {
script {
bat 'echo MSVERSION is ${MSVERSION}'
}
bat 'echo MSVERSION is ${MSVERSION}'
}
}
}
}
but my result is:
MSVERSION is 1234
MSVERSION is ${MSVERSION}
MSVERSION is ${MSVERSION}
EDIT
I find a workaroud but is not my question today:
in powershell I write a var.propertie file:
set-Content -path "var.properties" -Value "MSVERSION=$($VERSION)"
and in my script I read this var.properties file:
properties = readProperties file: 'var.properties'
echo "MSVERSION is ${properties.MSVERSION}"
bat 'echo MSVERSION is ${MSVERSION}'
does not do string interpolation, but this does:
bat "echo MSVERSION is ${MSVERSION}"

Jenkins Pipleline using Groovy_Terraform plan job

I am creating a pipeline using jenkins, trying to add a logic where if the terraform-plan is successful then only it will proceed with apply, therefore need get the return value as 0/1/2 from the sh terraform plan command but getting an error as below:
+ gt
+ echo 2
2
C:/Users/Smi/.jenkins/workspace/Pipe_Groovy#tmp/durable-33bd46fb/script.sh: line 2: gt: command not found
+ status
C:/Users/Smi/.jenkins/workspace/Pipe_Groovy#tmp/durable-33bd46fb/script.sh: line 2: status: command not found
[Pipeline] }
Below is the code:
sh "terraform init"
sh "terraform get"
sh "set +e; terraform plan -out=plan.out -detailed-exitcode; echo \$? > status"
def exitCode = readFile('status').trim()
def apply = false
echo "Terraform Plan Exit Code: ${exitCode}"
if (exitCode == "0") {
currentBuild.result = 'SUCCESS'
}
if (exitCode == "1") {
slackSend channel: '#ci', color: '#0080ff', message: "Plan Failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER} ()"
currentBuild.result = 'FAILURE'
}
if (exitCode == "2") {
stash name: "plan", includes: "plan.out"
slackSend channel: '#ci', color: 'good', message: "Plan Awaiting Approval: ${env.JOB_NAME} - ${env.BUILD_NUMBER} ()"
try {
input message: 'Apply Plan?', ok: 'Apply'
apply = true
} catch (err) {
slackSend channel: '#ci', color: 'warning', message: "Plan Discarded: ${env.JOB_NAME} - ${env.BUILD_NUMBER} ()"
apply = false
currentBuild.result = 'UNSTABLE'
}
}
Please advice
Shell is trying to find a command named gt and fails, so your job fails at this step. You probably wanted to use > instead.
There is a way to get the exit code of a bash command without redirecting it into a file and than reading it:
def status = sh(returnStatus: true, script: "set +e; terraform plan -out=plan.out -detailed-exitcode")
Do something as follows:
#!/bin/bash -xe
set +e
/terraform plan -var-file="${env}-custom.tfvars" -refresh=false -detailed-exitcode
PLAN_ECODE=$?
echo ${PLAN_ECODE}
set -e
if [ "${PLAN_ECODE}" -eq 1 ]; then
echo "ERROR!!! something is wrong planning!"
exit 1
elif [ "${PLAN_ECODE}" -eq 0 ]; then
echo "No changes!"
elif [ "${PLAN_ECODE}" -eq 2 ]; then
echo "Applying in progress!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
/terraform apply -auto-approve -var-file="${env}-custom.tfvars"
echo "$i has been updated (check logs above for details)" >> /tmp/logs.txt
fi

Publish Nunit Test Results in Post Always Section

I'm trying to run a pipeline that does some Pester Testing and publish the NUnit results.
New tests were introduced and for whatever the reason, Jenkins no longer publishes the test results and errors out immediately after the powershell script. Hence, it doesn't get to the nunit publish piece. I receive this:
ERROR: script returned exit code 128
Finished: FAILURE
I've been trying to include the publish in the always section of the post section of the Jenkinsfile, however, I'm running into problems on how to make that NUnit test file available.
I've tried establishing an agent and unstash the file (even though it probably won't stash if the powershell script cancels the whole pipeline). When I use agent I get the following exception:
java.lang.NoSuchMethodError: No such DSL method 'agent' found among steps
Here is the Jenkinsfile:
pipeline {
agent none
environment {
svcpath = 'D:\\svc\\'
unitTestFile = 'UnitTests.xml'
}
stages {
stage ('Checkout and Stash') {
agent {label 'Agent1'}
steps {
stash name: 'Modules', includes: 'Modules/*/**'
stash name: 'Tests', includes: 'Tests/*/**'
}
}
stage ('Unit Tests') {
agent {label 'Agent1'}
steps {
dir(svcpath + 'Modules\\'){deleteDir()}
dir(svcpath + 'Tests\\'){deleteDir()}
dir(svcpath){
unstash name: 'Modules'
unstash name: 'Tests'
}
dir(svcpath + 'Tests\\'){
powershell """
\$requiredCoverageThreshold = 0.90
\$modules = Get-ChildItem ../Modules/ -File -Recurse -Include *.psm1
\$result = Invoke-Pester -CodeCoverage \$modules -PassThru -OutputFile ${unitTestFile} -OutputFormat NUnitXml
\$codeCoverage = \$result.CodeCoverage.NumberOfCommandsExecuted / \$result.CodeCoverage.NumberOfCommandsAnalyzed
Write-Output \$codeCoverage
if (\$codeCoverage -lt \$requiredCoverageThreshold) {
Write-Output "Build failed: required code coverage threshold of \$(\$requiredCoverageThreshold * 100)% not met. Current coverage: \$(\$codeCoverage * 100)%."
exit 1
} else {
write-output "Required code coverage threshold of \$(\$requiredCoverageThreshold * 100)% met. Current coverage: \$(\$codeCoverage * 100)%."
}
"""
stash name: 'TestResults', includes: unitTestFile
nunit testResultsPattern: unitTestFile
}
}
post {
always {
echo 'This will always run'
agent {label 'Agent1'}
unstash name: 'TestResults'
nunit testResultsPattern: unitTestFile
}
success {
echo 'This will run only if successful'
}
failure {
echo 'This will run only if failed'
}
unstable {
echo 'This will run only if the run was marked as unstable'
}
changed {
echo 'This will run only if the state of the Pipeline has changed'
echo 'For example, if the Pipeline was previously failing but is now successful'
}
}
}
Any and all input is welcome! Thanks!
The exception you are getting is due to Jenkins' strict pipeline DSL. Documentation of allowable uses of agent are here.
Currently agent {...} is not allowed to be used in the post section. Maybe this will change in the future. If you require the whole job to run on the node that services label 'Agent1' the only way to currently do that is to
Put agent {label 'Agent1'} immediately under pipeline { to make it global
Remove all instances of agent {label 'Agent1'} in each stage
Remove the agent {label 'Agent1'} from the post section.
The post section acts more like traditional scripted DSL than the pipeline declarative DSL. So you have to use node() instead of agent.
I believe I've had this same question myself, and this SO post has the answer and some good context.
This Jenkins issue isn't exactly the same thing but shows the node syntax in the post stage.