Jenkins: Không thể xác định biến trong giai đoạn đường ống


106

Tôi đang cố gắng tạo một tập lệnh đường ống Jenkins khai báo nhưng gặp sự cố với khai báo biến đơn giản.

Đây là kịch bản của tôi:

pipeline {
   agent none
   stages {
       stage("first") {
           def foo = "foo" // fails with "WorkflowScript: 5: Expected a step @ line 5, column 13."
           sh "echo ${foo}"
       }
   }
}

Tuy nhiên, tôi gặp lỗi này:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 5: Expected a step @ line 5, column 13.
           def foo = "foo"
           ^

Tôi đang sử dụng Jenkins 2.7.4 và Pipeline 2.4.

Câu trả lời:


101

Mô hình Khai báo cho Đường ống Jenkins có một tập hợp con bị hạn chế về cú pháp mà nó cho phép trong các stagekhối - hãy xem hướng dẫn cú pháp để biết thêm thông tin . Bạn có thể bỏ qua hạn chế đó bằng cách gói các bước của mình trong một script { ... }khối, nhưng do đó, bạn sẽ mất xác thực cú pháp, tham số, v.v. trong scriptkhối.


5
Điều gì xảy ra nếu tôi muốn sử dụng biến đó bên ngoài khối script?
Jan Steinke

3
cho việc sử dụng biến bên ngoài khối kịch bản kiểm tra điều này stackoverflow.com/questions/43879733/...
Senthil Một Kumar

56

Tôi nghĩ rằng lỗi không phải đến từ dòng được chỉ định mà là từ 3 dòng đầu tiên. Hãy thử cái này thay thế:

node {
   stage("first") {
     def foo = "foo"
     sh "echo ${foo}"
   }
}

Tôi nghĩ rằng bạn đã có một số dòng bổ sung không hợp lệ ...

BIÊN TẬP

Từ tài liệu mô hình đường ống giải mã , có vẻ như bạn phải sử dụng environmentkhối khai báo để khai báo các biến của mình, ví dụ:

pipeline {
   environment {
     FOO = "foo"
   }

   agent none
   stages {
       stage("first") {
           sh "echo ${FOO}"
       }
   }
}

1
Bạn cũng có thể thêm một khối môi trường vào một giai đoạn (ví dụ: nếu biến của bạn phụ thuộc vào điều gì đó được thực hiện trong bước trước đó).
Tereza Tomcova

34

Đồng ý với @ Pom12, @abayer. Để hoàn thành câu trả lời, bạn cần thêm khối tập lệnh

Hãy thử một cái gì đó như sau:

pipeline {
    agent any
    environment {
        ENV_NAME = "${env.BRANCH_NAME}"
    }

    // ----------------

    stages {
        stage('Build Container') {
            steps {
                echo 'Building Container..'

                script {
                    if (ENVIRONMENT_NAME == 'development') {
                        ENV_NAME = 'Development'
                    } else if (ENVIRONMENT_NAME == 'release') {
                        ENV_NAME = 'Production'
                    }
                }
                echo 'Building Branch: ' + env.BRANCH_NAME
                echo 'Build Number: ' + env.BUILD_NUMBER
                echo 'Building Environment: ' + ENV_NAME

                echo "Running your service with environemnt ${ENV_NAME} now"
            }
        }
    }
}

4
Lưu ý rằng ví dụ này giả định rằng đã có một biến môi trường xác định "ENVIRONMENT_NAME" có thể truy cập vào jenkins.
Alberto

1
Khối script có thể thay đổi các giá trị môi trường không?
pitchblack408

Có, bạn có thể thay đổi giá trị môi trường bên trong khối tập lệnh de.
NicoPaez

8

Trong Jenkins 2.138.3 có hai loại đường ống khác nhau.

Đường ống khai báo và tập lệnh.

"Đường ống khai báo là một phần mở rộng mới của DSL đường ống (về cơ bản nó là một tập lệnh đường ống chỉ có một bước, một bước đường ống với các đối số (được gọi là chỉ thị), các chỉ thị này phải tuân theo một cú pháp cụ thể. Điểm của định dạng mới này là nó nghiêm ngặt hơn và do đó sẽ dễ dàng hơn đối với những người mới sử dụng đường ống, cho phép chỉnh sửa đồ họa và hơn thế nữa. Đường ống theo tập lệnh là dự phòng cho các yêu cầu nâng cao. "

đường ống jenkins: tác nhân và nút?

Đây là một ví dụ về việc sử dụng các biến môi trường và toàn cục trong một Đường ống so sánh. Từ những gì tôi có thể cho biết môi trường là tĩnh sau khi chúng được thiết lập.

def  browser = 'Unknown'

pipeline {
    agent any
    environment {
    //Use Pipeline Utility Steps plugin to read information from pom.xml into env variables
    IMAGE = readMavenPom().getArtifactId()
    VERSION = readMavenPom().getVersion()


    }
    stages {
        stage('Example') {
            steps {
                script {
                    browser = sh(returnStdout: true, script: 'echo Chrome')
                }
            }
        }
        stage('SNAPSHOT') {
                when {
                    expression { 
                        return !env.JOB_NAME.equals("PROD") && !env.VERSION.contains("RELEASE")
                    }
                }
                steps {
                    echo "SNAPSHOT"
                    echo "${browser}"
                }
            }
            stage('RELEASE') {
                when {
                    expression { 
                        return !env.JOB_NAME.equals("TEST") && !env.VERSION.contains("RELEASE")
                    }
                }
                steps {
                    echo "RELEASE"
                    echo "${browser}"
                }
            }
    }//end of stages 
}//end of pipeline

Tôi gặp lỗi sau từ mã trên: [Pipeline] Start of Pipeline [Pipeline] readMavenPom [Pipeline] End of Pipeline org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: Lớp ngữ cảnh bắt buộc hudson.FilePath bị thiếu Có lẽ bạn đã quên bao quanh mã với một bước cung cấp điều này, chẳng hạn như: node
mancocapac

Không, nó đã hoạt động như vậy. Nó là một đường ống khai báo. Đại lý bất kỳ phương tiện mà nó có thể làm việc trên bất kỳ nút
pitchblack408

@ pitchblack408, bạn nói đúng là tôi đã có [không có đại lý] ở đầu đường dẫn của mình. Không chắc bạn muốn nói gì: môi trường tĩnh sau khi chúng được thiết lập? Chúng có thể được thay đổi trong một tập lệnh, ví dụ: script {IMAGE = "newVal}
mancocapac

Ví dụ, hãy nhìn vào IMAGE. Nó không thể thay đổi mà có thể hoặc cần được thay đổi bởi các đường ống. Tôi hiểu rằng nó được coi là một giá trị tĩnh sau khi định nghĩa như một phần của môi trường.
pitchblack408

0

Bạn đang sử dụng Đường ống so sánh yêu cầu bước tập lệnh để thực thi mã Groovy. Đây là một sự khác biệt rất lớn so với Đường ống có tập lệnh khi điều này là không cần thiết.

Các tài liệu chính thức cho biết như sau:

Bước tập lệnh lấy một khối Đường ống được mã hóa và thực thi nó trong Đường ống so sánh.

pipeline {
   agent none
   stages {
       stage("first") {
           script {
               def foo = "foo" 
               sh "echo ${foo}"
           }
       }
   }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.