生産性向上ブログ

継続的な生産性向上を目指すエンジニアのためのブログ

Jenkins Pipeline でパラメータ(環境変数)でビルドするブランチを指定する

小ネタメモです。

Jenkins のジョブを作るときに、パラメータを受け取ってその値を環境変数としてブランチに指定することがあると思います。

f:id:miya-jan:20170712224729p:plainf:id:miya-jan:20170712224740p:plain

↑こんな感じですね。

しかし、この方法を Jenkins Pipeline で行うとエラーが出ます。

hudson.plugins.git.GitException: Command "git fetch --tags --progress origin +refs/heads/${BRANCH_NAME}:refs/remotes/origin/${BRANCH_NAME} --prune" returned status code 128:
stdout: 
stderr: fatal: Couldn't find remote ref refs/heads/${BRANCH_NAME}

どうやら環境変数が解決されないようなので調べてみると、SCM の設定で “Lightweight checkout” を無効にしないといけないようです。(関連issue

f:id:miya-jan:20170712224812p:plain

“Lightweight checkout” は Jenkinsfile を master で取得するときにリポジトリ全体をチェックアウトせずに Jenkinsfile だけ取得する仕組みのようです。なので、無効にすると master 側のディスク使用量などが若干増加すると予想されます。

Jenkins の Multibranch Pipeline で Jenkinsfile のパスを指定できるようになった件

Pipeline Multibranch Plugin の 2.15 で、表題の通り Jenkinsfile のパスを指定できるようになったのでメモです。

[JENKINS-34561] Allow to detect different Jenkinsfile filenames - Jenkins JIRA

f:id:miya-jan:20170607222602p:plain

これまではリポジトリ直下の Jenkinsfile で決め打ちだったのが、↑の画像のようにパスを指定できるようになっています。

この改善は、Multibranch Pipeline だけでなく、Organization Folder にも適用されています。ちなみに、通常のシンプルな Pipeline ジョブはこれまでもパスを指定できました。

この変更によって、

  • 1リポジトリで複数の Multibranch Pipeline を作成したい
  • リポジトリのルートには決まったファイル以外を置けない・置きたくない

という場合に嬉しそうです。他のCIサービスだと1リポジトリ1パイプラインで設定ファイルの名前が決め打ちであることが多いので、おもしろい取り組みです。

一方で、1つの Multibranch Pipeline につき1ファイルしかジョブとして認識できないのは以前と変わらずでした。Organization Folder では複数のパスを Project Recognizaers として指定できるのですが、その場合でも1リポジトリ1ファイルまでしか認識されません。

つまり、例えばモノレポ方式で1リポジトリにたくさんのプロジェクトがあってそれぞれに Jenkinsfile を用意する場合、複数の Multibranch Pipeline を作成するしかなく、ちょっと面倒です。

[JENKINS-35415] Multiple branch projects per repository with different recognizers - Jenkins JIRA

この件については、↑に別 issue として登録されています。CloudBees 社が提供する Jenkins Enterprise ではすでに機能としてあるようです。

UI 面での複雑さはありそうですが、個人的には Organization Folder 1つで完結してほしいので、今後に期待です。

『カエルを食べてしまえ! 新版』読了

カエルを食べてしまえ!  新版

カエルを食べてしまえ! 新版

『カエルを食べてしまえ! 新版』を読み終えたので、簡単に感想とかのまとめです。

ちょっと変わったタイトルですが、内容を一言でまとめると、最も重要で厄介なこと(=カエル)を最優先で実行しましょう、という本です。量は少なく、1〜2時間くらいあれば読めてしまうくらいでした。

もう少し掘り下げると、以下のような内容が書かれています。

  • 目標をはっきりさせる
  • きちんと計画を立てる
  • 重要な上位20%のことに集中する
  • 大きく複雑なことでも一歩ずつ進めていく
  • 自分にしかできないことを見つける
  • 時間の浪費をやめる
  • 切迫感を持つ
  • 仕事を中断しない

まっとうな内容でしたし、個人的にはできていない部分がけっこうあったので、いろいろ考え直すきっかけになる本でした。「1日のタスクは前日に計画しておくと翌日までにアイディアが浮かんで仕事が捗る」とか、「自己鍛錬とは、自分がすべきことを好きであろうとなかろうとできるようになること」とか、なるほどなと思う部分は多かったです。

一方で、科学的な検証とかはあまりない本です。実際にこれを実現した人とそうでない人で、なにが違ってくるのかといった説明はほとんどないです。また、「切迫感を持とう」とか、「やりとげるまでは他のことに気を取られないようにしよう」みたいな部分は、精神論に近いものを少し感じ、それを実現するために具体的にどうすればいいんだろうと疑問のまま終わる説明も多かったです。

筆者はビジネス寄りの人のようなので、そこまで理詰めな内容ではなく、どちらかというと精神面重視の啓発書という感想です。ただ、文章は読みやすく、「原則」という形で気をつけるべき内容もきれいにまとまっているので、気軽に読める本だと思います。誰にでもオススメというほどではないですが、なんとなく仕事に集中できていないと感じている人とかには習慣を考え直すきっかけになるかもしれません。

『レガシーソフトウェア改善ガイド』読了

レガシーソフトウェア改善ガイド

レガシーソフトウェア改善ガイド

『レガシーソフトウェア改善ガイド』を読み終えたので、簡単に感想とかまとめておきます。

タイトルから、『レガシーコード改善ガイド』を連想されると思いますが、特に続編ではなく、そもそも作者が違います。良し悪しはさておき、まぎらわしいことは間違いないです。

『レガシーコード改善ガイド』では、「テストのないコードはレガシーコード」という定義だったのに対して、『レガシーソフトウェア改善ガイド』では、「保守または拡張が困難」なものであればなんでもレガシーと定義しています。そして、コードだけではなく、それ以外のプロジェクト全体についてもかなりの量を割いて記述しています。本が扱う内容は、おおまかに以下のようなものがあります。

  • レガシープロジェクトの定義、性質、なぜレガシーになるのか
  • 改善のための指標、その計測方法
  • チームとのコミュニケーション
  • リファクタリングとレガシーコードのテスト
  • リアーキテクチャリング、リライト
  • 開発環境構築やデプロイの自動化

正直、1冊の本によくここまで詰め込んだなという幅広い内容です。

1つのトピックに対して深掘りする本ではないですが、そこまで多くない分量の中で実戦的かつ本質的な部分がよくまとまっていると思います。自分含め、世の中の開発者がレガシーコードに対して感じていることをうまく言語化してくれていると感じました。新しい知識が得られる本ではないかもしれませんが、レガシープロジェクトと戦うための引き出しを一通り確認したいときや、チームでレガシーな部分にどのように立ち向かっていくか認識を揃えるときにとても役に立つ本なのではないでしょうか。

個人的に取り入れたいなと思ったのは、個々の変更レベルでのレビューだけではなく、定期的にコードベース全体のレビューをチームで行うという部分です。普段放置されがちな部分は、いざというときになってから問題が顕在化しがちです。また、全体としての設計やコード品質の一貫性という部分は意識的に改善しないと、実装当初は問題なくても、ゆるやかにレガシー化していくでしょう。なにより、定期的な習慣として改善の姿勢を明確化することは、組織の文化づくりとしてとても良さそうに思いました。

エンジニアは、多かれ少なかれレガシーなプロジェクトに関わるものです。それどころか、大半のエンジニアは新規プロジェクトよりもレガシー化した後のプロジェクトに関わる時間の方が圧倒的に長いでしょう。そう考えるとこの本は、エンジニア人生を豊かにしてくれる一冊と言えます。

Jenkins 2.0 (5): Jenkinsfileをコマンドラインからlintする

Jenkins 2.0のDeclarative Pipelineには、Jenkinsfileをlintするための仕組みが用意されています。

curlとssh

プラグインのWikiには、sshとcurlそれぞれでJenkinsをlintするための方法が紹介されています。以下は引用です。

# ssh方式
ssh -p [sshd port on master] [Jenkins master hostname] declarative-linter < Jenkinsfile

# curl方式
curl -X POST -H `curl 'JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'` -F "jenkinsfile=<Jenkinsfile" JENKINS_URL/pipeline-model-converter/validate

ssh方式の場合は、「Jenkinsの管理」→「システム設定」→「SSHサーバー」からsshdポートを指定しておくのがいいでしょう。

curl方式の -H `curl 'JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'` のサブコマンド部分は、「グローバルセキュリティの設定」→「CSRF対策」→「Default Crumb Issuer」が有効になっている場合のみ必要です。Jenkins 2.0ではデフォルトで有効になっているはずです。さらに、ログイン前ユーザーにread権限がない場合は、 -u <username>:<password> を追加するなどして認証情報を与えないと 403 Forbidden でエラーになってしまいます。

jflint

上記の方式だと、日常的に叩くにはちょっとコマンドが複雑です。なので、jflintというコマンドラインツールをnpmパッケージとして作成しました。

$ npm install -g jflint

でインストールできます。

$ jflint -j [Jenkins master hostname] Jenkinsfile

でlintが走ります。内部的には、curl方式でJenkinsにリクエストを投げているだけですが、curlコマンドを直に叩くよりは楽だと思います。

さらに、 -j [Jenkins master hostname] 部分も毎回書くのが面倒なので、設定ファイルから自動で読み込めるようにしています。

{
  "jenkinsUrl": "[Jenkins master hostname]"
}

のようなjsonを、 .jflintrc という名前のファイルとして、現在のディレクトリからファイルシステムルートまでの間か、ホームディレクトリに保存してください。すると、

$ jflint Jenkinsfile

だけでlintできるようになります。

まとめ

JenkinsfileをCLI上からlintする方法と、入力を簡単にするためのnpmパッケージ、jflintについて紹介しました。Jenkinsfileをいじるときに手軽にlintできるの便利なので、ぜひ使ってみてください。なにか不具合や質問などあれば、issue立てるなり、なんらかの手段で自分に連絡するなりしていただけると助かります。