この記事はZOZOテクノロジーズ #1 Advent Calendar 2019 1日目の記事になります。
また、今年は全部で5つのAdvent Calendarが公開されています。
- ZOZOテクノロジーズ #2 Advent Calendar 2019
- ZOZOテクノロジーズ #3 Advent Calendar 2019
- ZOZOテクノロジーズ #4 Advent Calendar 2019
- ZOZOテクノロジーズ #5 Advent Calendar 2019
概要
先月のGitHub UniverseでGitHub ActionsとGitHub Packages(旧GitHub Package Registry)が正式リリースされました。GitHub PackagesはGitHubと統合されたパッケージのホスティングサービスで、ソースコードとその成果物であるパッケージを一括で管理できます。
integrated permissions management and billing
とあるので、package単位での課金がサポートされるかもしれませんね。
Supported clients and formatsを見るとGitHub Packagesは以下のクライアントとファイルフォーマットをサポートします。
Package client | Language | Package format | Description |
---|---|---|---|
npm | JavaScript | package.json | Node package manager |
gem | Ruby | Gemfile | RubyGems package manager |
mvn | Java | pom.xml | Apache Maven project management and comprehension tool |
gradle | Java | build.gradle or build.gradle.kts | Gradle build automation tool for Java |
docker | N/A | Dockerfile | Docker container management platform |
nuget | .NET | nupkg | NuGet package management for .NET |
Apache Mavenのpom.xmlフォーマットに対応しており、また、クライアントとしてGradleをサポートしています。したがって、GitHub PackagesにAndroid Libraryをホスティングし、Androidプロジェクトから参照することができそうです。
この記事では、Android Libraryの作成、GitHub Packagesへの公開設定とGitHub Actionsを使用した自動アップロード、そして公開したライブラリのAndroidプロジェクトからの利用方法についてまとめます。
サンプルコード
作業環境
Android Studioのバージョンは3.5.2を使用しています。
Android Libraryの作成
ライブラリを作成してみます。次のようなHelloクラスを作成しライブラリとして公開してみます。
class Hello {
companion object {
fun world(name: String) = "Hello World ${name}!"
}
}
使い方は次の通りです。
Hello.world(name = "Horie1024") // Hello World Horie1024!
プロジェクトの作成
Android Developersのプロジェクトの作成を参考にプロジェクトを作成します。
Android Studioのメインメニューから [File] > [New] > [New Project]を選択します。Create New Projectウィザードが表示されるので、「Empty Activity」を選択してNextをクリックします。
プロジェクトの設定をします。各項目の詳細は「プロジェクトを設定する」を参照してください。Finishをクリックするとプロジェクトが作成されます。
Libraryモジュールの作成
Libraryモジュールを作成します。ライブラリのコードは、Libraryモジュールに書いていきます。Android DevelopersのAndroid ライブラリの作成を参考にLibraryモジュールを作成します。
Android Studioのメインメニューから [File] > [New] > [New Module]を選択します。Create New Moduleウィザードが表示されるので、「Android Library」を選択してNextをクリックします。
ライブラリの名前、コードのMinimum SDKバージョンを指定して[Finish] をクリックします。
「mylibrary」というLibraryモジュールが作成されました。
appモジュールからの参照
ライブラリの開発を行う場合、appモジュールから参照できた方が便利です。Libraryモジュールを作成するとsettings.gradle
が次のように更新されていることを確認します。
include ':app', ':mylibrary'
appモジュールのbuild.gradle
のdependencies
にブロックに次の行を追加します。
dependencies {
implementation project(":mylibrary")
}
これでappモジュールからLibraryモジュールのコードを参照できるようになり、次のように使用できます。
import com.horie1024.mylibrary.Hello
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
hello_world.text = Hello.world(name = "Horie1024")
}
}
ビルドしてアプリを起動するとこんな感じです。
GitHub Packagesへの公開設定
作成したライブラリをGitHub Packagesへアップロードして公開します。公開するための設定はConfiguring Gradle for use with GitHub Packagesにまとめられています。必要になる設定は次の2つです。
- 認証設定
- ライブラリの公開設定
Maven Publish Pluginを使用して設定しますので、Libraryモジュールのbuild.gradleの先頭にapply 'maven-publish'
を追加します。
apply 'maven-publish'
認証設定
GitHub Packagesでのライブラリの公開、ダウンロード、削除には認証が必要になり、GitHubのユーザ名とAccess Tokenが必要になります。
Libraryモジュールのbuild.gradleにpublishing
ブロックを定義し、そこに設定を追加します。url
はライブラリの公開先で、https://maven.pkg.github.com/OWNER/REPOSITORY
の形で指定します。そして、credentials
のusename
にGitHubのユーザー名、password
にAccess Tokenを指定します。
publishing {
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/horie1024/github-packages-android-sample")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
password = project.findProperty("gpr.token") ?: System.getenv("TOKEN")
}
}
}
}
ライブラリの公開設定
GitHub Packagesがサポートするpackageのフォーマット(pom.xml
)にライブラリのソースコードを変換する必要があります。
publishing
にpublications
ブロックを定義し、ライブラリの公開設定を追加します。ここで①の設定を書かない場合、ライブラリの推移的依存関係が含まれなくなります。
apply 'maven-publish'
task sourceJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
archiveClassifier.set("sources")
}
publishing {
publications {
maven(MavenPublication) {
groupId "com.horie1024"
artifactId "github-packages-sample-library"
version "$VERSION"
artifact sourceJar
artifact "$buildDir/outputs/aar/mylibrary-release.aar"
// include any transitive dependencies・・①
pom {
withXml {
def dependenciesNode = asNode().appendNode('dependencies')
project.configurations.implementation.allDependencies.each {
if (it.group != null || it.name != null || it.version != null || it.name == "unspecified") return
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
}
}
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/horie1024/github-packages-android-sample")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
password = project.findProperty("gpr.token") ?: System.getenv("TOKEN")
}
}
}
}
また、ライブラリの公開設定はwupdigital/android-maven-publishを使用するとより簡単に記述できます。ライブラリを使用する側から、ライブラリのKotlinのソースコードを追うことができなかったので今回は使用を見送っています。
手動での公開
Access TokenはGitHubの[Settings] > [Developer settings] > [Personal access tokens] から作成します。scopeはrepo
、write:packages
、read:packages
にチェックを付けて生成します。
ユーザー名とtokenをgradle.properties
に次のように定義するか、環境変数として定義します。
gpr.user = horie1024
gpr.token = 123456789abcdefghijklmnopqrstuvwxyz
次のコマンドを実行するとGitHub Packagesへライブラリが公開されます。
./gradlew assembleRelease publish
そして、公開が成功するとRepositoryのpackagesページに次のようなページが追加されます。これで作成したライブラリを公開できました。
GitHub Actionsの設定
手動での公開ができたのでGitHub Actionsで自動化しましょう。
今回はmasterブランチにコミットがpushされたタイミングでGitHub Packagesにライブラリが公開されるようにします。これは次のymlをプロジェクトトップの.github/workflows
以下に配置することで実現します。
name: "Publish library to GitHub Packages"
on:
push:
branches:
- master
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Publish library
env:
USERNAME: horie1024
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew assembleRelease publish
triggerの設定
masterブランチにコミットがpushされたタイミングでワークフローがトリガーされて欲しいので、onで制御します。次のように設定することでmasterブランチにpushされた場合にワークフローをトリガーすることができます。
on:
push:
branches:
- master
jobの設定
ワークフローはjob
単位で実行されていきます。ここではpublish
jobを定義します。
runs-on
はjobを実行する環境でubuntu-latest
を指定します。steps
はjobを構成する一連のタスクです。1つ目のstepではuses: actions/checkout@master
でソースコードをチェックアウトし、2つ目のPublish library
stepでライブラリの公開を実行します。
Publish library stepでは、env
でstep内でのみ有効な環境変数を定義しています。ここでTOKEN
にはsecrets.GITHUB_TOKEN
を指定します。GITHUB_TOKEN
はワークフロー内で自動的に作られる環境変数です(詳細はこちら)。また、GITHUB_TOKENにどのようなパーミッションが与えられているかはこちらから確認でき、GitHub Packagesについてもread/writeパーミッションを持っています。
そして、run
で./gradlew publish
を実行することでライブラリが公開されます。
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Publish library
env:
USERNAME: horie1024
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew assembleRelease publish
公開したライブラリの利用
GitHub Packagesで公開したライブリを利用するには、認証設定が必要です。現時点(2019/12/01)でpublicなrepositoryの場合でも認証が必要になります。
認証設定
プロジェクトトップのbuild.gradle
内、allprojectsブロックのrepositoriesブロックにライブラリの公開設定と同様の設定を追加します。
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.3.60'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
// repositoriesにGitHub Packagesを追加
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/horie1024/github-packages-android-sample")
credentials {
username = USERNAME // GitHubのユーザ名
password = ACCESS_TOKEN // 発行したAccess Tokenを指定
}
}
}
}
Access Tokenは、read:packages
scopeを指定して作成します。用途としてはライブラリをダウンロードするだけなのでscopeは絞った方が良いでしょう。
dependenciesへの追加
dependenciesブロックにライブラリを追加し、「Sync Project with Gradle files」を実行すると公開したライブラリを使用できるようになります。
android {
// androidブロックの定義
}
dependencies {
// 公開したライブラリをimplementationに追加
implementation 'com.horie1024:github-packages-sample-library:1.0.0'
}
まとめ
Androidのライブラリ作成してGitHub Packagesで公開してみました。GitHub Actionsと組み合わせるとライブラリの自動公開まで簡単に実現でき、今後社内向けのAndroidライブラリはGitHub Packagesでホスティングしていこうと考えています。
明日は@kenz_firespeedさんによる「今風の画像アップローダーを作る」です。