Search Results for ""

言語ガイド: Java

このガイドでは、CircleCI で Gradle を使用して Java アプリケーションをビルドする方法について説明します。

概要

お急ぎの場合は、後述の設定ファイルの例をプロジェクトのルート ディレクトリにある .circleci/config.yml に貼り付け、ビルドを開始してください。

ここでは、以下を前提としています。

  • Gradle を使用している (Maven 版のガイドはこちら)
  • Java 11 を使用している
  • Spring Framework を使用している (このプロジェクトは Spring Initializr を使用して生成されています)
  • アプリケーションをオールインワン uberjar として配布できる

設定ファイルの例

version: 2 # CircleCI 2.0 を使用します
jobs: # 一連のステップ
  build:
    # 並列処理が必要ない場合は削除します
    parallelism: 2
    environment:
      # OOM (メモリ不足) エラーを回避するように JVM と Gradle を構成します
      _JAVA_OPTIONS: "-Xmx3g"
      GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2"
    docker: # Docker でステップを実行します

      - image: circleci/openjdk:11.0.3-jdk-stretch # このイメージをすべての `steps` が実行されるプライマリ コンテナとして使用します
      - image: circleci/postgres:12-alpine
        environment:
          POSTGRES_USER: postgres
          POSTGRES_DB: circle_test
    steps: # 実行可能コマンドの集合
      - checkout # ソース コードを作業ディレクトリにチェックアウトします
      # 依存関係キャッシュについては https://circleci.com/ja/docs/2.0/caching/ をお読みください
      - restore_cache:
          key: v1-gradle-wrapper-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}
      - restore_cache:
          key: v1-gradle-cache-{{ checksum "build.gradle" }}
      - run:
          name: テストの並列実行 # https://circleci.com/ja/docs/2.0/parallelism-faster-jobs/ を参照してください
          # テストを並列に実行しない場合は、代わりに「./gradlew test」を使用します
          command: |
            cd src/test/java
            # このノードで実行する必要があるテストのクラス名のリストを取得します
            CLASSNAMES=$(circleci tests glob "**/*.java" \
              | cut -c 1- | sed 's@/@.@g' \
              | sed 's/.\{5\}$//' \
              | circleci tests split --split-by=timings --timings-type=classname)
            cd ../../..
            # 引数を「./gradlew test」にフォーマットします
            GRADLE_ARGS=$(echo $CLASSNAMES | awk '{for (i=1; i<=NF; i++) print "--tests",$i}')
            echo "Prepared arguments for Gradle: $GRADLE_ARGS"
            ./gradlew test $GRADLE_ARGS
      - save_cache:
          paths:
            - ~/.gradle/wrapper
          key: v1-gradle-wrapper-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}
      - save_cache:
          paths:
            - ~/.gradle/caches
          key: v1-gradle-cache-{{ checksum "build.gradle" }}
      - store_test_results:
      # テスト サマリー (https://circleci.com/ja/docs/2.0/collect-test-data/) に表示するテスト結果をアップロードします
          path: build/test-results/test
      - store_artifacts: # アーティファクト (https://circleci.com/ja/docs/2.0/artifacts/) に表示するテスト結果をアップロードします
          path: build/test-results/test
          when: always
      - run:
          name: JAR の収集
          command: |
            # 他のノードでは以下をスキップします
            if [ "$CIRCLE_NODE_INDEX" == 0 ]; then
              ./gradlew assemble
            fi
      # JAR は最初のビルド コンテナでのみ収集されるため、他のすべてのビルド コンテナでは build/libs が空になります
      - store_artifacts:
          path: build/libs
      # デプロイ例については https://circleci.com/ja/docs/2.0/deployment-integrations/ を参照してください
workflows:
  version: 2
  workflow:
    jobs:
    - build 

コードの取得

上記は Java デモ アプリケーションの設定ファイルの抜粋です。このデモ アプリケーションには、https://github.com/CircleCI-Public/circleci-demo-java-spring からアクセスできます。

ご自身でコード全体を確認する場合は、GitHub でプロジェクトをフォークし、ローカル マシンにダウンロードします。 CircleCI で [Add Projects (プロジェクトの追加)] ページにアクセスし、プロジェクトの横にある [Build Project (プロジェクトのビルド)] ボタンをクリックします。 最後に .circleci/config.yml の内容をすべて削除します。

これで config.yml を最初からビルドする準備ができました。

設定ファイルの詳細

常にバージョンの指定から始めます。

version: 2

次に、jobs キーを記述します。 1 つひとつのジョブが、ビルド、テスト、デプロイのプロセス内の各段階を表します。 このサンプル アプリケーションでは 1 つの build ジョブのみが必要なので、他の要素はそのキーの下に置きます。

version: 2
jobs:
  build:
    # 並列処理が必要ない場合は削除します
    parallelism: 2
    environment:
      # OOM (メモリ不足) エラーを回避するように JVM と Gradle を構成します
      _JAVA_OPTIONS: "-Xmx3g"
      GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2"

テストを並列に実行してジョブを高速化するために、オプションの parallelism 値を 2 に指定しています。

また、environment キーを使用して、OOM エラーを回避するように JVM と Gradle を構成しています。

version: 2
...
    docker:
      - image: circleci/openjdk:11.0.3-jdk-stretch
      - image: circleci/postgres:12-alpine
        environment:
          POSTGRES_USER: postgres
          POSTGRES_DB: circle_test

バージョン 11.0.3-jdk-stretch のタグが付いた CircleCI OpenJDK コンビニエンス イメージを使用します。

この build ジョブ内にいくつかの steps を追加します。

コードベースで作業できるように、最初に checkout を置きます。

次に、Gradle ラッパーと依存関係のキャッシュをプル ダウンします (存在する場合)。 初回実行時、または gradle/wrapper/gradle-wrapper.propertiesbuild.gradle を変更した場合、これは実行されません。

...
    steps:

      - checkout
      - restore_cache:
          key: v1-gradle-wrapper-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}
      - restore_cache:
          key: v1-gradle-cache-{{ checksum "build.gradle" }}

追加の引数を使用して ./gradlew test を実行します。これにより、キャッシュが空だった場合、Gradle やプロジェクトの依存関係がプル ダウンされ、テストのサブセットが各ビルド コンテナで実行されます。 各並列ビルド コンテナで実行されるテストのサブセットは、組み込みの circleci tests split コマンドを使用して決定されます。

...
    steps:

      - run:
          name: Run tests in parallel # https://circleci.com/ja/docs/2.0/parallelism-faster-jobs/ を参照してください
          # テストを並列に実行しない場合は、代わりに「./gradlew test」を使用します
          command: |
            cd src/test/java
            # このノードで実行する必要があるテストのクラス名のリストを取得します
            CLASSNAMES=$(circleci tests glob "**/*.java" \
              | cut -c 1- | sed 's@/@.@g' \
              | sed 's/.\{5\}$//' \
              | circleci tests split --split-by=timings --timings-type=classname)
            cd ../../..
            # 引数を「./gradlew test」にフォーマットします
            GRADLE_ARGS=$(echo $CLASSNAMES | awk '{for (i=1; i<=NF; i++) print "--tests",$i}')
            echo "Prepared arguments for Gradle: $GRADLE_ARGS"
            ./gradlew test $GRADLE_ARGS

次回の処理を高速化するために、save_cache ステップを使用して Gradle ラッパーと依存関係を保存します。

...

      - save_cache:
          paths:
            - ~/.gradle/wrapper
          key: v1-gradle-wrapper-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}
      - save_cache:
          paths:
            - ~/.gradle/caches
          key: v1-gradle-cache-{{ checksum "build.gradle" }}

続けて、CircleCI ダッシュボードにテスト メタデータを表示できるように、store_test_resultsbuild/test-results/test ディレクトリから JUnit テスト メタデータを取得してアップロードします。 また、テスト メタデータを調べる必要がある場合は、store_artifacts を介してテスト メタデータをアーティファクトとしてアップロードします。

...

      - store_test_results:
          path: build/test-results/test
      - store_artifacts:
          path: build/test-results/test
          when: always

./gradlew assemble コマンドを使用して、”uberjar” ファイルを作成します。このファイルには、コンパイルされたアプリケーションと共にそのアプリケーションのすべての依存関係が含まれます。 uberjar のコピーは 1 つだけあればよいので、これは、並列に実行しているすべてのビルド コンテナではなく最初のビルド コンテナでだけ実行されます。

その後、store_artifacts ステップを使用して、uberjar をアーティファクトとして保存します。 そこから、これを目的の継続的デプロイ スキームに結び付けることができます。

...

      - run:
          name: Assemble JAR
          command: |
            # 他のノードでは以下をスキップします
            if [ "$CIRCLE_NODE_INDEX" == 0 ]; then
              ./gradlew assemble
            fi
      # JAR は最初のビルド コンテナでのみ収集されるため、他のすべてのビルド コンテナでは build/libs が空になります
      - store_artifacts:
          path: build/libs

最後に、ワークフロー内の唯一のジョブとして build ジョブによって実行される workflow というワークフローを定義します。

...
workflows:
  version: 2
  workflow:
    jobs:

    - build

完了です。 これで Gradle と Spring を使用する Java アプリケーション用に CircleCI をセットアップできました。

関連項目