へんてこのブログ

日々気づいたことや、最近やっていることを書いています

gradle-xcodePluginにプルリクした

openbakery/gradle-xcodePlugin · GitHubにプルリクした!
Support for DeployGate by henteko · Pull Request #63 · openbakery/gradle-xcodePlugin · GitHub

何したのか

Support for DeployGate!!!
gradle-xcodePluginだけでdeploygateにアップロード出来るようにした
便利
使い方とかは以下を見れば分かりそう
iPhoneアプリをGradleでビルドしてDeployGateで自動配布する方法の続き - Qiita

ハッカソン

http://www.lovelive-anime.jp/img/top/keyv5a.png
(http://www.lovelive-anime.jp/から引用)

この前の土曜日に、同期で集まってハッカソンするみたな感じのことをやっていたのだけど、そこでやること無かったからgradle-xcodePluginにDeployGate対応をした
そのハッカソン自体はラブライブ見ながら全員違うことやりながらモクモクするみたいな感じで、とにかくラブライブ最高だった

Travis CIからDeployGateにアップロードする

Travis CIでAndroidアプリをビルドしてDeployGateにアップロードします

使うもの

今回のサンプルプロジェクト

henteko/AssistHack · GitHub

gradle準備

普通にgradleでビルド出来るようにしたAndroidアプリのプロジェクトを用意します
そして、gradleでdeploygateに簡単に上げられるgradleプラグインがあるので詳しくはここを参照しながら準備して下さい
ここで重要なのが、deploygateを上げる際にtoken(api key)が必要なんだけど、これは公開してはいけないので、gradle.propertiesを使って外部化する(下のやつのmyToken部分)
今回はこのような形になった

travis準備

これ読んでる人なら大丈夫だと思う気がする
githubにプロジェクト上げてルートに.travis.ymlを生成する
.travis.ymlの中はここを参考にさせてもらった
最終的にこのような形になった

ここで重要なのがsecureの文字列
ここにはdeploygateのtokenを記述する
今回はgradleでmyTokenといったプロパティ変数名で読み込んでいるので、こんなコマンドでいける

$ gem install travis
$ travis encrypt ORG_GRADLE_PROJECT_myToken=<deploygateのtoken>

これで出力された文字列を.travis.ymlに書けば、travis内で以下のコマンドを実行したのと同じになる

$ export ORG_GRADLE_PROJECT_myToken=<deploygateのtoken>

ちなみに、ORG_GRADLE_PROJECT_<変数名>ってのを環境変数に加えると、自動でgradleがプロパティ変数化してくれる、便利

あとはgithubにpushするだけ

pushするだけでビルドが走って成功すれば自動でdeploygateにアップロードされます
便利

参照

Android Studio projectをTravis-CIでビルドする - Islands in the byte stream
Travis CI からHerokuへのデプロイを自動化してみた - アジャイルSEの憂鬱
Literal Ice: Gradleでプロパティなどの設定情報を外出しして切り替えて使う
Travis CI: Encryption keys DeployGate/gradle-deploygate-plugin · GitHub

Gradleプラグインでの入れ子構造引数による動的タスク生成

前回のエントリのやつが解決した

こんなことがしたい

sample {
  configKey = "test config key"

  books {
    quickStart {
      title = "quick start book"
      body = "quick start book body"
    }
    userGuide {
      title = "user guide book"
      body = "user guide book body"
    }
  }
}

といったbuild.gradleがあった場合、動的にbooks内のquickStartやuserGuideごとのタスクを生成したい
具体的に書くと、quickStartBookReadとかuserGuideBookReadとかいうタスクを動的に生成したい

ソースコード

henteko/gradle-samplebooks-plugin · GitHub
アップデートしたのでこれを参照してもらいたい

結論

applyメソッド内に以下の様な感じで書いたら出来た

def books = project.container(BookTarget) {
  String bookName = it.toString()
  def subTask = project.task("${bookName}BookRead", type: SubBookTask)
  subTask.group = 'Sample' 
  subTask.description = "${bookName} book read"
  subTask.bookName = bookName

  project.extensions.create(it, BookTarget, bookName)
}
def sample = new SampleExtension(books)

project.containerのクロージャー内で、itにより自身(?)を参照することにより、それぞれのbookNameを取得することが出来る
その後、動的にタスクを生成後各タスクに渡すようにsubTask.bookName = bookNameで名前を渡している

ちなみにSubBookTask.groovyはこんな感じ

package com.henteko07.gradle.plugins

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction

class SubBookTask extends DefaultTask {
    String bookName
    
    @TaskAction
    def subBookRead() {
        println "your config key: ${project.sample.configKey}"
        println ""

        def books = project.sampleBooks
        for(book in books) {
            if(bookName != book.name) continue

            println "setting name: ${book.name}"
            println "title: ${book.title}"
            println "body: ${book.body}"
            println ""
        }
    }
}

bookNameってやつが動的にくる名前となる
bookNameごとにifで振り分けるみたいなことすると、今回の目的が達成出来た

参考

Gradleプラグインで動的にタスクを生成したいのだけどどうやるのか分からない

2013/11/29 7:00頃追記

解決しました
Gradleプラグインでの入れ子構造引数による動的タスク生成 - hentekoのdev日記

何?

タイトル通り
前のエントリでGradleプラグインで入れ子構造の引数の受け取り方を書いたけど、この状態で引数を受け取るときに、nameの名前のタスクを動的に生成したくなった
どうやるのか悩んでる

最初は普通にapplyメソッド内に、

for(book in project.sampleBooks) {
    project.task("${book.name}") {
        // task
    }
}

とか書けばいいかなとか考えてたけど、実際やってみたらapplyメソッド内が実行されるタイミングではproject.sampleBooksには何も入っていない
これではbooksのnameが取得出来ない

難しい
知ってる方いたら僕に教えて下さいよろしくお願いいたします

Gradleプラグインで入れ子構造の引数を受け取る方法

課題

とあるGradleプラグインのアップデートを実装してて、設定の記述をこんな風にしたかった

sample {
  configKey = "test config key"

  books {
    quickStart {
      title = "quick start book"
      body = "quick start book body"
    }
    userGuide {
      title = "user guide book"
      body = "user guide book body"
    }
    ...
    ...
    ...
  }
}

sampleって中にconfigKeyってパラメータを保持したまま、その中のbooksパラメータの中に任意の数のパラメータを入れ子構造で入れていきたいってのが今回の課題

こういうのをいい感じに解析するのにGradleではproject.containerってのを使うらしい
参照: 第58章 カスタムプラグインの作成

この参照先のサイトの例を見ると、booksの中にいい感じに入れ子構造での値受け渡しが出来てるみたいだけど、このさらに上の構造(configKeyの所)が今回は必要なので少し工夫する

方法

サンプルプラグインを書いてみた
henteko/gradle-samplebooks-plugin · GitHub

2013/11/29 7:00頃追記

サンプルのプラグインをアップデートしました
Gradleプラグインでの入れ子構造引数による動的タスク生成 - hentekoのdev日記

ちょっと解説

Pluginのapplyメソッド内で以下を記述する

def sample = new SampleExtension(project.container(BookTarget))
project.convention.plugins.sample = sample
project.extensions.sample = sample

SampleExtensionクラスを作成し、そのコンストラクタとしてproject.container(BookTarget)を渡す
SampleExtensionはこんな感じ

public class SampleExtension {
    final private NamedDomainObjectContainer<BookTarget> sampleBooks
    String configKey

    public SampleExtension(NamedDomainObjectContainer<BookTarget> books) {
        sampleBooks = books
    }

    public books(Closure closure) {
        sampleBooks.configure(closure)
    }
}

ここで重要なのが、booksメソッド*1でsampleBooks.configure(closure)を実行すること
これで解析していい感じに値が取得出きる

値の取得

値の取得はそれぞれ、
configKey : project.sample.configKey
books : project.sampleBooks*2
で取得が出来る
全て取得したい場合はこんな感じ

for(book in project.sampleBooks) {
    println book.name
}

まとめ

結構苦労した
他の既に動いてるプラグインを参考にしてやっと出来た感じだった
参考: catalysts-gradle-plugins/src/main/groovy/cc/catalysts/gradle/plugins/deploy at 155df09fd1754c6aa9df84d41632a495c0ca1faa · Catalysts/catalysts-gradle-plugins · GitHub
参考2: jvoegele/gradle-android-plugin · GitHub

*1:このメソッド名で設定記述欄の名前が決まる

*2:SampleExtension内のNamedDomainObjectContainerの変数名で決定されるよう