heihei blog

Blog icon by Unsplash https://unsplash.com/@virussinside

maven-publish plugin + GitHub Actions + GitHub Packagesでライブラリモジュールを公開する

最近タイトルのようなことを行ったので、備忘録としてメモ程度にまとめます。自分は今回このように設定してみたよーという紹介になりますので、他にも方法は色々あるかと思います。 あくまで一例として参考程度に見ていただければと思います。

今回行いたかったことは以下です:

  • いくつかの.ktファイルを含んだlibraryモジュール(Androidモジュールではない)をpublishする
  • GitHub Packagesを利用するためのgithub username, tokenはGitHub Actions経由で渡す
  • ライブラリのバージョンはtagの名前に合わせる

maven-publishのセットアップ

まずはpublishするための設定を行います。 今回はmaven-publish pluginを利用しました。このプラグイン以外にも、サードパーティ製のプラグインがあるようです。

Maven Publish Plugin

publishしたいlibraryモジュールのbuild.gradleに以下を記述します(今回はGroovyで記述しましたが、きっと.ktsでも似たような記述になると思います)

// library/build.gradle

plugins {
    id 'kotlin'
    id 'maven-publish'
}

また、maven-publishのセットアップも同様のbuild.gradle内に記述します。

// library/build.gradle

// GitHub Actions経由で動的に値をセットします(動的に値をセットする必要がない場合には直接gradle内に記述します)
def releaseVersion = System.getenv("RELEASE_VERSION")
def credentialUserName = System.getenv("GITHUB_PACKAGE_USER_NAME")
def credentialPassword = System.getenv("GITHUB_PACKAGE_TOKEN")

publishing {
    publications {
        maven(MavenPublication) {
            groupId "YOUR_GROUP_ID"
            artifactId "YOUR_ARTIFACT_ID"
            version releaseVersion
            from components.java
        }
    }
    repositories {
        maven {
            name = "GitHubPackages"
            url = uri("https://maven.pkg.github.com/YOUR_ORG_NAME/YOUR_REPOSITORY_NAME")
            credentials {
                username = credentialUserName
                password = credentialPassword
            }
        }
    }
}

余談ですが、これらの設定は、別ファイルに切り出しておくことも可能です。 たとえば、publish.gradleという名前の別のgradleファイルに設定を記述し、apply を用いてbuild.gradleに適用することができます。

// library/build.gradle

plugins {
    id 'kotlin'
    id 'maven-publish'
}

apply from: "./publish.gradle" // build.gradleと同階層のpublish.gradleを読み込みたい場合

maven-publishプラグインのセットアップを行いGradle Syncが正しく完了すると、publish というGradleコマンドが利用できるようになります。 最終的には、このコマンドを使ってmavenにライブラリを公開します。

maven-publishのセットアップTips or 注意点

Androidモジュールをpublishする

自分は試せていませんが、aarをpublishする場合にはいくつか追加でセットアップが必要かもしれません。

Android LibraryをGitHub ActionsでビルドしGitHub Packagesで公開する - Qiita

GitHubユーザーの権限

GitHub Packagesに公開するための設定で、usernameを指定する箇所がありますが、指定したユーザーがRepositoryへのアクセス権限(もしかしたら不要かも?)と、GitHub PackagesへのWrite権限を持っていることを確認してください。(権限が付与されていない場合にどのようなエラーになるかは失念してしまいました、すみません、、)

// library/build.gradle
    repositories {
        maven {
            name = "GitHubPackages"
            url = uri("https://maven.pkg.github.com/YOUR_ORG_NAME/YOUR_REPOSITORY_NAME")
            credentials {
                username = YOUR_USER_NAME // 指定したユーザーがリポジトリへのアクセス権限があることを確認してください
                password = YOUR_PASSWORD
            }
        }
    }

GitHub Actionsのセットアップ

次にGitHub Actionsの設定です。 以下のYAMLでは、ざっくりこのような処理を順番に行っています

  1. mainブランチにpush
  2. tagのバージョンアップ
  3. バージョンアップされたtagの値をreleaseバージョンとして、publish

それぞれのstepの中で利用しているActionの詳細について気になる方は、Action名で検索するとドキュメントが出てくると思いますので調べてみてください。

name: Publish library module
on:
  push:
    branches:
      - main
jobs:
  publish-library:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout library repository
        uses: actions/checkout@v2
      - name: Bump up tag version # tagのバージョンアップ
        id: bump_tag_version
        uses: anothrNick/github-tag-action@1.26.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          RELEASE_BRANCHES: main
      - name: Prepare for gradle command execution
        uses: actions/setup-java@v1
        with:
          java-version: 11
      - name: Execute gradle command to publish
        env: # libraryモジュールのgradleファイル内で利用する環境変数の値を設定
          RELEASE_VERSION: ${{ steps.bump_tag_version.outputs.new_tag }}
          GITHUB_PACKAGE_USER_NAME: YOUR_USER_NAME
          GITHUB_PACKAGE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        uses: eskatos/gradle-command-action@v1
        with:
          arguments: library:assemble library:publish # maven-publishのコマンドを実行

(もしかしたら最後の assemble のコマンドは不要かもしれません)

GitHub Actions全般については、公式ドキュメントやチュートリアルが充実していますのでこちらを参照するのが良いと思います: GitHub Actions Documentation - GitHub Docs

正しくGitHub PackagesにPublishされると、リポジトリの画面で公開されたPackageを確認できます。

f:id:shoheikawano:20201206203017p:plain

f:id:shoheikawano:20201206203032p:plain

GitHub ActionsのセットアップTips

workflow_dispatch

GitHub Actionsでは、基本的にpushなどのgitのイベントに応じて処理が実行されます。ただ、workflow_dipsatch というイベントをworkflow YAMLに定義しておくことで、手動で特定のworkflowを実行することができるようになります。デバッグなどで処理を実行したい場合には便利です。

リポジトリ>Actionsタブ>All Workflowsの下の個別のWorkflow詳細ページから実行できます。わかりにくい場合はスクリーンショットを参考にしてみてください。

f:id:shoheikawano:20201206203045p:plain

Events that trigger workflows - GitHub Docs

Library Module読み込みのセットアップ

次に、公開されたPackageを利用するための設定です。この記事ではAndroidアプリで利用する前提で説明をします。

プロジェクトルートのbuild.gradleに以下を追加します:

allprojects {
  repositories {
    ...
    maven {
        name = "GitHubPackages"
        url = uri("https://maven.pkg.github.com/YOUR_ORG_NAME/YOUR_REPOSITORY_NAME")
        credentials {
          username = YOUR_USER_NAME
          password = YOUR_PASSWORD
        }
    }
...

以上までの設定が正しく完了すると、ライブラリを利用する準備が整ったことになります。

例えばライブラリが以下の情報で公開されている場合は、

<groupId>jp.co.hogehoge.fugafuga</groupId>
<artifactId>library</artifactId>
<version>0.1.0</version>

以下のように指定することで利用することが可能になるはず:

implementation "jp.co.hogehoge.fugafuga:library:0.1.0"

Library Module読み込みのセットアップ注意点

GitHubユーザーの権限

上でも記述しましたが、ここで username に指定したユーザーがRepositoryへのアクセス権限(もしかしたら不要かも?)と、GitHub PackagesへのWrite権限を持っていることを確認してください。自分はこれにハマりました。

ライブラリ利用の際のユーザー名とトークンのセットアップについて(追記)

GitHub Packagesで公開されているライブラリを利用する際、GitHubのトークンが必要となりますが、念の為バージョン管理せずに動的に値を設定する方針をとりました。

NAME=xxx
TOKEN=xxx

という文字列だけ保持するgithub-packages.propertiesというようなファイルを作成し、ローカルではgitignoreした状態でこちらを利用するようにしています。

CIの場合は、現状GitHub ActionsとBitrise両方を利用していますので、

  • GitHub Actions: Secretsにユーザー名とトークンの値をそれぞれ保存し、propertiesファイルに記述
  • Bitrise: 事前にこのpropertiesファイルをアップロードしておき、Bitriseのworkflow内でDLして利用

という形を現状はとっています。

まとめ

  • maven-publish plugin
  • GitHub Actions
  • GitHub Packages

でどのように自分がライブラリ公開を行ったかをざっと書きました。

GitHub Actionsを利用することで、たとえば

  1. ライブラリモジュールで依存しているライブラリのバージョンの自動更新をdependabotで行う
  2. tagを切ってGitHub Packages公開モジュールのバージョンを上げる
  3. ライブラリモジュールを利用しているリポジトリにバージョン更新PRを投げる

ということも自動で行えるように設定できると思います。(まだできていない)便利ですね。

以上です。間違っている点、不要な記述などあれば教えていただけたら嬉しいです🙏

参考にした記事やドキュメントなど