Azure Pipelinesでは様々なPipeline用のタスクが用意されています。例えばMaven taskだったり、 Docker taskだったりです。
この中で柔軟性が高いのはCommand Line taskや Bask taskでしょう。
例えばCommand Line taskでは、以下のようにしてスクリプトを自由に記述できます。
stages: - stage: Lint jobs: - job: textlint displayName: Textlint container: lint_cli steps: - script: | npx textlint '**/*.md'
問題
しかしここで問題が出てきました。なんとscript
で指定したスクリプトが異常終了しても、パイプラインが失敗にならない。
Starting: CmdLine ============================================================================== Task : Command line Description : Run a command line script using Bash on Linux and macOS and cmd.exe on Windows Version : 2.182.0 Author : Microsoft Corporation Help : https://docs.microsoft.com/azure/devops/pipelines/tasks/utility/command-line (snip) /__w/1/s/guide/how_to/azure/azure_pipelines_ci.md 5:15 ✓ error Azure Pipeline => Azure Pipelines (snip) ✖ 14 problems (14 errors, 0 warnings) ✓ 8 fixable problems. Try to run: $ textlint --fix [file] Finishing: CmdLine
解決法
set -e
しましょう。
シェルスクリプトではset -eu
しようというのがよく言われますが、これがAzure Pipelinesでも当てはまります。
Azure Pipelinesでは、script
で指定した一連のコマンドを1つのファイルにした上で、当該ファイルを実行する形になっています。
このためset -e
を明示的に記述しない限り、一連のスクリプトは途中で止まることなく全て実行されます。
おそらく最後のコマンドが正常終了する限り、Azure Pipelines上のビルドジョブはFailしないでしょう。
$ man bash (snip) -e Exit immediately if a simple command (see SHELL GRAMMAR above) exits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of a && or || list, or if the command's return value is being inverted via !. A trap on ERR, if set, is executed before the shell exits.
というわけで、Azure Pipelinesでスクリプトを書くときはset -e
しましょう。
stages: - stage: Lint jobs: - job: textlint displayName: Textlint container: lint_cli steps: - script: | set -eu npx textlint '**/*.md'
✖ 14 problems (14 errors, 0 warnings) ✓ 8 fixable problems. Try to run: $ textlint --fix [file] ##[error]Bash exited with code '1'. Finishing: CmdLine