I'm writing Jenkins pipeline script and have an error:
No such DSL method '$' found among steps
At this line:
+ mkdir -p /scratch/jenkins-build-results/Release
I can't figure out what the problem is.
I think I work with params incorrectly, but where?
Script excerpt:
stage('Build and install')
{
steps
{
script
{
buildAndInstall( preset: 'gcc_release', destPath: getReleaseDestPath() )
}
}
}
def buildAndInstall(params)
{
bash("cmake --preset ${params.preset}", "Configure")
bash("cmake --build --preset ${params.preset}", "Building")
sh(script:"mkdir -p ${params.destPath}", label: "Creating a directory for ${params.preset} installation")
def buildDir = getBuildPath( preset : ${params.preset} )
sh(script:"cmake --install ./${buildDir} --prefix ${params.destPath}", label: "Installation")
}
def bash(String cmd, String label)
{
sh(script:"#/usr/bin/env bash\nset -euo pipefail\n${cmd}", label: label)
}
def getReleaseDestPath()
{
return "/scratch/jenkins-build-results/Release"
}
def getBuildPath( params )
{
// 'build' suffix is hardcoded in the cmake presets
return "build/${params.preset}"
}
The problem was in this line:
def buildDir = getBuildPath( preset : ${params.preset} )
It should be the following:
def buildDir = getBuildPath( preset : params.preset )
Related
how can I save a command in a variable and executed anywhere in the stage
tried differnt way, but still success
here is my example
pipeline {
agent any
environment {
myscript = sh '''
echo "hello"
echo "hello"
echo "hello"
'''
}
stages {
stage("RUN") {
steps {
sh "${myscript}"
}
}
}
}
you can do it like this. Not with a groovy variable but can be more dynamic with groovy function/method
def reusableScript(message) {
sh """
echo Hello World
echo Hi ${message}
"""
}
pipeline {
agent any;
stages {
stage('01') {
steps {
script {
reusableScript("From ${env.STAGE_NAME}")
}
}
}
stage('02') {
steps {
script {
reusableScript("From ${env.STAGE_NAME}")
}
}
}
}
}
I a variable in my Jenkinsfile that contains a list of URLs and i would like a be able to run over them. When i pass the variable $URL to the function, I get an error:
No such property: $URL for class: groovy.lang.Binding
However, I'm able to echo this variable with sh.
pipeline {
agent any
environment {
URL="https://www.aaa.com," \
+ "https://www.bbb.com," \
+ "https://www.ccc.com"
}
stages {
stage ('A') {
//...
}
stage ('B') {
//...
}
stage ('C') {
steps {
script {
sh 'echo $URL'
funcion($URL)
}
}
}
}
}
def funcion(URL) {
sh "echo Going to echo a list"
for (int i = 0; i < URL.size(); i++) {
sh "echo ${URL[i]}"
}
}
What could be the issue?
You should pass this variable to the funcion() method as
function(URL)
instead of
funcion($URL)
The dollar sign $ is used only inside the GString when you want to interpolate a variable. For instance
#!groovy
def name = "Joe"
println "My name is $name"
results in
My name is Joe
You can read more about string interpolation in the Groovy documentation - http://groovy-lang.org/syntax.html#_string_interpolation
I need to fail one Jenkins pipeline stage when one file contains 'errors'
I do not know how to return an error from bash to Jenkins
stage('check if file continas error and exit if true') {
steps {
sh "grep 'error' filetocheck.txt"
}
}
}
reference Is it possible to capture the stdout from the sh DSL command in the pipeline
This worked for me,
def runShell(String command){
def responseCode = sh returnStatus: true, script: "${command} &> tmp.txt"
def output = readFile(file: "tmp.txt")
return (output != "")
}
pipeline {
agent any
stages {
stage('check shellcheck') {
steps {
script {
if (runShell('grep \'error\' file_to_parse.txt')) {
sh "exit 1"
}
}
}
}
}
}
you can try using String.count(charSequence) where String could be a file or string.
def file = 'path/to/file.txt'
if ( file.count('error') > 0 )
return stageResultMap.didB2Succeed = false
Following is my code:
task encodeFile(type: Exec) {
workingDir dirName
def files = file(dirName).listFiles()
files.each { File file ->
if (file.isFile()) {
println " *** $file.name *** "
def tmpName = "tmp$file.name"
println " === $tmpName"
commandLine "cmd", "/c native2ascii $file.name $tmpName"
commandLine "cmd", "/c del $file.name"
commandLine "cmd", "/c move $tmpName $file.name"
// commandLine "cmd", "/c move $file.name $tmpName"
println " === $file.name is moved"
println "----------------------------------"
// """executable "native2ascii" "$file.name" "$tmpName""""".execute()
}
}
}
I'm trying to encode all the files under the specified folder for localization. But when I ran the code above, only the last file is changed as expected. I printed some messages and all the files are iterated.
Does anyone know what happens here?
Yes, the last iteration of each invoked on files object sets the configuration up and wins - you can change the order of files passed to verify it.
native2ascii task is built-in gradle by default, you can try e.g.:
task n2a {
doLast {
ant.native2ascii(
src : project.file('n2a-src'),
dest : project.file('n2a-dest')
)
}
}
It seems that there's no need to do it via Exec task.
For me this is working properly:
processResources {
"*.properties, *.txt".split(",").each {pattern ->
filesMatching ("**/" + pattern.trim ()) {
filter {
it
.replace ('${projectVersion}', project.version)
.replace ('${projectName}', project.name)
}
}
}
doLast {
if (file (processResources.destinationDir).exists()) {
ant.native2ascii (
src: "${processResources.destinationDir}",
dest: "${processResources.destinationDir}/../ascii",
includes: '**/*.properties',
)
copy {
from "${processResources.destinationDir}/../ascii"
into processResources.destinationDir
}
}
}
}
I am trying to implement a gradle task to dynamically create a buildsignature.properties file from a series of environment variable values and shell executions. I have it mostly working, but I can't seem to get the output of the shell commands. Here's my task...
task generateBuildSignature << {
ext.whoami = exec() {
executable = "whoami"
}
ext.hostname = exec() {
executable = "hostname"
}
ext.buildTag = System.env.BUILD_TAG ?: "dev"
ant.propertyfile(
file: "${buildDir}/buildsignature.properties",
comment: "This file is automatically generated - DO NOT EDIT!" ) {
entry( key: "version", value: "${project.version}" )
entry( key: "buildTimestamp", value: "${new Date().format('yyyy-MM-dd HH:mm:ss z')}" )
entry( key: "buildUser", value: "${ext.whoami}" )
entry( key: "buildSystem", value: "${ext.hostname}" )
entry( key: "buildTag", value: "$ext.buildTag" )
}
}
But the resulting properties field does not get the desired results for buildUser and buildSystem.
#This file is automatically generated - DO NOT EDIT!
#Mon, 18 Jun 2012 18:14:14 -0700
version=1.1.0
buildTimestamp=2012-06-18 18\:14\:14 PDT
buildUser=org.gradle.process.internal.DefaultExecHandle$ExecResultImpl#2e6a54f9
buildSystem=org.gradle.process.internal.DefaultExecHandle$ExecResultImpl#46f0bf3d
buildTag=dev
How do I get buildUser and buildSystem to match the output of the corresponding exec rather than some default ExecResultImpl toString? This really can't be that hard, can it?
This is my preferred syntax for getting the stdout from exec:
def stdout = new ByteArrayOutputStream()
exec{
commandLine "whoami"
standardOutput = stdout;
}
println "Output:\n$stdout";
Found here: http://gradle.1045684.n5.nabble.com/external-process-execution-td1431883.html
(Note that page has a typo though and mentions ByteArrayInputStream instead of ByteArrayOutputStream)
This post describes how to parse the output from an Exec invocation. Below you'll find two tasks that run your commands.
task setWhoamiProperty {
doLast {
new ByteArrayOutputStream().withStream { os ->
def result = exec {
executable = 'whoami'
standardOutput = os
}
ext.whoami = os.toString()
}
}
}
task setHostnameProperty {
doLast {
new ByteArrayOutputStream().withStream { os ->
def result = exec {
executable = 'hostname'
standardOutput = os
}
ext.hostname = os.toString()
}
}
}
task printBuildInfo {
dependsOn setWhoamiProperty, setHostnameProperty
doLast {
println whoami
println hostname
}
}
There's actually an easier way to get this information without having to invoke a shell command.
Currently logged in user: System.getProperty('user.name')
Hostname: InetAddress.getLocalHost().getHostName()
Using the kotlin-dsl:
import java.io.ByteArrayOutputStream
val outputText: String = ByteArrayOutputStream().use { outputStream ->
project.exec {
commandLine("whoami")
standardOutput = outputStream
}
outputStream.toString()
}
Groovy allows for a much simpler implementation in many cases. So if you are using Groovy-based build scripts you can simply do this:
def cmdOutput = "command line".execute().text
Paraphrased from the Gradle docs for Exec:
task execSomething {
doFirst {
exec {
workingDir '/some/dir'
commandLine '/some/command', 'arg'
...
//store the output instead of printing to the console:
standardOutput = new ByteArrayOutputStream()
//extension method execSomething.output() can be used to obtain the output:
ext.output = {
return standardOutput.toString()
}
}
}
}
kotlin-dsl variants
Groovy style
in buildSrc:
import org.codehaus.groovy.runtime.ProcessGroovyMethods
fun String.execute(): Process = ProcessGroovyMethods.execute(this)
fun Process.text(): String = ProcessGroovyMethods.getText(this)
build.gradle.kts:
"any command you want".execute().text().trim()
exec style
in buildSrc:
import org.gradle.api.Project
import org.gradle.process.ExecSpec
import java.io.ByteArrayOutputStream
fun Project.execWithOutput(spec: ExecSpec.() -> Unit) = ByteArrayOutputStream().use { outputStream ->
exec {
this.spec()
this.standardOutput = outputStream
}
outputStream.toString().trim()
}
build.gradle.kts:
val outputText = project.execWithOutput {
commandLine("whoami")
}
//variable project is actually optional
val outputText = execWithOutput {
commandLine("whoami")
}