Windows 上の Jenkins から curl で TypeTalk API を叩いてメッセージを送信するまでの道のり
Windows 上の Jenkins はとにかく罠が多い…。
Windows 上の Jenkins から「シェルスクリプトの実行」で curl
コマンドを実行し、TypeTalk API を叩いて任意のメッセージを投稿してみようと思った。それがかなりつまづいたのでまとめる。
TypeTalk API の叩き方
今回は、シェルスクリプトから TypeTalk API を叩いて、任意のメッセージを投稿させようと思った。
予め TypeTalk のトピックの設定から、Client ID と Client Secret という認証用の文字列を発行しておく。
そして、TypeTalk API の公式リファレンスを基にすれば、以下の2行のコードでメッセージが投稿できるはずだった…。
# アクセストークンを発行し、jq で curl のレスポンスをパースして変数に入れる
access_token=$(curl https://typetalk.com/oauth2/access_token -X POST --data-urlencode "client_id=【Client ID】" -d "client_secret=【Client Secret】" -d "grant_type=client_credentials" -d "scope=topic.post" | jq -r .access_token)
# メッセージ「こんにちは!」を指定のトピックに投稿する
curl https://typetalk.com/api/v1/topics/【トピック ID】 -X POST -H "Authorization:Bearer $access_token" --data-urlencode "message=こんにちは!"
Mac のターミナルで上の2行を実行すると、正常にメッセージが送信できた。しかし、Windows GitBash から実行すると、投稿メッセージが文字化けしてしまっていた。
GitBash の curl
で POST すると日本語が文字化けする
最初は Mac の curl
と Windows GitBash 付属の curl
で仕様が違うのか?と思ったが、どうもそうでもないみたいだ。curl
は --verbose
(or -v
) オプションを渡すと通信内容の詳細が表示されるので見てみたが、解決の糸口には繋がらず…。
色々調べてみると、近しいポイントでつまづいていそうな人は見かけるが、そのものズバリな答えがなくて結構困った。
-
参考 : Windowsコマンドラインからcurlで全角文字を送るには - 日本語による質問・議論はこちら - Discuss the Elastic Stack
-
コマンドラインから直接送るのは難しいということですね。
-
-
参考 : 【無理】WindowsのコンソールでUnicodeを使いたい
-
chcp 65001
でコマンドプロンプトの設定が Unicode (UTF8?) になるので、これでirb
とかpry
で日本語を表示できる。
でも、日本語入力は出来ない。IME がアクティブにならないし、コピペならできるそうだけど、自分の環境ではコピペさえも不可能。
無理です。
-
-
参考 : bluemix - Watson Text to Speechで日本語をPOSTで送る方法を教えて下さい - スタック・オーバーフロー
とりあえず、1つ目の文献で触れられていた @file
オプションを利用したやり方にしてみた。メッセージはシェルスクリプト内で用意したいので、リダイレクトで msg.txt
というファイルに書き込むことにした。
access_token=$(curl https://typetalk.com/oauth2/access_token -X POST --data-urlencode "client_id=【Client ID】" -d "client_secret=【Client Secret】" -d "grant_type=client_credentials" -d "scope=topic.post" | jq -r .access_token)
echo 'message=こんにちは!' > msg.txt
curl https://typetalk.com/api/v1/topics/【トピック ID】 -X POST -H "Authorization:Bearer $access_token" -d @msg.txt
-d
じゃなくて --data-urlencode
か?とか思ったけどダメ。そこで chcp
のことを思い出して msg.txt
を Notepad++ で開いてみると、このファイルは Shift-JIS 形式になっていた。どうもリダイレクトのエンコーディングはコードページに左右されるっぽい。
$ chcp.com
でコードページを確認してみると、932
≒ Shift-JIS と返ってきた (英語版の Windows を使ったりしていると 932
ではなく 437
= 英語 が返される)。そこで GitBash 上で $ chcp.com 65001
と実行して、UTF-8 形式に変更してみてから msg.txt
を生成してみた。コマンドプロンプトなら拡張子 .com
を省略できるが、GitBash では .com
を省略できないので chcp
ではなく chcp.com
と叩く。
chcp.com 65001
access_token=$(curl https://typetalk.com/oauth2/access_token -X POST --data-urlencode "client_id=【Client ID】" -d "client_secret=【Client Secret】" -d "grant_type=client_credentials" -d "scope=topic.post" | jq -r .access_token)
echo 'message=こんにちは!' > msg.txt
curl https://typetalk.com/api/v1/topics/【トピック ID】 -X POST -H "Authorization:Bearer $access_token" -d @msg.txt
こうすると、msg.txt
を BOM なし UTF-8 で出力できた。GitBash 上で叩いた限りだとコレで日本語が送信できた。
やった〜じゃあコレを Jenkins のジョブに書き込んでやろう〜と思って実行してみると、なぜか Jenkins を経由して GitBash を使った場合だと文字化けする…。一体何故…。
Jenkins 上で実行する GitBash のリダイレクトは Java の実行環境に左右される
Jenkins の「シェルスクリプトの実行」経由で GitBash を利用すると、なんか環境が変なところがある。今回色々調べてみると、どうも Java 製である Jenkins が、Java の実行環境に影響されて、シェルスクリプトの実行内容にも影響が出ているっぽいことが分かった。
- 参考 : Windows環境でJenkinsのコンソール出力が文字化けした - 文系seの備忘録
- 参考 : ブログズミ: Jenkins Cppcheck ソースファイルの文字化けを解消する
- 参考 : Jenkinsのコンソール出力が読みづらくなっている人向けのメモ
- 参考 : 或るプログラマの一生 » Windows 上で Jenkins のジョブを走らせるといろいろ文字化けする
このサイトにならって、Jenkins のシステムプロパティで file.encoding
と sun.jnu.encoding
を見てみると、Shift-JIS (MS932) となっていた。そこでコチラのページを参考に、
システム環境変数で
JAVA_TOOL_OPTIONS
を-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
に設定し、Jenkins のサービスを再起動
してみたところ、chcp.com 65001
をせずとも、msg.txt
生成時のリダイレクトが UTF-8 (BOM なし) に切り替わり、文字化けせず curl
で POST できた。
access_token=$(curl https://typetalk.com/oauth2/access_token -X POST --data-urlencode "client_id=【Client ID】" -d "client_secret=【Client Secret】" -d "grant_type=client_credentials" -d "scope=topic.post" | jq -r .access_token)
echo 'message=こんにちは!' > msg.txt
curl https://typetalk.com/api/v1/topics/【トピック ID】 -X POST -H "Authorization:Bearer $access_token" -d @msg.txt
シェルスクリプトはコレだけで良くなった。よしよし、じゃあ次はメッセージに改行を入れてみよう…と思ってまたハマった。
投稿メッセージに改行を入れるには
改行をメッセージに入れたくて、message=ほげ\nふが
と msg.txt
に書き込んでみたが、うまく改行されなかった。ログを見ると、curl
の送信時に \
記号が \\
とエスケープされているようだった。&br;
という Backlog 記法も試してみたけどダメだった。
解決法を探ったところ、実際に改行を入れたファイルを用意して、-d
ではなく --data-binary
オプションで送ると良いそうだ。
改行を含んだテキストファイルを吐くには、cat
によるヒアドキュメントを利用する。
access_token=$(curl https://typetalk.com/oauth2/access_token -X POST --data-urlencode "client_id=【Client ID】" -d "client_secret=【Client Secret】" -d "grant_type=client_credentials" -d "scope=topic.post" | jq -r .access_token)
cat << EOF > msg.txt
message=ほげ
ふが
EOF
curl https://typetalk.com/api/v1/topics/【トピック ID】 -X POST -H "Authorization:Bearer $access_token" --data-binary @msg.txt
こうすると、msg.txt
内で実際に改行されている部分が \n
としてそのまま送信されるので、投稿メッセージにコメントを含めることができた。
あと、message=
部分のイコール記号の意味合いでバッティングするものと思われるが、本文中に半角イコール =
があると、それ以降の文字列が送られない。どうもうまくエスケープできなかったので、本文で使用するイコール記号は全角のみ使用することにした。いいやり方ないだろうか…。
以上
今回やったことは、結局「エンコーディングを UTF-8 に揃える」ということだ。Jenkins 起動時に -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
オプションを与え、もし必要なら chcp.com 65001
コマンドを利用して、UTF-8 な msg.txt
を用意できれば良い。
あとはこのファイルを curl
POST する時に --data-binary
を使って渡してやれば上手くいった。
「GitBash on Jenkins on Windows」な環境はエンコーディングとコードページの罠がキツいのう…。
- その他参考 : Windows版curlでJSONをPOSTする際に困った話