Jenkinsのパラメータに特殊文字が含まれている状態でシェルに適切に渡すには

詰まったのでメモ


ユースケースと課題

例えばPipelineのパラメータとして以下のプレースホルダーに作成したいファイル名を記載するとき


ファイル名にホワイトスペースやシングルクオートといった特殊文字を入れたくなるときがある。

Jenkins内で扱うだけならまだ良いが、シェルスクリプトコマンドライン引数などとして投げるとき、シェルがうまくパースしてくれない場合がある。非常に詰まって時間を費やしてしまったので後進のためのメモ。

解決策

Groovyファイル側で一度パラメータをエスケープしてあげ、その後シェル側でエスケープシークエンスを評価する。 今回は簡単のためホワイトスペースとシングルクオートのみを考慮に入れる。

まずJenkins側でパラメータ内の特殊文字エスケープする。これはシェル側で正しくエスケープシークエンスを評価できるようにするための処理。

EscapedOutput="${SomeParam.replaceAll(/('| )/, /\\$0/)}"

次にコマンドライン引数のオプションとしてシェルに投げる。このとき直接Jenkinsの変数を展開してしまうと、エスケープシーケンスを正しく評価できない。 例えば、 echo 'test\'test'のような場合、最後のシングルクオートが閉じられていないと解釈される 。

そこで$'文字列'のように記載してあげる必要がある(因みにこれはbashでのみ利用可能でshでは利用可能でないことに注意)。 ただGroovy側では$特殊文字なので\$のように書いてエスケープしてあげる必要がある。あくまでもシェルに解釈してもらいたい。

注意点として、shコマンドはGroovyではbashではなく無印shを呼び出してしまうので、

sh "#!/bin/bash \n" + "./script.sh --outputname \$'${EscapedOutput}'"

のように明示的にbashで実行してあげる必要がある。

これでスクリプト内で適切に変数が展開される。


最終的なコードは以下のような感じ。

stages {
        stage('build') {
            environment {
                EscapedParam="${SomeParam.replaceAll(/('| )/, /\\$0/)}"
            }

            steps {
                sh "#!/bin/bash \n" + "./script.sh --outputname \$'${EscapedOutput}'"
            }
        }
}

続く。。。