【入門編】レガシーからモダンへ:Jenkins Pipelineの宣言的構文への段階的移行計画と書き換えパターン – バージョン管理・CI/CD活用バイブル

こんにちは!開発現場の裏側で、日々コードとパイプラインの海を泳いでいる先輩エンジニアです。

今回は、多くの開発チームが一度は頭を悩ませる「Jenkinsのレガシーな世界からの脱却」についてお話しします。

「昔からあるGroovyスクリプト書きまくりのJenkinsfile、誰も修正したくない……」
「エラーが出てもどこでコケているのかパッと見でわからない……」

そんな絶望的な状況、ありませんか?
これを放置すると、CI/CDパイプラインは技術的負債の塊となり、デプロイのたびにチーム全体のストレスがマッハで上昇します。

今回は、古いScripted Pipeline(スクリプト型)から、モダンなDeclarative Pipeline(宣言型)へ安全かつ確実に移行するためのロードマップを、具体的なコードの書き換えパターン付きで優しく、徹底的に解説していきます。これをマスターすれば、毎日のビルド監視が劇的に楽になりますよ!

—

1. なぜ「宣言的(Declarative)」へ移行すべきなのか?

まず前提として、なぜ今のJenkinsfileを書き換える必要があるのか、その本質を整理しておきましょう。

Jenkinsには大きく分けて2つのパイプライン構文があります。

1. Scripted Pipeline(スクリプト型・レガシー)

  • Groovyのフルパワーが使えるため何でもできる反面、「ただのプログラム」になりがちで、コードの可読性が最悪になりやすい。

2. Declarative Pipeline(宣言型・モダン)

  • 構造が厳密に定義されており、「何をするか(What)」だけを書くスタイル。UIでの可視化、エラー検知、並列処理の記述などが圧倒的にエレガント。

宣言的構文に移行する最大のメリットは「誰が書いても同じ品質の、安全なパイプラインになること」です。文法エラーを事前に検知しやすく、JenkinsのビジュアルUI(Blue OceanやStage View)とも抜群の相性を誇ります。

—

2. 移行のための事前チェックリスト

闇雲に書き換えるのはバグの元です。以下のステップで安全に移行を進めましょう。

  • [ ] 現状の把握: 動いているScripted Pipelineの全ステージを洗い出す。
  • [ ] プラグインの更新: Jenkins本体および主要なプラグイン(Pipeline系など)を最新版にしておく。
  • [ ] ブランチ戦略の策定: `main`や`master`に直接反映するのではなく、検証用の別ブランチ(例: `feature/migrate-jenkinsfile`)を切る。
  • [ ] 並行稼働の準備: リポジトリ内に一時的に別名のファイル(例: `Jenkinsfile.declarative`)を置き、Multibranch Pipelineでテストビルドできるようにする。

—

3. 実践!書き換えマッピングパターン集

それでは、実際のコードをどう書き換えるのか、よくあるパターンを見ていきましょう。

パターンA:全体の構造と基本変数の定義

まずは骨組みの変更です。Scriptedでは自由なGroovy変数定義が乱立しがちですが、Declarativeでは`pipeline { }`ブロックの中に厳格にルールを置きます。

❌ レガシー(Scripted Pipeline)

// 自由度が高すぎて、何がどこで定義されているか追いづらい
node {
def myVersion = “1.0.0”

stage(‘Build’) {
echo “Building version ${myVersion}”
sh ‘mvn clean package’
}
}

⭕️ モダン(Declarative Pipeline)

// 構造が明確。どこに何を書くべきかが一目瞭然
pipeline {
agent any // 実行環境の指定

environment {
MY_VERSION = “1.0.0” // 環境変数はここで一元管理
}

stages {
stage(‘Build’) {
steps {
echo “Building version ${env.MY_VERSION}”
sh ‘mvn clean package’
}
}
}
}

—

パターンB:エラーハンドリングと後始末(try-catch vs post)

ビルドが失敗したときの通知や、成果物のクリーンアップ(後始末)の書き方も大きく変わります。Scriptedでは`try-catch-finally`の海に溺れがちですが、Declarativeには強力な`post`セクションが用意されています。

❌ レガシー(Scripted Pipeline)

node {
try {
stage(‘Test’) {
sh ‘npm test’
}
} catch (err) {
currentBuild.result = ‘FAILURE’
echo “Failed: ${err}”
throw err
} finally {
stage(‘Cleanup’) {
cleanWs() // ワークスペースの削除
}
}
}

⭕️ モダン(Declarative Pipeline)

pipeline {
agent any

stages {
stage(‘Test’) {
steps {
sh ‘npm test’
}
}
}

// 成功・失敗・常時実行などの条件ごとにスッキリ記述できる
post {
always {
cleanWs() // どんな結果であれ必ず実行される
}
failure {
echo “ビルドが失敗しました!担当者にメンションを送ります。”
// Slack通知などの処理をここに書く
}
}
}

この `post` セクションの導入により、コード量が減るだけでなく、「例外処理を書き忘れてワークスペースがゴミだらけになる」という事故を防げます。

—

パターンC:条件分岐とタイムアウト制御

「特定のブランチのときだけデプロイしたい」「テストが無限ループしたときに強制終了したい」という要件も、宣言的構文ならスマートに書けます。

❌ レガシー(Scripted Pipeline)

node {
stage(‘Deploy’) {
if (env.BRANCH_NAME == ‘main’) {
timeout(time: 10, unit: ‘MINUTES’) {
sh ‘./deploy.sh’
}
}
}
}

⭕️ モダン(Declarative Pipeline)

pipeline {
agent any

stages {
stage(‘Deploy’) {
// ステージ単位、あるいはステップ単位で条件やタイムアウトを制御
when {
branch ‘main’
}
options {
timeout(time: 10, unit: ‘MINUTES’)
}
steps {
sh ‘./deploy.sh’
}
}
}
}

`when` ディレクティブを使うことで、「このステージはどの条件のときに走るのか」が視覚的にも直感的にわかるようになります。

—

4. 段階的なテスト運用法:一気に本番へ入れてはいけない

移行作業で最もやってはいけないのが、「ある日突然、メインブランチのJenkinsfileを書き換えて全体 अप्लाई(適用)する」ことです。CI/CDパイプラインはチームのライフライン。止めると全員の仕事が止まります。

以下のステップで安全にテスト運用を行ってください。

1. 別名ファイルでのトライ

  • リポジトリに `Jenkinsfile.v2` などの名前でDeclarative版を作成します。

2. Jenkins側でのジョブ個別作成

  • JenkinsのUIから、一時的な検証用ジョブ(Pipeline job)を作成し、スクリプトパスに `Jenkinsfile.v2` を指定して手動ビルドします。

3. 挙動の比較

  • 古いパイプラインと新しいパイプラインで、成果物やテスト結果に差異がないことを入念に確認します。

4. リネームと切り替え

  • 動作確認ができたら、古い `Jenkinsfile` を削除(またはリネームしてバックアップ)し、`Jenkinsfile.v2` を正式な `Jenkinsfile` にリネームしてマージします。

—

おわりに:レガシーからの脱却は、チームの未来への投資

いかがでしょうか?
Scripted PipelineからDeclarative Pipelineへの移行は、最初は少し億劫に感じるかもしれません。しかし、一度モダンな書き方に移行してしまえば、コードの保守性は劇的に向上し、新しいメンバーがジョインした際もスムーズにCI/CDの仕組みを理解できるようになります。

「これをマスターすれば、毎日の作業が劇的に楽になりますよ!」

技術的負債を一つずつ解消し、快適でモダンな開発ライフを手に入れましょう。あなたのパイプラインの旅が、実りあるものになることを応援しています!

タイトルとURLをコピーしました