☕️

GitHub Packagesへネイティブイメージをデプロイする

2021/09/20に公開

概要

GitHub ActionsでネイティブイメージをビルドしてGitHub Packagesへデプロイする方法を記載します。

要点は次の通りです。

コード例は次のリポジトリです。

Native Image Maven Pluginの設定

まずネイティブビルドの設定です。
Native Image Maven Pluginを追加してpackageフェーズでnative-imageゴールが動くようにしています。

<plugin>
    <groupId>org.graalvm.nativeimage</groupId>
    <artifactId>native-image-maven-plugin</artifactId>
    <version>${graalvm.version}</version>
    <executions>
        <execution>
            <goals>
                <goal>native-image</goal>
            </goals>
            <phase>package</phase>
        </execution>
    </executions>
    <configuration>
        <imageName>${project.artifactId}</imageName>
        <mainClass>com.example.App</mainClass>
        <buildArgs>
            --no-fallback
        </buildArgs>
    </configuration>
</plugin>

deploy:deploy-fileのための設定

次にApache Maven Deploy Pluginの設定です。

fileへネイティブイメージのパスを設定します。

urlはデプロイ先となるMavenリポジトリ(今回はGitHub Packages)のURLです。
これはdistributionManagementから読み取ってくれるんじゃないのか?と思ったんですが、そうでもないんですかね。
よくわかっていないです。

それからclassifierpackagingにそれぞれbinexeを設定していますが、これで良いのかは実はよくわかっていません。
特にpackagingは決まった値がいくつかあるはずで、exeなんて値はないはず……でもこれでデプロイできたのでとりあえずまあいいかという感じです。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-deploy-plugin</artifactId>
    <configuration>
        <repositoryId>github</repositoryId>
        <file>${project.build.directory}/${project.artifactId}</file>
        <url>${repository.url}</url>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <classifier>bin</classifier>
        <packaging>exe</packaging>
    </configuration>
</plugin>

なお、distributionManagementの設定はGitHub PackagesへJARをデプロイするを参考にしてください。

GitHub Actionsのビルドスクリプト

jobs.<job_id>.steps以下を説明します。

まずはactions/checkoutでソースコードをチェックアウトします。

それからDeLaGuardo/setup-graalvmでGraalVMをセットアップします。
さらにguコマンドでnative-imageコマンドをインストールしています。

最後にmvn packageしてdeploy:deploy-fileでデプロイしています。

- uses: actions/checkout@v2
- uses: DeLaGuardo/setup-graalvm@4.0
with:
    graalvm: 21.2.0
    java: java11
- name: Install native-image command
run: |
    gu install native-image
    native-image --version
- name: Cache local Maven repository
uses: actions/cache@v2
with:
    path: ~/.m2/repository
    key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
    restore-keys: |
    ${{ runner.os }}-maven-
- name: Maven build and deploy
run: |
    GITHUB_USERNAME=backpaper0 GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} mvn -B -DskipTests package deploy:deploy-file -s settings.xml

これでgit pushすればGitHub Actionsによってビルドが行われてネイティブイメージがGitHub PackagesのMavenリポジトリへデプロイされます。

デプロイされたネイティブイメージの動作確認

ubuntu-latestでビルドしたのでUbuntuで動作確認してみます。
私はMacを使っているのでDockerを利用しようと思います。

まずコード例のリポジトリからネイティブイメージをダウンロードします。

それから実行権限を付けます。

chmod +x native-deploy-demo-1.0-20210920.091209-1-bin.exe


DockerでUbuntuを起動してネイティブイメージを実行します。

docker run --rm -v $PWD:/workspace ubuntu \
  ./workspace/native-deploy-demo-1.0-20210920.091209-1-bin.exe

Hello Worldと出力されたらOKです。

アーカイブにしてデプロイする

本記事の公開後にまきさんが教えてくれたのですが、アーカイブにしてデプロイすると便利そうです。
あと、-bin.exeみたいな違和感があるsuffixにしなくてもよくなりますね。

そういうわけでpom.xmlを修正して試してみたのですが、なぜかGitHub Packagesへデプロイしようとするとアーカイブファイルはデプロイされているのに409 Conflictが発生してビルドエラーとなりました……
ローカルに立てたSonatype Nexusへはエラーなくデプロイできるのですが……

ネイティブイメージをデプロイできたことで当面の目的は達成できているため、この課題は置いておきます。
それでまた気が向いたらトラブルシュートしようと思います。

以上です。

Discussion