AWS CodeBuild で AWS Lambda(java) を使用してビルドを実行してみた

記事タイトルとURLをコピーする

こんにちは、末廣です。

弊社山本のブログで紹介されている 「CodeBuild で AWS Lambda のランタイムを使用したビルドが可能になりました」を実際に Lambda を使用して Java プログラムをビルドしてみたのでブログにまとめます。

blog.serverworks.co.jp

ビルドツールとして Maven / Gradle それぞれ試しています。

maven.apache.org

gradle.org

Gradle ロゴのぞうさん?がかわいいですね。

構成

入力ソースは CodeCommit リポジトリとし、ビルド出力アーティファクトを S3 へ格納します。

構成

Maven プロジェクトのビルド

まずは Maven でのビルドを紹介します。 公式ドキュメントのチュートリアル「コンソールを使用した AWS CodeBuild の開始方法」のソースコードと手順を参考にしていますが、このチュートリアルはビルドコンピューティングが EC2 なので Lambda にてビルドされるよう変更して進めています。

ビルドソース

入力ソースの CodeCommit リポジトリとその階層構造は以下図のようになっています。

Maven プロジェクトのソース CodeCommit

Maven プロジェクトの階層構造

ソースコード(MessageUtil.java)

チュートリアルのソースコードを一部変更したものになります。 コードの内容としては、メッセージ出力に関するクラス MessageUtilがメッセージを単に標準出力するメソッドと、挨拶形式で標準出力するメソッドを持っています。

public class MessageUtil {
  private String message;

  public MessageUtil(String message) {
    this.message = message;
  }

  public String printMessage() {
    System.out.println(message);
    return message;
  }

  public String salutationMessage() {
    message = "Hi!" + message;
    System.out.println(message);
    return message;
  }

  public static void main(String[] args) {
    System.out.print("Java version: ");
    System.out.println(System.getProperty("java.version"));

    System.out.print("Os name: ");
    System.out.println(System.getProperty("os.name"));

    MessageUtil messageUtil = new MessageUtil("Sue");
    messageUtil.printMessage();
    messageUtil.salutationMessage();
  }
}

15行目から本サンプルのソースコードへ main 関数を追加しています。(パブリックスタティックヴォイドメイン…) main 関数内で実行している Java のバージョンと OS 名をシステムプロパティから取得し、おまけにクラスのインスタンス化・各メソッドの実行も行いました。

テストコード(TestMessageUtil.java)

テストコードはビルド時に pom.xml の指示に従って、テストコードを実行します。

docs.aws.amazon.com

ソースコードと同じくチュートリアルのテストコードを使用しています。 JUnit の import 先のみ変更し(理由は後ほどに記載します)、assertEquals による JUnit テストを実行しています。

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class TestMessageUtil {

  String message = "Robert";
  MessageUtil messageUtil = new MessageUtil(message);

  @Test
  public void testPrintMessage() {
    System.out.println("Inside testPrintMessage()");
    assertEquals(message,messageUtil.printMessage());
  }

  @Test
  public void testSalutationMessage() {
    System.out.println("Inside testSalutationMessage()");
    message = "Hi!" + "Robert";
    assertEquals(message,messageUtil.salutationMessage());
  }
}

ビルド定義ファイル(pom.xml)

Maven プロジェクトの設定ファイルを チュートリアルの POM ファイルからmaven-compiler-pluginでバージョンを指定しない設定にして作成しました。 後ほど実行結果よりmvn install でどのバージョンが使用されるか確認してみましょう。

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.example</groupId>
  <artifactId>messageUtil</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>
  <name>Message Utility Java Sample App</name>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.10.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

ビルド仕様ファイル(buildspec.yml)

build セクションでは、Maven のビルドとしてmvn installを実行し、jar ファイルを作成します。また、java -version では、ビルド環境の Java バージョンを確認しています。 post_build セクションでは、クラスファイルの実行としてjava -classpath ./target/classes/ MessageUtil を実行し、実際に動作している Java のバージョンを確認できるようにしています。 また、Maven の jar ファイルは target 配下に作成されるため、アーティファクトはその jar ファイルのみを指定しています。

version: 0.2

phases:
  pre_build:
    commands:
      - echo Nothing to do in the pre_build phase...
  build:
    commands:
      - echo Build started on `date`
      - mvn install
      - java -version
  post_build:
    commands:
      - echo Build completed on `date`
      - java -classpath ./target/classes/ MessageUtil
artifacts:
  files:
    - target/*

CodeBuild 環境

CodeBuild の環境はコンピューティングをもちろん Lambda に、イメージの Java バージョンを最新の Amazon Corretto21 としています。

CodeBuild の環境

ビルドログ

実際にビルドしたログ結果を確認します。

Maven ビルドログその1

〜〜ログが長いので中略〜〜

1312 行目から JUnit ライブラリがダウンロードされ JUnit テストがビルド時に実行されています。

Maven ビルドログその2

ビルド成功後、buildspec.yml に記載した Java バージョンの確認コマンドを実行します。 ビルド環境の Java バージョンと実際にプログラムが動作している Java バージョン が CodeBuild 環境に選択した Correto21 になっていることが確認できました。 おまけに追加したメソッドの実行も行われています。

Maven ビルドログその3

ビルド出力アーティファクト

s3://xxxx/java-trial/target/ 配下へ messageUtil-1.0.jarアーカイブファイルとして格納されていました。

アーティファクトファイル

なお、jar ファイルを実行するには別途マニフェストファイルを作成した上で実行、またはビルド時にマニフェストファイルが作成されるよう pom.xml を設定する必要があります。

参考:https://docs.oracle.com/javase/jp/1.5.0/guide/jar/jar.html

Gradle プロジェクトのビルド

次に Gradle プロジェクトの場合のビルドを試してみます。

ビルドソース

入力ソースの CodeCommit リポジトリとその階層構造は以下図のようになっています。

Gradle プロジェクトのソース CodeCommit

Gradle プロジェクトの階層構造

また、

  • ソースコード(MessageUtil.java)
  • テストコード(TestMessageUtil.java)

は Maven 検証時と同じものを使用しています。

ビルド定義ファイル(build.gradle)

Gradle プロジェクトのビルド定義ファイルになります。 AWS SDK for Java の Gradle プロジェクトを参考にし、JUnit のバージョンとテストとして実行する形で今回に沿うよう指定しています。

plugins {
    id 'application'
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}

application {
    mainClass = 'MessageUtil'
}

tasks.named('test') {
    useJUnitPlatform()
}

ビルド仕様ファイル(buildspec.yml)

build セクションでは、Gradle のビルドとしてgradle buildを実行し、jar ファイルを作成します。Maven 同様java -versionにて、ビルド環境の Java バージョンを確認しています。 post_build セクションではjava -classpath ./target/classes/ MessageUtil を実行し、実際に動作している Java のバージョンを確認できるようにしています。 また、Gradle の jar ファイルは build/libs 配下にできるため、アーティファクトはその jar ファイルのみを指定しています。

version: 0.2

phases:
  pre_build:
    commands:
      - echo Nothing to do in the pre_build phase...
  build:
    commands:
      - echo Build started on `date`
      - gradle build
      - java -version
  post_build:
    commands:
      - echo Build completed on `date`
      - java -classpath ./build/classes/java/main MessageUtil
artifacts:
  files:
    - build/libs/*

CodeBuild 環境

CodeBuild の環境についても Maven ビルド時と同様コンピューティングを Lambda 、イメージの Java バージョンを Amazon Corretto21 にしています。

ビルドログ

Gradle のビルドログもみていきます。こちらは Maven よりかなり短かったです。

Gradle ビルドログその1

こちらもビルド環境の Java バージョンと実際にプログラムが動作している Java バージョン が CodeBuild 環境に選択した Correto21 になっていることが確認できました。

Gradle ビルドログその2

ビルド出力アーティファクト

s3://xxxx/java-trial-gradle/build/libs/配下へ java-trial-gradle.jarアーカイブファイルとして格納されました。

アーティファクトファイル

今回 jar ファイル名を指定していないため、プロジェクトによって違いますが、pom.xml、build.gradle へそれぞれ定義することで任意の名前を付与することも可能です。

補足:JUnit テストエラーについて

ここで JUnit のバージョンを4から5に変更した理由として、検証時に Gradle でエラーが発生したことが関係しています。 今回は build.gradle ファイルには何もバージョンを指定していないため、Gradle 8.2.1 が使用されています。 おそらくこれが JUnit テストのバージョンと合わないため失敗したと思われますが、バージョンを上げることで無事テストが成功しました。 Maven の方は JUnit のバージョンが低い状態でもビルド、テストの両方が成功していました。

JUnit テストエラー

まとめ

山本さんのブログにも記載ありますが、「ビルドを素早く安く同時に多数実行したい」といった本ブログの「してみた」のような検証時にはもってこいの環境だと感じました。また本ブログ執筆により、大学時代には Java を学習していたもののビルドツールについてあまり知識がなかったため改めて学ぶよいきっかけとなりました。

末廣 満希(執筆記事の一覧)

2022年新卒入社です。ここに何かかっこいい一言を書くことができるエンジニアになれるように頑張ります。