set -o pipefail とは何か? pipeline の失敗を捉える
set -o pipefail は、pipeline 内のいずれかのコマンドが失敗すると、最後の 1 つだけでなく失敗の終了コードを返すようにし、静かな失敗のギャップを塞ぎます。
シェルの pipeline は通常、最後のコマンドの終了コードだけを報告するので、連鎖の早い段階でのクラッシュが完全に隠される可能性があります。set -o pipefail はこれを修正します。pipe のいずれかのステージが失敗すると、pipeline 全体が失敗します。それは CI スクリプトを信頼できるものにする set -euo pipefail 三兄弟の 3 つ目です。
pipefail が行うこと
デフォルトでは pipeline の終了コードは最後のコマンドのものです。pipefail を使うと、pipeline の終了コードは失敗した最も右のコマンドのものになるので、連鎖内のあらゆる失敗が浮かび上がります。
隠れた失敗の問題
generate_report | tee report.txt を考えてみましょう。generate_report がクラッシュしても tee が成功すると、pipeline は 0 で終了しステップが pass し、空または部分的なレポートが残ります。pipefail はそのクラッシュを捉えます。
set -e との連携
- set -e 単独では pipeline 内の失敗を捉えない。
- pipefail は、いずれかの失敗で pipeline が非ゼロを返すようにする。
- 両者を合わせると、失敗した pipe ステージが実際にスクリプトを停止させる。
三兄弟に含まれる理由
set -euo pipefail の組み合わせは 3 つの大きなギャップをカバーします。エラーで停止すること、未設定変数でエラーにすること、pipeline の失敗を捉えることです。pipefail は最も忘れられがちな部分であり、最も厄介なバグを隠すものです。
CI における pipefail
CI スクリプトは pipe を多用します。ログの解析、出力の整形、ツール間のデータの受け渡しです。pipefail がないと、早い段階での失敗が成功として通ってしまいます。それを有効にすると、pipe のいずれかのステージが失敗したときにステップが失敗するようになります。
managed runner での信頼できる pipe
Latchkey runner では、ステップに set -o pipefail を追加すると、pipeline 内の壊れたステージが確実に job を失敗させます。それは、静かでデバッグしにくい pipeline の失敗というカテゴリ全体を取り除きます。
重要なポイント
- set -o pipefail は、pipeline 内のいずれかのコマンドが失敗すると pipeline を失敗させます。
- それがないと、最後のコマンドの終了コードだけが数えられ、失敗を隠します。
- 信頼できる CI スクリプトの標準である
set -euo pipefailを完成させます。