Tidak dapat menjalankan perintah shell di Groovy di Jenkins

Saya mencoba mendapatkan nilai tertentu dari budak dengan menjalankan perintah shell seperti:

git rev-parse HEAD
git config --get remote.origin.url

Metode yang saya coba tulis untuk ini adalah:

def executeCommand(String command) {
    stdout = sh script: command, returnStdout: true
    return stdout.trim()
}

Sekarang ketika saya mencoba menjalankan perintah pertama:

output = executeCommand('git rev-parse HEAD')

Saya mendapatkan KESALAHAN:

[Running] groovy "/Users/user-a/Documents/cmd.groovy"
Caught: groovy.lang.MissingMethodException: No signature of method: cmd.sh() is applicable for argument types: (LinkedHashMap) values: [[script:git rev-parse HEAD, returnStdout:true]]
Possible solutions: is(java.lang.Object), use([Ljava.lang.Object;), run(), run(), any(), tap(groovy.lang.Closure)
groovy.lang.MissingMethodException: No signature of method: cmd.sh() is applicable for argument types: (LinkedHashMap) values: [[script:git rev-parse HEAD, returnStdout:true]]
Possible solutions: is(java.lang.Object), use([Ljava.lang.Object;), run(), run(), any(), tap(groovy.lang.Closure)
    at cmd.executeCommand(cmd.groovy:2)
    at cmd.run(cmd.groovy:6)

Saya juga mencoba:

output = command.execute().text

Tapi ini tidak menghasilkan apa-apa.

Saya kehabisan ide tentang cara menjalankan perintah shell di Groovy di Jenkins dan mencatat hasilnya.

DETAIL LEBIH LANJUT

Saya bekerja dengan Perpustakaan bersama Jenkins. Saya telah mengekspos metode untuk Jenkinsfile saya dengan nama getLatestBuildDetails(). Metode ini didefinisikan dalam perpustakaan saya. Salah satu tindakan dalam metode ini adalah menjalankan perintah git secara lokal. Jadi untuk menjalankan perintah shell apa pun secara lokal, saya telah membuat fungsi executeCommand yang mengambil perintah sebenarnya untuk dijalankan sebagai String dan menjalankannya dan mengembalikan output untuk digunakan nanti oleh getLatestBuildDetails()


person Community    schedule 17.08.2018    source sumber
comment
apakah Anda mencoba melakukan hardcoding secara langsung dan mencoba "git rev-parse HEAD"..execute().text   -  person rohit thomas    schedule 17.08.2018
comment
yakin .execute() cocok dengan jenkins-pipeline?   -  person StephenKing    schedule 17.08.2018
comment
Ah.. @Jason Stanley, apakah Anda yakin dengan apa yang Anda lakukan? sh merupakan langkah dari Jenkins Pipelines, namun postingan Anda lainnya tidak Kedengarannya tidak sebanyak Anda sebenarnya menggunakan saluran pipa Jenkins. Bisakah Anda menambahkan detail lebih lanjut, di mana Anda menggunakan kode yang diberikan?   -  person StephenKing    schedule 17.08.2018
comment
@StephenKing Saya menambahkan lebih banyak perspektif. Fungsi executeCommand hanya berfungsi jika saya memanggil @NonCPS jika tidak maka tidak.   -  person    schedule 17.08.2018


Jawaban (2)


Kelas perpustakaan tidak bisa langsung memanggil langkah-langkah seperti sh atau git. Namun mereka dapat mengimplementasikan metode, di luar lingkup kelas yang melingkupinya, yang pada gilirannya memanggil langkah-langkah Pipeline, misalnya:

// src/org/foo/Zot.groovy
package org.foo;

def checkOutFrom(repo) {
  git url: "[email protected]:jenkinsci/${repo}"
}

return this

Yang kemudian dapat dipanggil dari Scripted Pipeline:

def z = new org.foo.Zot()
z.checkOutFrom(repo)

Pendekatan ini memiliki keterbatasan; misalnya, ini mencegah deklarasi superclass.

Sebagai alternatif, serangkaian langkah dapat diteruskan secara eksplisit menggunakan ini ke kelas perpustakaan, dalam konstruktor, atau hanya satu metode:

package org.foo
class Utilities implements Serializable {
  def steps
  Utilities(steps) {this.steps = steps}
  def mvn(args) {
    steps.sh "${steps.tool 'Maven'}/bin/mvn -o ${args}"
  }
}

Saat menyimpan status pada kelas, seperti di atas, kelas tersebut harus mengimplementasikan antarmuka Serializable. Hal ini memastikan bahwa Pipeline yang menggunakan kelas tersebut, seperti terlihat pada contoh di bawah, dapat ditangguhkan dan dilanjutkan dengan benar di Jenkins.

@Library('utils') import org.foo.Utilities
def utils = new Utilities(this)
node {
  utils.mvn 'clean package'
}

Jika perpustakaan perlu mengakses variabel global, seperti env, variabel tersebut harus secara eksplisit diteruskan ke kelas atau metode perpustakaan, dengan cara yang sama.

Daripada meneruskan banyak variabel dari Scripted Pipeline ke perpustakaan,

package org.foo
class Utilities {
  static def mvn(script, args) {
    script.sh "${script.tool 'Maven'}/bin/mvn -s ${script.env.HOME}/jenkins.xml -o ${args}"
  }
}

Contoh di atas menunjukkan skrip diteruskan ke satu metode statis, yang dipanggil dari Scripted Pipeline sebagai berikut:

@Library('utils') import static org.foo.Utilities.*
node {
  mvn this, 'clean package'
}

Dalam kasus Anda, Anda harus menulis sesuatu seperti:

def getLatestBuildDetails(context){
    //...
    executeCommand(context, 'git rev-parse HEAD')
    //...
}

def executeCommand(context, String command) {
    stdout = script.sh(script: command, returnStdout: true)
    return stdout.trim()
}

berkas Jenkins:

@Library('library_name') _
getLatestBuildDetails(this)

Untuk info lebih lanjut lihat dokumentasi perpustakaan bersama jenkins: https://jenkins.io/doc/book/pipeline/shared-libraries/

person grolegor    schedule 26.08.2018

Cobalah langkah sh alih-alih mengeksekusi. :)

EDIT: Saya akan memilih execute() atau yang menurut saya lebih baik, grgit. Saya pikir Anda tidak mendapatkan keluaran apa pun saat menjalankan cmd.execute().text karena .text mengembalikan keluaran standar dari perintah dan perintah Anda mungkin hanya menggunakan kesalahan standar sebagai keluarannya, Anda dapat memeriksa keduanya:

def process = cmd.execute()
def stdOut = process.inputStream.text
def stdErr = process.errorStream.text
person Jonatan Ivanov    schedule 17.08.2018
comment
Dalam Jenkinsfile tradisional, ya ini akan berhasil :) tapi saya bekerja dengan Perpustakaan Bersama Jenkins dan skrip shell dipanggil dari perpustakaan. - person ; 17.08.2018
comment
Ups, maaf, saya salah memahami masalahnya, silakan periksa jawaban saya yang telah diperbarui. - person Jonatan Ivanov; 26.08.2018
comment
Saya mengalami masalah yang sama dengan Process mencoba menjalankan perintah curl. Apakah saya perlu menyingkirkannya atau tidak? stackoverflow .com/questions/56574053/ - person SSF; 13.06.2019