こんにちは。最近 build.gradle
をゴニョゴニョするのに慣れてきました。
ここ数日、 PhotoLinkViewer をモジュール分けしたいなーと思って一部分を切り離しました。
切り離したものは他のアプリでも使いたいので、プロジェクトとして独立させることにしています。
ここで切り離し元から参照するには 2つほど方法があり、
submodule
などでプロジェクト直下等に置いて管理するaar
化してレポジトリに置き、build.gradle
のdependencies
に組み込む。
という感じです。
submodule で管理する方法を使えば ManifestMerger
が AndroidManifest
をよしなにマージしてくれるので、切り離し元の AndroidManifest
に Activity の情報を書く必要がありません。
aar
はその点自分で書かないといけなくて不便*1
なのですが、submodule は push や pull を頻繁にしないといけないのが面倒だなあ...などと考えた結果、結局 aar
を使うことにしました。
aar
を生成する
ライブラリプロジェクトから aar
を生成するようにするにはまず build.gradle
で設定する必要があります。
// "./repository/" にレポジトリを作成 def repo = new File(rootDir, "repository") // "./repository/snapshots" にスナップショットレポジトリを作成 def snapshotRepo = new File(rootDir, "repository") group = '{{ group name }}' version = '{{ version name }}' apply plugin: 'maven' uploadArchives { repositories.mavenDeployer { repository url: "file://${repo.absolutePath}" snapshotRepository url: "file://${snapshotRepo.absolutePath}" // pom情報 pom.artifactId = '{{ artifact id }}' pom.project { packaging 'aar' name '{{ project name }}' url '{{ siteUrl }}' licenses { license { name '{{ license }}' url '{{ url }}' } } developers { developer { id '{{ name }}' email '{{ mail address }}' } } scm { connection '{{ gitUrl }}' developerConnection '{{ gitUrl }}' url '{{ siteUrl }}' } } } } // 以下、sources.jar を生成する場合に必要。生成すると切り離し元からモジュールのソースコードが見れる。 task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' } artifacts { archives sourcesJar }
のように追記します。{{ ~ }}
は適宜置き換えてください*2。
そうすると uploadArchives
というタスクが追加されるはずなので、
$ ./gradlew clean :{{ module name }}:uploadArchives
とすると、プロジェクトの ./repository/
以下に aar
や pom
が生成されるはずです。
これを gh-pages
ブランチに push すれば、すでに GitHub Pages がレポジトリ代わりになります。
CircleCI で自動的に生成、push する
しかし毎回 commit して push して...となると面倒です。いい感じに自動化する方法としては、
- CircleCI 内で Bintray 等に gradle plugin を使ってアップロードする
- CircleCI 内で直接
gh-pages
ブランチにcommit
,push
させる
等があるでしょう。
1の場合、下の記事を参考にすると簡単にできます。
これを用いると CircleCI 内でそのタスクを実行するだけで Bintray にアップロードできて楽なのですが、このライブラリは自分ぐらいしか使わないし、割りと頻繁に更新する(SNAPSHOT
を使っていく)ようにしたかったので gh-pages
を使うようにしました。*3
ということで、まずは CircleCI が GitHub レポジトリに push できるようにします。これはプロジェクトの設定から Permissions -> Checkout SSH Keys
と辿れば push 権限を追加できる画面が出て来るので、設定して SSH Key を追加させます。
ちなみに僕は GitHub レポジトリの Collaborator に bot を追加させて、そのアカウントで行うようにしました。
そして、ビルドし push させるシェルスクリプトを書きます。
#!/usr/bin/env bash git config --global user.email "{{ mail }}" git config --global user.name "{{ name }}" # 以前の ./repository/ 以下を gh-pages ブランチから持ってくる git branch gh-pages origin/gh-pages git checkout gh-pages -- repository/ ./gradlew --stacktrace clean :{{ module name }}:uploadArchives # ファイルを残したままブランチ変更 git symbolic-ref HEAD refs/heads/gh-pages git reset git add repository/ # 変更点があれば commit, push if [ -n "$(git diff --cached --exit-code)" ]; then CI_RELEASE_DATE=`date +"%Y%m%d%H%M%S"` # 環境変数から GitHub レポジトリ情報を取得 CI_REMOTE_REPOSITORY="git@github.com:${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}.git" git commit -m "[auto] SNAPSHOT-${CI_RELEASE_DATE}" git push ${CI_REMOTE_REPOSITORY} "gh-pages" fi
なぜ current branch には commit しないかというと、コンフリクトを防ぐためです。(gh-pages
は CircleCI のみが管理するのでコンフリクトしない)
なので、以前の ./repository/
以下を gh-pages
から持ってきて、current branch 上でビルドし、その後ファイルを残したままブランチを gh-pages
に切り替えて commit ということをしています。*4
そして、最後に circle.yml
で master
に push されたらデプロイするようにします。
deployment: publish: branch: master commands: - ./gh-push.sh
ここで parallel: true
とかするとコンフリクト不可避なので注意。
こうして bot がレポジトリに push してくれました。
あとは自分の GitHub Pages のレポジトリURL を build.gradle
に加え、さらに dependencies
にライブラリを加えれば完了です。
// 例 repositories { jcenter() maven { url "http://{{ base address }}/repository" } } dependencies { compile "{{ group }}:{{ artifact id }}:{{ version }}" }
無事インポートできました。