JenkinsのスクリプトをPowershellにしてみての考察

enishのJenkinsではpowershellを多く利用しています。
もともとはPipeline(groovy)での実装を始めていたのですが、偉い人から「ローカルでもビルドスクリプト動くようにして」と言われちゃったので、Powershellにしてみました。

やっとそこそこ上手くいったのでそれの振り返り記事になります。

経緯

当時Jenkinsのビルドプロセスをgitで管理したい,スクリプト化したいと言う要望がありました。
Jenkins2が入ってすぐだったので当然初期型のPipelineを試しました。
その頃のPipelineはDeclarative Pipelineなんてものはまだ存在せず、バグもてんこ盛りでした。
特にUnityとの相性が悪く気がつくとジョブがゾンビ化する始末でした。

上述の問題や冒頭の要求があったためpowershellでビルドスクリプトを書き直すことにしました。

なぜPowershellを選択したのか

Powershellが使いたかったからです!!!

一応他にも

  1. Windows10以降なら環境をインストールする必要がない
  2. Macでも簡単に動かせるようになる
  3. いわゆるimportや外部ライブラリを使用しなくてもそこそこ色々できる
  4. 恐らく破壊的仕様変更はほぼないだろうという期待

あたりを期待して選びました。

shで書くという拷問のような作業はしたくなかった。
憲法にも犯罪に因る処罰の場合を除いては、その意に反する苦役に服させられない。
と書いてあるのでこれは正しい労働者の権利のはず…

こういう経緯でpowershellをびました。

結果

スクリプトをgitで管理できるなどの結果は出たのですが、それ以外にも副次的メリット・デメリットが色々と出てきました。

Powershellにしてよかった点

  1. 環境依存がほぼない
  2. ライブラリを追加する必要がほぼない
  3. スクリプトの呼び出しフォーマットが統一できる
  4. シェル言語なのでJenkinsという用途に合う
  5. 個人的に書きやすい

Powershellにして困った点

  1. shのxオプションような今どこまで行ったのかがわかるオプションがない
  2. エラー/例外を起こしてもデフォルトでは素通りしてしまう

その他にスクリプト化したのでJenkinsのプラグインは使用できません。

Powershellにしてよかった点

Powershellにしてよかった点をもう少し深く説明します。

環境依存がない

期待していたとおり環境に依存したりバージョン間の問題はほぼありませんでした。
唯一macとwindowsでUnityを起動する方法が違うための調整だけしましたが、それ以外でpowershellのバージョンが問題になったことはありません。

ライブラリを追加する必要がほぼない

使用しているライブラリはSlackへ投稿するためのライブラリとHockeyAppへアップロードするためのライブラリだけです。どちらもそれぞれのAPIのラッパーです。
これ以外で外部ライブラリが必要になったことはありません。

xmlやJsonのパース,Webへのリクエスト,zipの圧縮などJenkinsで使いたい一通りの機能を基本機能で揃えているのがかなり助かりました。

スクリプトの呼び出しフォーマットが統一できる

Powershellは言語仕様上コマンドの呼び出しが次の形に固定されます。そして引数の受け方も決まっています。


コマンド -引数1 値1  -引数2 値2

そのため、引数の受け取り方を議論するというフェーズを飛ばすことができ、また共有する必要もありません。

シェル言語なのでJenkinsという用途に合う

git pullをしたければ単純に「git pull」と書けばいいだけです。
pythonのos.systemのようなメソッドを呼ぶ必要はありません。
また標準出力へのアウトプットも単純に式を書けば勝手に結果が出力されます。
つまり、Jenkins用のスクリプトとしては記述するフレーズが非常に短くります。

やっぱりこういう用途においてはパイプって便利ですね!

個人的には書きやすい

.Net系の言語なのでC#やUnity系の人には書きやすいしわかりやすいと思います。
他にコマンドがrmやlsのような初見殺しのような省略形でないのが高評価です。

Powershellにして困った点の解説

shellのxオプションような今どこまで実行したのかがわかるオプションがない

Jenkinsのログを見ていると今どのコマンドを実行しているかがわからないことが少し困ります。
Verboseオプションがありますが、明示的にWrite-Verboseしてログを出力していくのでちょっと違うかなという感じがします。

今のところは重要なコマンドの前でそのコマンドをecho(Write-Output)で出力してます。

エラー/例外を起こしてもデフォルトでは素通りしてしまう。

これがpowershellでスクリプトを組むときの最大の問題になります。
powershellはエラーや例外は規定でスキップになります。
各コマンドに-ErrorAction Stopオプションを入れれ止まりますが、それでも使いにくい部分があります。

なので正しくエラートラップしてあげないとエラーになるべきところで正常終了してしまいます。(そしてめっちゃ怒られます)
トラップの方法はtrap節や例外など色々あるのでいい感じにしてあげましょう。

結局の所Powershellどうなのよ

最後の問題に気をつければ十分使えそうな感じはしました。(現在全力で使っています。)
Jenkinsでもビルドしたいけどエンジニア各個人が利用できたらいいなという用途であればいい選択肢だと思いました。(パスの問題とかもないですし本当に環境設定が楽なのが正義ですね!)

もちろん他のジョブと絡んでくるようなジョブ等Jenkinsでだけ動けばいい場合はpipelineジョブがいいと思います。
(今は特に大きなバグもなさそうですし!)
一つpipelineジョブの問題を上げるとすればWorkspaceをJenkinsから参照するのが結構面倒くさい。というくらいでそこを許容できるのならばpipelineスクリプトもどんどん使うといいと思います。(あとCPSとうまく付き合えるなら・・・)