command substitutionとは何か?出力を値として使う
command substitutionはコマンドを実行してその出力に置き換え、あるコマンドの結果を別のコマンド内の値として使えるようにします。
あるコマンドの出力を別のコマンドの入力や引数として必要とすることがよくあります。現在のGitのcommit、今日の日付、queryの結果などです。command substitutionはまさにそれを行います。コマンドを実行し、その出力を周囲の行に挿入します。CIスクリプトはtag、path、version文字列を計算するためにこれに常に依存します。
command substitutionとは何か
これはコマンドの標準出力をキャプチャし、その場に置き換えます。現代的な形式は$(command)で、古い形式はbacktickを使います。出力は行が実行される前に式を置き換えます。
簡単な例
TAG=$(git rev-parse --short HEAD)と書くと、Gitコマンドを実行してその出力をTAGに格納します。その後"$TAG"を使って、buildやimageにそれが由来するcommitでラベルを付けられます。
なぜbacktickより$()を優先するか
$()はきれいにネストできますが、backtickはネストが厄介です。- 長い行で読みやすくなります。
$()内のクォートのルールがより予測可能です。
結果をクォートする
"$(cmd)"のように常にsubstitutionをクォートし、出力に空白や改行が含まれるときにそれを損なわないようにします。クォートしないと、shellが出力を空白で分割し、微妙なバグを引き起こします。
CIにおけるcommand substitution
pipelineはこれを使って値を導出します。imageのtag用のcommit SHA、artifact名用のtimestamp、ファイルからのversionなどです。コマンドはsubshellで実行されるため、exit codeを確認しない限り、内部の失敗が見逃される可能性があることに注意してください。
マネージドrunnerでの値の計算
Latchkeyのrunnerでは、command substitutionによってステップが値を一度計算して再利用できます。特にset -eのもとでは、結果をクォートし内部コマンドが成功したことを確認して、失敗したsubstitutionが空のデータを下流に送らないようにしてください。
重要なポイント
- command substitutionは
$(...)を介してコマンドをその出力に置き換えます。 - backtickより
$()を優先し、常に結果をクォートします。 - CIはコマンドの出力からtag、version、pathを計算するためにこれを使います。