không xây dựng jenkins nếu thực thi shell thất bại


132

Là một phần của quá trình xây dựng của tôi, tôi đang chạy một cam kết git như một bước thực thi shell. Tuy nhiên, nếu không có thay đổi trong không gian làm việc, Jenkins đang thất bại trong quá trình xây dựng. Điều này là do git đang trả về mã lỗi khi không có thay đổi nào để cam kết. Tôi muốn hủy bỏ bản dựng hoặc chỉ đánh dấu nó là không ổn định nếu đây là trường hợp. Có ý kiến ​​gì không?


Kiểm tra nếu có bất cứ điều gì để cam kết, và chỉ cam kết trong những trường hợp đó? stackoverflow.com/questions/5139290/ từ
Anders Lindahl

Câu trả lời:


210

Để dừng thực thi thêm khi lệnh thất bại:

command || exit 0

Để tiếp tục thực thi khi lệnh thất bại:

command || true


12
Bạn không cần || exit 0trong trường hợp đầu tiên, nếu commandtrả về sai, việc thực thi sẽ dừng lại. Điều đó nói rằng, lựa chọn thứ hai là rất hữu ích!
alfasin

20
@alfasin Bạn không hiểu vấn đề. OP không muốn bản dựng Jenkins thất bại; Chúng ta phải làm thế exit 0bởi vì bất kỳ mã thoát khác không sẽ không xây dựng được.
Câu hỏi của Quolonel

1
Tôi thấy, trong trường hợp đó tôi sẽ thay đổi từ ngữ từ: "Để dừng thực thi thêm khi lệnh thất bại:" thành: "Để dừng thực thi thêm khi lệnh thất bại và đánh dấu công việc của Jenkins là thành công:".
alfasin

1
@alfasin Trong khi tôi đồng ý rằng Quolonel Câu hỏi nhận xét linh hoạt là không chuyên nghiệp, anh ấy đã đúng trong những gì anh ấy nói. "Thoát 0" sẽ KHÔNG đánh dấu công việc thành công. Nó sẽ chỉ đánh dấu bước xây dựng hiện tại thành công. Công việc vẫn có thể thất bại ở một trong các bước xây dựng tiếp theo.
noamik

1
Cảm ơn điều này đã làm việc! Điều này đặc biệt hữu ích cho tính năng "Thực thi trình bao trên máy chủ từ xa bằng ssh" vì bạn không thể sử dụng / bin / bash + e để không bị lỗi. Tôi cũng thích ý tưởng tôi có thể chọn các lệnh không thất bại trong quá trình xây dựng.
leeman24

80

Jenkins đang thực hiện các bước xây dựng shell bằng cách sử dụng /bin/sh -xetheo mặc định. -xcó nghĩa là in mọi lệnh được thực thi. -ecó nghĩa là thoát với thất bại nếu bất kỳ lệnh nào trong tập lệnh thất bại.

Vì vậy, tôi nghĩ những gì đã xảy ra trong trường hợp của bạn là thoát lệnh git của bạn với 1 và vì tham số mặc định -e, shell chọn mã thoát không 0, bỏ qua phần còn lại của tập lệnh và đánh dấu bước là thất bại. Chúng tôi có thể xác nhận điều này nếu bạn có thể đăng kịch bản bước xây dựng của mình tại đây.

Nếu đó là trường hợp, bạn có thể cố gắng đặt #!/bin/shđể tập lệnh sẽ được thực thi mà không có tùy chọn; hoặc thực hiện một set +ehoặc bất cứ điều gì tương tự ở đầu bước xây dựng để ghi đè hành vi này.


Đã chỉnh sửa: Một điều cần lưu ý là, nếu lệnh cuối cùng trong tập lệnh shell của bạn trả vềkhông 0 , toàn bộ bước xây dựng sẽ vẫn được đánh dấu là thất bại ngay cả với thiết lập này. Trong trường hợp này, bạn chỉ cần đặt một echolệnh ở cuối để tránh điều đó.

Một câu hỏi liên quan khác


41

Nếu không có gì để đẩy git trả về trạng thái thoát 1. Thực hiện bước xây dựng shell được đánh dấu là thất bại tương ứng. Bạn có thể sử dụng câu lệnh OR | | (ống đôi).

git commit -m 'some messasge' || echo 'Commit failed. There is probably nothing to commit.'

Điều đó có nghĩa là, thực thi đối số thứ hai nếu lần đầu tiên thất bại (trả về trạng thái thoát> 0). Lệnh thứ hai luôn trả về 0. Khi không có gì để đẩy (thoát trạng thái 1 -> thực hiện lệnh thứ hai) echo sẽ trả về 0 và bước xây dựng tiếp tục.

Để đánh dấu bản dựng là không ổn định, bạn có thể sử dụng bước sau khi xây dựng Jenkins Text Finder. Nó có thể đi qua đầu ra giao diện điều khiển, mô hình khớp (tiếng vang của bạn) và đánh dấu xây dựng là không ổn định.


27

Có một cách trơn tru khác để nói với Jenkins đừng thất bại. Bạn có thể cô lập cam kết của mình trong bước xây dựng và đặt shell không bị lỗi:

set +e
git commit -m "Bla."
set -e

2
Đảm bảo thêm set -esau lệnh mà bạn muốn chạy bất kể mã thoát. Nếu không, bạn có thể sẽ thực hiện các lệnh bạn không có ý định. Tôi muốn tự xử lý lỗi, vì vậy tôi đã làm một cái gì đó như: `set + e commit -m" bla "EXIT_CODE =" $ {?} "Set -e # xử lý logic thoát
mã`

8

Jenkins xác định thành công / thất bại của một bước bằng giá trị trả về của bước đó. Đối với trường hợp của shell, nó sẽ là giá trị trả về của giá trị cuối cùng. Đối với cả vỏ Windows CMD và (POSIX) Bash, bạn sẽ có thể đặt giá trị trả về theo cách thủ công bằng cách sử dụng exit 0làm lệnh cuối cùng.


điều này dường như không hoạt động đối với một 'cửa sổ thực thi' có 2 dòng: git commit -m "message" exit 0
Ben

@Ben Tôi sử dụng exit 0với "thực thi lệnh windows windows" trong nhiều bản dựng trên bản cài đặt Windows Jenkins của tôi và nó hoạt động như mong đợi. Một cái gì đó khác phải được diễn ra. Bạn có thể đăng phần có liên quan của nhật ký giao diện điều khiển?
jwernerny

bạn đang sử dụng nó với git commit -m "blah" trong bước đầu tiên của bạn? Tôi đã thử tạo một tập lệnh bat trên máy theo cách thủ công, và đặt một tiếng vang và thoát 0 sau lệnh git. Không có lệnh nào khác được chạy khi không có gì để cam kết ...
Ben

Xem câu trả lời từ @xiawei. Hành vi mặc định của Jenkins là thực thi shell #!/bin/sh -xvmà kết quả là dừng tập lệnh nếu gặp bất kỳ lỗi nào.
Steven dễ dàng thích thú

8

Tôi đã có thể làm việc này bằng cách sử dụng câu trả lời được tìm thấy ở đây:

Làm thế nào để git cam kết không có gì mà không có lỗi?

git diff --quiet --exit-code --cached || git commit -m 'bla'

1
Những gì ở trên là: "Thực hiện git difflệnh và nếu thất bại, hãy thực hiện git commitlệnh. Về cơ bản, nó chỉ thực hiện cam kết, nếu git difftìm thấy điều gì đó để cam kết. Tuy nhiên, câu trả lời @jwerny là chính xác mà bạn có thể thêm exit 0vào như câu lệnh cuối cùng với bất kỳ kịch bản nào để khiến Jenkins coi đó là thành công. Tôi có thể nghĩ đến một kịch bản mà điều này sẽ thất bại nếu bạn đang thực hiện bước shell Linux, nhưng trong Batch, điều này sẽ luôn hoạt động.
Slav

@Ben Jenkins đang thực hiện các bước xây dựng shell bằng cách sử dụng /bin/sh -xetheo mặc định như được đề cập ở đây (ở giữa). Vì vậy, bạn có thể thử đặt #!/bin/bashhoặc thực hiện set +etrên đầu bước xây dựng để ghi đè hành vi này, việc này sẽ tiếp tục phần còn lại của bước ngay cả một lệnh bên trong lối ra với mã không 0
Xiawei Zhang

8

Về câu hỏi (tổng quát hơn) trong tiêu đề - để ngăn Jenkins không thành công, bạn có thể ngăn nó xem mã thoát 1. Ví dụ cho ping:

bash -c "ping 1.2.3.9999 -c 1; exit 0"

Và bây giờ bạn có thể lấy ví dụ đầu ra của ping:

output=`bash -c "ping 1.2.3.9999 -c 1; exit 0"`

Tất nhiên thay vì ping ...Bạn có thể sử dụng bất kỳ lệnh nào - bao gồm git commit.



6

Bạn có thể sử dụng Plugin Text-finder . Nó sẽ cho phép bạn kiểm tra bảng điều khiển đầu ra cho biểu hiện của sự lựa chọn của bạn sau đó đánh dấu bản dựng là Unstable.


Điều này có vẻ đầy hứa hẹn, nhưng vì một số lý do, nó tiếp tục thất bại trong quá trình xây dựng.
Ben

4

Đối với nhiều lệnh shell, tôi bỏ qua các lỗi bằng cách thêm:

set +e commands true

nhập mô tả hình ảnh ở đây


Tôi không khuyến khích việc không đặt cược - nói chung. Nếu bạn muốn bỏ qua một số giá trị trả về của một số lệnh cụ thể, bạn có thể thêm "|| true" hoặc một cái gì đó có ý nghĩa hơn trả về true, chẳng hạn như: stop-service.sh || Dịch vụ tiếng vang đã ngừng hoạt động
Raúl Salinas-Monteagudo

3

Nếu bạn đặt lệnh này vào khối shell:

false
true

bản dựng của bạn sẽ được đánh dấu là không thành công (ít nhất 1 mã thoát khác không), vì vậy bạn có thể thêm (set + e) ​​để bỏ qua nó:

set +e
false
true

sẽ không thất bại. Tuy nhiên, điều này sẽ thất bại ngay cả với (set + e) ​​tại chỗ:

set +e
false

bởi vì lệnh shell cuối cùng phải thoát bằng 0.


2

Sau đây hoạt động cho đồng bóng bằng cách chỉ cam kết nếu có thay đổi. Vì vậy, việc xây dựng chỉ thất bại nếu cam kết thất bại.

hg id | grep "+" || exit 0
hg commit -m "scheduled commit"

0

Một câu trả lời khác với một số lời khuyên, có thể hữu ích cho ai đó:

nhớ tách các lệnh của bạn theo quy tắc sau :

lệnh1 && lệnh2 - có nghĩa là, lệnh2 sẽ được thực thi, chỉ khi lệnh1 thành công

lệnh1 ; lệnh2 - có nghĩa là, lệnh 2 đó sẽ được thực thi mặc dù kết quả của lệnh1

ví dụ:

String run_tests = sh(script: "set +e && cd ~/development/tests/ && gmake test ;set -e;echo 0 ", returnStdout: true).trim()
println run_tests 

sẽ được thực hiện thành công với set -eecho 0các lệnh nếu gmake testthất bại (các thử nghiệm của bạn không thành công), trong khi đoạn mã sau bị cắt:

String run_tests = sh(script: "set +e && cd ~/development/tests/ && gmake test && set -e && echo 0 ", returnStdout: true).trim()
println run_tests 

một chút sai và các lệnh set -eecho 0in && gmake test && set -e && echo 0sẽ bị bỏ qua, với println run_testscâu lệnh, bởi vì thất bại gmake testsẽ hủy bỏ việc xây dựng jenkins. Giải pháp thay thế bạn có thể chuyển sang returnStatus:true, nhưng sau đó bạn sẽ bỏ lỡ đầu ra từ lệnh của bạn.


0

Câu trả lời này là đúng, nhưng nó không chỉ định || exit 0hoặc || trueđi vào bên trong lệnh shell . Đây là một ví dụ đầy đủ hơn:

sh "adb uninstall com.example.app || true"

Ở trên sẽ hoạt động, nhưng sau đây sẽ thất bại:

sh "adb uninstall com.example.app" || true

Có lẽ nó rõ ràng với người khác, nhưng tôi đã lãng phí rất nhiều thời gian trước khi tôi nhận ra điều này.

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.