[英]groovy.lang.MissingPropertyException: No such property: sh for class: groovy.lang.Binding
Im trying to build a pipeline on Jenkins that runs a command on node and informs me of the following error:我试图在 Jenkins 上构建一个在节点上运行命令并通知我以下错误的管道:
groovy.lang.MissingPropertyException: No such property: sh for class: groovy.lang.Binding
at groovy.lang.Binding.getVariable(Binding.java:63)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:270)
at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:353)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:357)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:333)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:333)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:333)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
at WorkflowScript.run(WorkflowScript:57)
at WorkflowScript.withGheStatusSender(WorkflowScript:150)
at WorkflowScript.run(WorkflowScript:56)
at WorkflowScript.withSlackNotifier(WorkflowScript:178)
at WorkflowScript.run(WorkflowScript:23)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:74)
at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:66)
at sun.reflect.GeneratedMethodAccessor560.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
at com.cloudbees.groovy.cps.Next.step(Next.java:83)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:129)
at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:268)
at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:51)
at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:185)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:400)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$400(CpsThreadGroup.java:96)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:312)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:276)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:136)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Finished: FAILURE
The source code of Jenkinsfile that I refer is from this https://github.com/nobuoka/jenkins-pipeline-sample-for-android/blob/master/Jenkinsfile .我提到的 Jenkinsfile 的源代码来自这个https://github.com/nobuoka/jenkins-pipeline-sample-for-android/blob/master/Jenkinsfile 。 The pipeline success until before stage Assemble管道成功直到组装阶段
Jenkinsfile:詹金斯文件:
stage 'Assemble'
withGheStatusSender('Assemble', env.GIT_COMMIT, 'Building') {
sudo sh './gradlew assemble'
}
stage 'Lint'
withGheStatusSender('Lint', env.GIT_COMMIT, 'Checking') {
// If you run the lint task, lint will be run for all variants, but with only one output.
// For the time being, specify each variant and lint it.
def pfs = ['']
def bts = ['release', 'debug']
List<String> variants = []
pfs.each { pf -> bts.each{ bt -> variants.add(pf + (pf.isEmpty() ? bt : bt.capitalize())) } }
// I want to use the List # collect method, but it doesn't work on Pipeline due to a bug in the groovy-cps library.
// See : https://issues.jenkins-ci.org/browse/JENKINS-26481
List<GString> gradleTasks = []
List<GString> outputFiles = []
variants.each {
gradleTasks.add(":app:lint${it.capitalize()}")
outputFiles.add("lint-results-${it}.html")
}
// テスト失敗時にも結果を保存するように try-catch する。
// Try-catch to save the result even if the test fails.
Throwable error = null
try { sh "./gradlew --stacktrace ${gradleTasks.join(' ')}" } catch (e) { error = e }
try {
publishHTML([
target: [
reportName: 'Android Lint Report',
reportDir: 'app/build/outputs/',
reportFiles: outputFiles.join(','),
],
// Lint でエラーが発生した場合はリポートファイルがないことを許容する。
// Allow Lint to have no report file if an error occurs.
allowMissing: error != null,
alwaysLinkToLastBuild: true,
keepAll: true,
])
} catch (e) { if (error == null) error = e }
if (error != null) throw error
}
stage 'Local Unit Test'
withGheStatusSender('Local Unit Test', env.GIT_COMMIT, 'Testing') {
runTestAndArchiveResult(':app:test', 'app/build/test-results', '*/TEST-*.xml')
}
// Emulator にバージョンアップで以下のものが使えなくなったので一旦コメントアウト。
// 社内では shell スクリプトで AVD の起動や終了をするようにした。
// Since the following items can no longer be used with the version upgrade to Emulator, comment out once.
// In-house, the shell script is used to start and stop AVD
/*
stage 'Instrumented Test'
try {
sh './gradlew :avd:startAvd'
sh './gradlew connectedAndroidTest'
} finally {
sh './gradlew :avd:killAvd'
}
*/
}
}
/** GHE にステータスを通知する。 */
void postGheStatus(Map<String, String> params) {
// 送信する JSON をファイルに書き出しておく。
String jsonFileName = 'jenkins_pipeline_input_json.temp'
String jsonContent = groovy.json.JsonOutput.toJson([
state: params['state'],
target_url: env.BUILD_URL,
description: params['description'],
context: params['context'],
])
writeFile file: jsonFileName, text: jsonContent
// 実際に送信する際にはここのコメントアウトを外す。
/*
sh 'curl --insecure -H "Authorization: token ' + C.GHE_TOKEN + '" ' +
'"' + C.GHE_API + '/repos/' + C.GHE_REPO + '/statuses/' + params['commitHash'] + '" ' +
'-X POST ' +
'-d @' + jsonFileName
*/
}
/**
* GHE へのステータス通知を行ってタスクの実行を行う。
The chair of the GHE chair.
* タスク実行前に pending 状態を通知し、タスク完了後に、タスクの結果に応じて成功か失敗の状態を通知する。
Notify the pending status before executing the task, and notify the success or failure status after the task is completed, depending on the result of the task.
*/
void withGheStatusSender(String context, String commitHash, String firstDescription, Closure task) {
postGheStatus(context: context, commitHash: commitHash, state: 'pending', description: firstDescription)
try {
task()
postGheStatus(context: context, commitHash: commitHash, state: 'success', description: 'Success')
} catch (e) {
postGheStatus(context: context, commitHash: commitHash, state: 'failure', description: 'Failure')
throw e
}
}
/** Slack に投稿する。 */
/** Post to Slack. */
void postSlack(String text, boolean useNgJenkinsIcon) {
String slackUrl = C.SLACK_WEBHOOK_URL
String iconImageUrl = useNgJenkinsIcon ?
'成功時の Jenkins アイコン' :
'失敗時の Jenkins アイコン'
String payload = groovy.json.JsonOutput.toJson([
text: text,
icon_url: iconImageUrl,
])
// 実際に送信する際にはここのコメントアウトを外す。//Uncomment here when actually sending.
//sh "curl -X POST --data-urlencode \'payload=${payload}\' ${slackUrl}"
}
/** タスクを実行し、実行後に成功か失敗かを Slack に投稿する。 */
//Execute the task and post to Slack whether it succeeded or failed after execution.
void withSlackNotifier(Closure task) {
echo "branch name : ${env.BRANCH_NAME}"
try {
task()
postSlack("Job for branch `${env.BRANCH_NAME}` succeeded! (<${env.BUILD_URL}|Open>)", false)
} catch (e) {
postSlack("Job for branch `${env.BRANCH_NAME}` failed! (<${env.BUILD_URL}|Open>)", true)
throw e
}
}
void runTestAndArchiveResult(String gradleTestTask, String resultsDir, String resultFilesPattern) {
// `test` タスクの入力と出力の両方とも更新がなければ `test` タスクがスキップされる (UP-TO-DATE) ので、
// スキップされないように出力ディレクトリを消しておく。
// The `test` task will be skipped (UP-TO-DATE) if both the input and output of the` test` task are not updated.
// Delete the output directory so that it will not be skipped.
sh "rm -rf ${resultsDir}"
// テスト失敗時にも結果を保存するように try-catch する//// Try-catch to save the result even if the test fails.
Throwable error = null
try { sh "./gradlew --stacktrace ${gradleTestTask}" } catch (e) { error = e }
try {
step $class: 'JUnitResultArchiver', testResults: "${resultsDir}/${resultFilesPattern}"
} catch (e) { if (error == null) error = e }
if (error != null) throw error
}
I found that the suggestion need to install script security plugin but I am not sure.我发现建议需要安装脚本安全插件,但我不确定。 Any suggestion to fix it?有什么建议可以解决吗?
Without having the line numbers available and what seems very bad formatting in terms of tabs in the Jenkinsfile following the stack trace is quite hard to debug.如果没有可用的行号,并且在堆栈跟踪之后的 Jenkinsfile 中的选项卡方面看起来非常糟糕的格式,很难调试。
However I suspect it might be this line sudo sh './gradlew assemble'
as sudo
isnt a valid groovy command.但是我怀疑它可能是这一行sudo sh './gradlew assemble'
因为sudo
不是有效的 groovy 命令。 If you are wanting to run the gradlew as sudo then it would be sh 'sudo./gradlew assemble'
如果您想将 gradlew 作为 sudo 运行,那么它将是sh 'sudo./gradlew assemble'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.