From 88f8bcc0862621c96d23a552eaa2a8fed010440f Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 20 Apr 2024 23:44:15 +0900 Subject: feat(blog/content): new post /posts/2024-04-21/pipefail-option-in-gitlab-ci-cd/ --- .../pipefail-option-in-gitlab-ci-cd.ndoc | 180 +++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.ndoc (limited to 'vhosts/blog/content/posts/2024-04-21') diff --git a/vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.ndoc b/vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.ndoc new file mode 100644 index 00000000..028cbbb0 --- /dev/null +++ b/vhosts/blog/content/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd.ndoc @@ -0,0 +1,180 @@ +--- +[article] +uuid = "a4c326a6-5ffe-450c-abf2-45833c5efb6a" +title = "【GitLab】 GitLab CI/CD 上での bash/sh は pipefail が有効になっている" +description = "GitLab CI/CD で bash/sh スクリプトを動かすと、pipefail オプションが有効になった状態で実行される。" +tags = [ + "ci-cd", + "gitlab", +] + +[[article.revisions]] +date = "2022-11-17" +remark = "デジタルサーカス株式会社の社内記事として公開" +isInternal = true + +[[article.revisions]] +date = "2024-04-21" +remark = "ブログ記事として一般公開" +--- +
+ + この記事は、2022-11-17 にデジタルサーカス株式会社 の社内 Qiita Team に公開された記事をベースに、加筆修正して一般公開したものです。 + +

+ ハマったのでメモ。 +

+
+ 前提 +
+ GitLab CI/CD について +

+ GitLab CI/CD では、Docker executor を用いて任意の Docker image 上でスクリプトを走らせることができる。 +

+

+ 例: +

+ + + +

+ ここで、script に指定したコマンドが失敗する (exit status が 0 以外になる) と、即座に実行が停止され、ジョブは失敗する。 +

+

+ では、次のようなケースだとどうなるか。 +

+ + + +

+ 失敗するコマンドをパイプに接続した。通常 Bash では、パイプの最後のコマンドの exit code が全体の exit code になる。 +

+
+
+ pipefail オプションについて +

+ 前述したようなケースにおいて、途中で失敗したときに全体を失敗させるには、pipefail オプションを有効にする。 +

+ + + +

+ こうすると、パイプ全体が失敗するようになる。 + この設定は、デフォルトだと off になっている。 +

+
+
+
+ 発生した問題 +

+ 次のような GitLab CI/CD ジョブが失敗してしまった。 +

+ + + +

+ grep コマンドは、パターンにマッチする行が一行もなかったとき、exit code 1 を返す。よって、pipefail が on になっていると、このジョブは失敗する。 + 現在の pipefail がどうなっているか確かめるため set +o で全オプションを出力させたところ、pipefail が on になっていた。 +

+

+ しかし、先述したように Bash における pipefail のデフォルト値は off のはずだ。 + 実際に、ローカルで alpine:latest を動かしてみたところ、 +

+ + + +

+ 確かに pipefail は無効になっている。 +

+

+ なぜスクリプト内で set -o pipefail しているわけでもないのに pipefail が on になっているのか。 +

+
+
+ どこで pipefail が on になるか +

+ .gitlab-ci.yml で明示的には書いていないので、GitLab Runner (GitLab CI/CD のスクリプトを実行するプログラム) が勝手に追加しているに違いない。 + そう仮説を立てて GitLab Runner のリポジトリ を調査したところ、ソースコード中の以下の箇所set -o pipefail していることが判明した (コメントは筆者による)。 +

+ + /dev/null; then set -o pipefail; fi; set -o errexit\n") + ]]> + +
+
+ どのように解決するか +

+ 通常の Bash スクリプトを書く場合と同様に、pipefail が on になっていては困る場所だけ off にしてやればよい。 +

+ + + +
+
+ 備考 +

+ なお、上述した実装ファイルは shells/bash.go だが、alpine:latest の例でもそうであったように、シェルが sh である場合にも適用される。 +

+
+
-- cgit v1.2.3-70-g09d2