JenkinsでGitのWebhookの情報をシェルの引数として渡すときは"で囲む

# 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`はどんなものかというと、次のようなものになります。
**注意）**値は書き換えました

```text: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形式で整形すると次のようになっています。

```json: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でも使えます。

![Jenkins_ビルドのパラメータ化.png](https://qiita-image-store.s3.amazonaws.com/0/33347/02c5c0c5-dc09-dccf-93e8-f0135be1b1ce.png)


この時`payload`をダブルクォーテーションで囲むようにします。

```groovy:jenkins.groovy
stage("パブリッシュ") {
sh '''export TOOLS_DIR
export payload
hoge="HOGE"

RUNNING=`./fuga.sh "${payload}" ${hoge}`

echo RUNNING'''
}
```

## 出力結果
上述のコードで呼び出される`fuga.sh`は次のコードです。

```sh: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をパースして必要な値だけ渡すようにした方がいいと思います。

ただし、結局必要な値に半角スペースが挟まっているのならダブルクォーテーションで囲む必要はあるので、どうせなら囲んでおいたほうが良いと思います。

[^1]: 設定によります。私はpushの時のみにしていることが多いです。
[^2]: payloadをそのまま受け取って、正規表現で色々と判定しています。