cangoxina

生産性向上見習いのブログ的な何かです

GitHub ActionsでGitHub Package RegistryにJavaパッケージを公開する

f:id:korosuke613:20191217235335p:plain

GitHub Actions Advent Calendar 2019 18日目の記事です。

Javaのパッケージ(jar)はMaven Centralにアップするのが主流でした。しかし、GitHub Package Registryがリリースされて、Javaパッケージの公開のハードルが下がったような気がします。

今回は、GitHubにtagをpushすることで、GitHub ActionsでGitHub Package RegistryにJavaパッケージを自動で公開する方法を記します。



仕組み

f:id:korosuke613:20191217235358p:plain

上の画像のような仕組みで、tagをpushしたときのみ、自動でパッケージを公開できるように設定します。*1

環境

以下の環境で検証しました。

  • Java 11
  • Gradle 5.2.1

パッケージをGitHub Actionsで公開する

今回公開するパッケージ

今回公開するパッケージのリポジトリコチラです。

Sampleという簡単なクラスを公開して、別のプロジェクトでMavenやGradleでSampleクラスを使えるようにします*2

f:id:korosuke613:20191217201619p:plain

公開するための設定

settings.gradle

ファイル全体はこちら

artifactIdの設定

rootProject.name = 'publish'

rootProject.nameは公開後、artifactIdになります。

com.github.korosuke613.example.publish:v1.0.1の太字部分です。

build.gradle

GitHub公式のドキュメントを参考にしています。

plugins {
    id 'java'
    id "maven-publish"  // 公開に必要なプラグイン
}

group 'com.github.korosuke613.example'

// GitHub Action上でタグ名がバージョンとなる
version = System.getenv("GRADLE_PUBLISH_VERSION") ?: "1.0-SNAPSHOT"

sourceCompatibility = 11

repositories {
    mavenCentral()
}

// 公開設定
publishing {
    repositories {
        maven {
            name = "GitHubPackages"
            url = uri("https://maven.pkg.github.com/korosuke613/java-plugin-publish-github-example")
            credentials {
                username = System.getenv("GITHUB_PACKAGE_USERNAME")
                password = System.getenv("GITHUB_PACKAGE_TOKEN")
            }
        }
    }
    publications {
        gpr(MavenPublication) {
            from(components.java)
        }
    }
}

ファイル全体はこちら

プラグインの追加

plugins {
    id 'java'
    id "maven-publish"
}

GitHub Package Registryに公開するために、maven-publishプラグインをインストールする必要があります。

groupIdの設定

group 'com.github.korosuke613.example'

groupは公開後、groupIdになります。

com.github.korosuke613.example.publish:v1.0.1の太字部分です。((僕は、groupIdartifactIdをどこで区切れば良いのかいまいちよくわかっていません。だれか教えてください))

versionの設定

version = System.getenv("GRADLE_PUBLISH_VERSION") ?: "1.0-SNAPSHOT"

System.getenv()環境変数を取得できます。versionに取得した環境構築の値を代入するのですが、もし、指定した環境変数がなければ、1.0-SNAPSHOTを代入するようにしています。

GitHub Actionsでワークフローを実行中に、GRADLE_PUBLISH_VERSIONにタグ名を代入します。

versionは公開後、そのままversionになります。

com.github.korosuke613.example.publish:v1.0.1の太字部分です。

公開先と認証情報の設定

publishing {
    repositories {
        maven {
            name = "GitHubPackages"
            url = uri("https://maven.pkg.github.com/korosuke613/java-plugin-publish-github-example")
            credentials {
                username = System.getenv("GITHUB_PACKAGE_USERNAME")
                password = System.getenv("GITHUB_PACKAGE_TOKEN")
            }
        }
    }
    publications {
        gpr(MavenPublication) {
            from(components.java)
        }
    }
}
  • urlにはhttps://maven.pkg.github.com/GitHubユーザ名/リポジトリ名を設定します。
  • usernameにはGitHubユーザ名を設定します。
  • passwordにはGitHubのパーソナルアクセストークンを設定します。(GitHubのパスワードではありません!)もし、自分のPCでgradle publishするなら、パーソナルアクセストークンを作成する必要がありますが、GitHub Actionsでは、secrets.GITHUB_TOKENで代用できるので、パーソナルアクセストークンを改めて作成する必要はありません。

usernamepasswordの設定で使っている環境変数は、GitHub Actionsでワークフローを実行中に設定します。

publish.yaml

GitHub Actionsのワークフローの設定です。

name: Publish

on:
  push:
    tags:
      - v*  # 'v'から始まるタグをpushしたときのみワークフローを実行する

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Set up JDK 11
        uses: actions/setup-java@v1
        with:
          java-version: 11
      - name: Get the tag version  # タグ名を保存する
        id: get_version
        run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
      - name: Publish
        env:
          GITHUB_PACKAGE_USERNAME: korosuke613  # ユーザー名
          GITHUB_PACKAGE_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # トークン
          GRADLE_PUBLISH_VERSION: ${{ steps.get_version.outputs.VERSION }} # タグ名
        run: ./gradlew publish

ファイル全体はこちら

トリガー設定

on:
  push:
    tags:
      - v* 

このワークフローを実行する条件を設定しています。

この設定は、vから始まる名前のtagをpushしたらトリガーするというものになります。この設定をしていることで、無駄にパッケージを公開せずにすみます。

参考

tag名の保存

      - name: Get the tag version
        id: get_version
        run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}

タグ名を保存しています。

こちらのサイトを参考にしました。

パッケージ公開

      - name: Publish
        env:
          GITHUB_PACKAGE_USERNAME: korosuke613 
          GITHUB_PACKAGE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GRADLE_PUBLISH_VERSION: ${{ steps.get_version.outputs.VERSION }} 
        run: ./gradlew publish

実際に./gradlew publishを実行して、GitHub Package Registryにパッケージを公開する設定です。

envブロックでは環境変数を設定することができます。

認証情報

GITHUB_PACKAGE_USERNAMEGITHUB_PACKAGE_TOKENは公開に必要な認証情報となります。(参照)

secrets.GITHUB_TOKENは「GitHub Actionsの代理で認証を受けるために利用できるトーク*3です。GitHub Actions上で参照できるため、GitHub周りの認証で楽できます。

version

GRADLE_PUBLISH_VERSIONは、versionの設定に必要なtag名となります。(参照)

steps.get_version.outputs.VERSIONは、「tag名の保存」で設定したtag名を参照しています。

実際にtagをpushする

実際にtag(v0.0.5)をpushして、Actionsのページに行くと、Publishというワークフローが実行されていることが確認できます。(リンク)*4

f:id:korosuke613:20191217222432p:plain

画像のように、Task :publishが正常に実行されていたら、パッケージがアップロードされているはずです。(リンク)

f:id:korosuke613:20191217222851p:plain

パッケージを利用する

公開したパッケージを利用しましょう。

利用するためのソースコードこちらに上げています。

利用するための設定

build.gradle

plugins {
    id 'java'
}

group 'com.github.korosuke613.example'
version '1.0-SNAPSHOT'

sourceCompatibility = 11

repositories {
    maven {
        name = "GitHubPackages"
        url = uri("https://maven.pkg.github.com/korosuke613/java-plugin-publish-github-example")
        credentials {
            username = System.getenv("GITHUB_PACKAGE_USERNAME")
            password = System.getenv("GITHUB_PACKAGE_TOKEN")
        }
    }
    mavenCentral()
}

dependencies {
    implementation "com.github.korosuke613.example:publish:v1.0.1"
    implementation "com.github.korosuke613:pict4java:v2.0.0"
}

GitHub Package Registryにログインする

repositories {
    maven {
        name = "GitHubPackages"
        url = uri("https://maven.pkg.github.com/korosuke613/java-plugin-publish-github-example")
        credentials {
            username = System.getenv("GITHUB_PACKAGE_USERNAME")
            password = System.getenv("GITHUB_PACKAGE_TOKEN")
        }
    }
    mavenCentral()
}

パッケージを公開したのと同じように、GitHub Package Registryにログインする必要があります。

Publicなリポジトリでパッケージを公開していたとしても、認証作業が必要です。

なぜこういう作りになっているのかはわかりません。実際、GitHub Communityで議論になっています。

github.community

urlには、先ほどと同じようなURLを設定していますが、設定したURLとは別のリポジトリのパッケージも、問題なく利用できたことから、別のリポジトリのURLでも良さそうです。一回認証すれば良いということなのでしょうか。

(ここら辺は僕も良くわかっていないので、だれか教えてください...)

dependenciesに追加

dependencies {
    implementation "com.github.korosuke613.example:publish:v1.0.1"
    implementation "com.github.korosuke613:pict4java:v2.0.0"
}

dependenciesに先ほど公開したパッケージを記述しています。

今回は、<groupId>:<artifactId>:<version>というルールで記述しています。*5

ちなみに、com.github.korosuke613:pict4java:v2.0.0は僕が既に同じ方法で公開している別のパッケージです。

実際に使ってみる

本当に使えるか確認するため、以下のソースコードを実行しました。

Main.java

package com.github.korosuke613.example.publish.use;

import com.github.korosuke613.example.publish.Sample;

public class Main {
    public static void main(String[] args) {
        Sample sample = new Sample();

        System.out.println(sample.sum(1, 2));
        System.out.println(sample.sum("Hello ", "GitHub Package Registry"));
    }
}

実行結果

$ ./gradlew run          

> Task :run
3
Hello GitHub Package Registry

BUILD SUCCESSFUL in 1s
2 actionable tasks: 1 executed, 1 up-to-date

ちゃんと、3Hello GitHub Package Registryと出力されているので、正しくインポートできていることが確認できました!

おわりに

今回は、tagをpushすることで、Javaのパッケージを自動でGitHub Package Registryに公開してみました😎

もっと良い方法があれば、ぜひ教えてくださいm(__)m


*1:本当はテストもすべきなのですが、今回の記事ではテストは扱いません。

*2:普段はKotlinを書いており、非常に久々にJavaを弄ったので、えらい大変でした...

*3:公式ドキュメント曰く

*4:実行するたびにGradleをダウンロードしてしまうので、Cache機能なんかを使って実行速度をはやめたいですね

*5:Gradleには別の記述方法もあった気がする


スポンサーリンク