TL;DR
- payloadを引数として渡して外部シェルを呼ぶときには
${payload}
ではなく"${payload}"
にする。
はじめに
GitのWebhookで設定しておくと、Gitにpushがされた時1にJenkinsのJobを走らせることが出来ます。
その時の各種情報はJenkinsのJobではpayload
という名前で取得できます。
このpayload
を外部シェルの引数として渡すときの注意点です。
(外部シェルを呼ぶとき全般に通じる話ですが、今回は私がハマったところということでピンポイントで書いています)
環境
動作環境は以下のとおりです。
- MacBookAir 10.13.2 HighSierra
- GitBucket 4.13.0
- Jenkins 2.101
payload
Gitから渡ってくるpayload
はどんなものかというと、次のようなものになります。
注意)値は書き換えました
'{"pusher":{"name":"","email":"**@**.**"},"sender":{"login":"","email":"**@**.**","type":"**","site_admin":true,"created_at":"20**-**-**T**:**:**Z","url":"http://**/**","html_url":"http://**/**","avatar_url":"http://**/**"}, "ref":"refs/heads/**", "before":"****************************************", "after":"****************************************", "commits":[{"id":"****************************************","message":"hello' world\n","timestamp":"20**-**-**T**:**:**Z","added":[],"removed":[],"modified":["package.json"],"author":{"name":"","email":"**@**.**","date":"20**-**-**T**:**:**Z"},"committer":{"name":"","email":"**@**.**","date":"20**-**-**T**:**:**Z"},"url":"http://**/**"}], "repository":{"name":"**","full_name":"**/**","description":"","watchers":0,"forks":0,"private":true,"default_branch":"**","owner":{"login":"**","email":"**@**","type":"**","site_admin":true,"created_at":"20**-**-**T**:**:**Z","url":"http://**/**","html_url":"http://**/**","avatar_url":"http://**/**"},"forks_count":0,"watchers_count":0,"url":"http://**/**","http_url":"http://**/**","clone_url":"http://**/**","html_url":"http://**/**"}, "compare":"http://**/**", "head_commit":{"id":"****************************************","message":"hello' world\n","timestamp":"20**-**-**T**:**:**Z","added":[],"removed":[],"modified":["package.json"],"author":{"name":"","email":"**@**.**","date":"20**-**-**T**:**:**Z"},"committer":{"name":"","email":"**@**.**","date":"20**-**-**T**:**:**Z"},"url":"http://**/**"}}'
上記のpayload
をjson形式で整形すると次のようになっています。
{
"pusher": {
"name": "",
"email": "**@**.**"
},
"sender": {
"login": "",
"email": "**@**.**",
"type": "**",
"site_admin": true,
"created_at": "20**-**-**T**:**:**Z",
"url": "http://**/**",
"html_url": "http://**/**",
"avatar_url": "http://**/**"
},
"ref": "refs/heads/**",
"before": "****************************************",
"after": "****************************************",
"commits": [
{
"id": "****************************************",
"message": "hello' world\n",
"timestamp": "20**-**-**T**:**:**Z",
"added": [],
"removed": [],
"modified": [
"package.json"
],
"author": {
"name": "",
"email": "**@**.**",
"date": "20**-**-**T**:**:**Z"
},
"committer": {
"name": "",
"email": "**@**.**",
"date": "20**-**-**T**:**:**Z"
},
"url": "http://**/**"
}
],
"repository": {
"name": "**",
"full_name": "**/**",
"description": "",
"watchers": 0,
"forks": 0,
"private": true,
"default_branch": "**",
"owner": {
"login": "**",
"email": "**@**",
"type": "**",
"site_admin": true,
"created_at": "20**-**-**T**:**:**Z",
"url": "http://**/**",
"html_url": "http://**/**",
"avatar_url": "http://**/**"
},
"forks_count": 0,
"watchers_count": 0,
"url": "http://**/**",
"http_url": "http://**/**",
"clone_url": "http://**/**",
"html_url": "http://**/**"
},
"compare": "http://**/**",
"head_commit": {
"id": "****************************************",
"message": "hello' world\n",
"timestamp": "20**-**-**T**:**:**Z",
"added": [],
"removed": [],
"modified": [
"package.json"
],
"author": {
"name": "",
"email": "**@**.**",
"date": "20**-**-**T**:**:**Z"
},
"committer": {
"name": "",
"email": "**@**.**",
"date": "20**-**-**T**:**:**Z"
},
"url": "http://**/**"
}
}
JenkinsのPipelineから外部シェルを呼ぶときの引数で使う
ジョブの方でパラメータとして設定したら、Pipelineでも使えます。
この時payload
をダブルクォーテーションで囲むようにします。
stage("パブリッシュ") {
sh '''export TOOLS_DIR
export payload
hoge="HOGE"
RUNNING=`./fuga.sh "${payload}" ${hoge}`
echo RUNNING'''
}
出力結果
上述のコードで呼び出されるfuga.sh
は次のコードです。
payload=$1
hoge=$2
echo "${payload}"
echo "${hoge}"
payload
が長すぎるので省略しますが、意図したとおりの出力結果になります。
'{"pusher":・・・
HOGE
"(ダブルクォーテーション)で囲まない場合
payload
の途中に半角スペースとかが入っていると、渡される値が変わります。
具体的には、半角スペースの位置で切れて渡ってしまうので、次の様になります。
'{"pusher":・・・
world\n",・・・
上述のpayload
のcommits.message
がhello' world\n
となっており、worldの前で途切れました。
HOGEがほしかったのに、違う値が入ってきてしまいました。
おわりに
個人的な背景としては、昔作ったシェル2を使いまわしたかったのでそのままpayload
を渡しました。
でも、必要な値が決まっているなら、payloadをパースして必要な値だけ渡すようにした方がいいと思います。
ただし、結局必要な値に半角スペースが挟まっているのならダブルクォーテーションで囲む必要はあるので、どうせなら囲んでおいたほうが良いと思います。