SpringBoot 2.7 to 3.0 自動化(Gradle版)

SpringBoot 2.7から3.0のアップデート情報を以下の記事でまとめましたが、
実業務では少しでも手間を省きたいですよね…!

SpringBoot 2.7 to 3.0 アップデートまとめ

この記事ではGradleを対象にアップデートの自動化方法をまとめます。

自動でできること

この記事の手順を実施することで自動的に更新できることは以下の通りです。

  • SpringBoot関連プラグインの更新
  • Javaバージョンの更新
  • 依存ライブラリの更新
  • javax → jakartaの移行
  • spring.factoriesの移行
  • プロパティの移行

更新手順

OpenRewriteを使用して自動更新を行います。

▼OpenRewriteについてもっと知りたい方はこちら

【OpenRewrite】コードを自動で一括変更

1. 定義ファイルを作成

プロジェクト直下に rewrite.ymlを作成します。

---
type: specs.openrewrite.org/v1beta/recipe
name: custom.SpringBootMigration
displayName: springboot migration to 3.0 from 2.7
recipeList:
  # プラグインの更新
  - org.openrewrite.gradle.plugins.UpgradePluginVersion:
      pluginIdPattern: org.springframework.boot
      newVersion: "3.0.0"
  - org.openrewrite.gradle.plugins.UpgradePluginVersion:
      pluginIdPattern: io.spring.dependency-management
      newVersion: "1.1.0"
  # Jaraバージョンの更新
  - org.openrewrite.gradle.ChangeJavaCompatibility:
      newVersion: "17"
      compatibilityType: "source"
  - org.openrewrite.gradle.ChangeJavaCompatibility:
      newVersion: "17"
      compatibilityType: "target"
  # 依存ライブラリの更新(更新に必要なライブラリごとに定義が必要)
  - org.openrewrite.gradle.ChangeDependencyVersion:
      groupId: org.mybatis.spring.boot
      artifactId: mybatis-spring-boot-starter
      newVersion: 3.0.0
  # javax → jakartaの更新
  - org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta
  # spring.factoriesの移行
  - org.openrewrite.java.spring.boot2.MoveAutoConfigurationToImportsFile
  # プロパティの移行
  - org.openrewrite.java.spring.boot3.SpringBootProperties_3_0_0

2. プロジェクトにOpenRewriteを導入

build.gradleに変更を加えます。

plugins {
    ...
    // OpenRewriteプラグインを追加する
    id("org.openrewrite.rewrite") version("5.32.0")
}

...

repositories {
    // mavenCentralが必要
    mavenCentral()
}

dependencies {
    ...
    // 書換に必要な依存を追加
    rewrite("org.openrewrite.recipe:rewrite-spring:4.30.0")
    rewrite("org.openrewrite:rewrite-gradle:7.33.0")
}

// 実行するレシピを定義
rewrite {
    // 先ほど定義した独自のレシピ
    activeRecipe('custom.SpringBootMigration')
}

3. テスト実行

rewriteDryRunタスクを実行します。

./gradlew rewriteDryRun

build/reports/rewrite/rewrite.patchに変更内容が出力されるので、
内容に問題がないか確認します。

※想定外の変更があればここで立ち止まって一部手動更新に切り替える。

4. 実行

rewriteRunタスクを実行します。

./gradlew rewriteRun

5. Completed !

これで自動更新の手順は終わりです!

「この手順をやればSpringBoot3.0への更新がすべて自動化される」ということではないので
手動でのチェックもしておきましょう。

おまけ ~shepherd~

shepherdというツールを使うとgithubのリポジトリに一斉にPRをあげることができます。

【リポジトリ管理を楽に!】shepherdを使ってみた

スクリプトもOSコマンドで自由にかけるのでOpenRewriteで対応しきれない部分も対応できます!

以下、自分の知っている限りをすべて自動で更新するための定義ファイルです!

id: migrate/springboot-3.0
title: "migrate springboot to 3.0 from 2.7."
adapter:
  type: github
  search_type: <repositories or code>
  search_query: <適宜設定してください>
hooks:
  should_migrate:
    - find . -name build.gradle | xargs -I{} grep -e "org.springframework.boot.*version.*2\.7\." {}
  apply:
    # gradle version upgrade
    - |
      # 非推奨な記述を検知
      ./gradlew help --warning-mode=fail
      if [ $? -ne 0 ]; then
        exit 1
      fi
      # gradleのversionをupgrade
      ./gradlew wrapper --gradle-version 7.6.1
    # prepare OpenRewrite
    - |
      # 変数定義
      build_gradle_file=./build.gradle
      sed_cmd=gsed
      
      # ファイル追加
      rm rewrite.yml
      curl 'https://raw.githubusercontent.com/rhirabay/my-projects/main/shepherd/migrations/springboot/3.0/gradle/rewrite.yml' -o rewrite.yml
      # プラグイン追加
      grep 'org.openrewrite.rewrite' ${build_gradle_file}
      if [ $? -ne 0 ]; then
        plugin_block_start=$(${sed_cmd} -n '/plugins {/=' ${build_gradle_file})
        plugin_block_end=$(${sed_cmd} -n '/}/=' ${build_gradle_file} | awk '{ if ($0 >= '$plugin_block_start') print $0 }' | head -1)
        ${sed_cmd} -i -e "${plugin_block_end}i \ \ \ \ id('org.openrewrite.rewrite') version('5.32.0')" ${build_gradle_file}
      fi
      # 依存を追加
      dependencies_block_start=$(${sed_cmd} -n '/dependencies {/=' ${build_gradle_file})
      dependencies_block_end=$(${sed_cmd} -n '/}/=' ${build_gradle_file} | awk '{ if ($0 >= '$dependencies_block_start') print $0 }' | head -1)      
      grep 'rewrite-spring' ${build_gradle_file}
      if [ $? -ne 0 ]; then
        ${sed_cmd} -i -e "${dependencies_block_end}i \ \ \ \ rewrite('org.openrewrite.recipe:rewrite-spring:+')" ${build_gradle_file}
        dependencies_block_end=$((${dependencies_block_end} + 1))
      fi
      grep 'rewrite-gradle' ${build_gradle_file}
      if [ $? -ne 0 ]; then
        ${sed_cmd} -i -e "${dependencies_block_end}i \ \ \ \ rewrite('org.openrewrite:rewrite-gradle:+')" ${build_gradle_file}
        dependencies_block_end=$((${dependencies_block_end} + 1))
      fi
      # rewriteブロックを追加
      grep 'rewrite {' ${build_gradle_file}
      if [ $? -ne 0 ]; then
        echo '' >> ${build_gradle_file}
        echo 'rewrite {' >> ${build_gradle_file}
        echo '}' >> ${build_gradle_file}
      fi
      rewrite_block_start=$(sed -n '/rewrite {/=' ${build_gradle_file})
      rewrite_block_end=$(sed -n '/}/=' ${build_gradle_file} | awk '{ if ($0 >= '$rewrite_block_start') print $0 }' | head -1)
      if [ ! $(grep 'springboot.migration2.7to3.0' ${build_gradle_file}) ]; then
        ${sed_cmd} -i -e "${rewrite_block_end}i \ \ \ \ activeRecipe('springboot.migration2.7to3.0')" ${build_gradle_file}
      fi
    # Rewrite実行
    - ./gradlew rewriteRun
    # SpringCloudのversion変更
    - |
      # 変数定義
      build_gradle_file="./build.gradle"
      spring_cloud_version=2022.0.1
      sed_cmd=gsed
      
      grep -e "set(.springCloudVersion." ${build_gradle_file}
      if [ $? -eq 0 ]; then
        # 行を特定
        spring_cloud_version_line=$(${sed_cmd} -n -e '/set(.springCloudVersion./=' ${build_gradle_file})
        ${sed_cmd} -i "${spring_cloud_version_line}c \ \ \ \ set('springCloudVersion', '${spring_cloud_version}')" ${build_gradle_file}
      fi
    # sleuthをmicrometerに切り替え
    - |
      # 変数定義
      build_gradle_file="./build.gradle"
      sed_cmd=gsed
      
      grep "spring-cloud-starter-sleuth" ${build_gradle_file}
      if [ $? -eq 0 ]; then
        ${sed_cmd} -i -e "/spring-cloud-starter-sleuth/a \ \ \ \ implementation\ 'io.micrometer:micrometer-tracing-bridge-brave'" ${build_gradle_file}
        ${sed_cmd} -i -e "/spring-cloud-starter-sleuth/a \ \ \ \ implementation\ 'io.micrometer:micrometer-tracing'" ${build_gradle_file}
        ${sed_cmd} -i "/spring-cloud-starter-sleuth/d" ${build_gradle_file}
      fi
    # httpclientをhttpclient5に切り替え
    - |
      # 変数定義
      build_gradle_file="./build.gradle"
      sed_cmd=gsed
      
      ${sed_cmd} -i -e "s/org.apache.httpcomponents:httpclient[^\"']*/org.apache.httpcomponents.client5:httpclient5/" ${build_gradle_file}

  # PRメッセージを生成(echo等で標準出力)
  pr_message: |
    echo 'this is migration sample.'

この定義で実際に作成したPRがこちら!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です