Grails3 アプリケーションプロファイル(意訳版)

Grails3[公式ドキュメント](http://docs.grails.org/3.1.x/)より。
[6章 Application Profiles](http://docs.grails.org/3.1.x/guide/profiles.html)意訳版です。

***

# アプリケーションプロファイル
create-appコマンドでGrailsアプリケーション作成ではデフォルトで"web"プロファイルを使用します:

```
grails create-app myapp
```

他のプロファイルを`profile`引数で指定することが可能です:

```
grails create-app myapp --profile=rest-api
```

指定したプロファイルで必要な、コマンド・テンプレート、プラグインが提供されます。プロファイルのソースコードは、[Github](https://github.com/grails/grails-profile-repository)にあります。各プロファイルはJARファイルとしてGrailsセントラルリポジトリーに発行されています。

使用可能なプロファイルを探すには`list-profile`コマンドを使用します。

```
grails list-profiles
```

プロファイルの情報を参照するには`profile-info`コマンドを使用します。

```
grails profile-info rest-api
```

## プロファイルリポジトリ
GrailsはデフォルトでGrailsセントラルリポジトリのプロファイルを参照します。プロファイル用のリポジトリを`USER_HOME/grails/settings.groovy`に定義する事で追加する事も可能です。

```
grails {
  profiles {
    repositories {
      myRepo {
        url = "http://foo.com/repo"
        snapshotsEnabled = true
      }
    }
  }
}
```

> Grailsではcreate-app時はまだGradleインスタンスが使用できないためAetherを使用してプロファイルを依存管理します。これにより必要であればリポジトリ設定やより高度な設定(プロキシ、認証等)は、USER_HOME/.m2/settings.xmlに設定する事ができます。[Grails3プロファイル: Mavenリポジトリ設定と参照の補足](http://qiita.com/tyama/items/ef875d7b322683d726ac)を参照

# プロファイルの作成
特定の技術や組織に対しての合わせて基本セットのコマンドやプラグインを設定したい場合が新たにプロファイルを作成する考え方になります。
プロファイルを新規作成するには、ベースプロファイルを継承した空のプロファイルを作成する`create-profile`コマンドを使用します:

```
grails create-profile mycompany
```

上記のコマンド例では、"mycompany"ディレクトリに新規プロファイルを作成します。ディレクトリでインタラクティブモードを実行するとプロファイルを作成するコマンドを参照する事ができます:

```
$ cd mycompany
$ grails
| Enter a command name to run. Use TAB for completion:
grails>
create-command      create-creator-command      create-feature      create-generator-command    create-gradle-command   create-template
```

コマンドは以下となります:

* create-command - プロファイルを使用しているときにGrails CLIで使用するコマンドを作成
* create-creator-command - テンプレートから生成を行うコマンドを作成 (例:create-controllerなど)
* create-generator-command - ドメインクラスをベースとした生成コマンドを作成 (例: generate-controllerなど)
* create-feature - プロファイルで使用するフィーチャーを作成
* create-gradle-command - gradleを呼び出すCLIコマンドを作成
* create-template - コマンドで生成されるテンプレートを作成

ライブラリ依存関係をカスタマイズするには、`profile.yml`に追加したい依存ライブラリを指定できます。

以下がprofile.ymlの例:

```
features:
    defaults: 
        - hibernate
        - asset-pipeline
build:
    plugins:
        - org.grails.grails-web
    excludes:
        - org.grails.grails-core
dependencies:
    compile:
        - "org.mycompany:myplugin:1.0.1"
```

ここまでの設定を行って`gradle install`を実行するとプロファイルをローカルリポジトリに発行する事ができます。

```
gradle install
```

`create-app`コマンドで使用するには以下のように実行します:

```
grails create-app myapp --profile mycompany
```

上記のコマンドで作成されたアプリケーションはプロファイルに"mycompany"を使用して、依存ライブラリに"myplugin"を含み、そして"hibernate"と"asset-pipeline"のフィーチャーを含んだ状態で作成されます。(フィーチャーの話は後述)

依存管理のグループやバージョンなどを指定する場合は以下のようになります:

```
grails create-app myapp --profile com.mycompany:mycompany:1.0.1
```

# プロファイル継承
プロファイルは幾つかの親プロファイルを拡張できます。プロファイルの`build.gradle`を変更する事でプロファイル継承の設定が可能です。
baseプロファイルを拡張るす設定例:

```
dependencies {
    runtime "org.grails.profiles:base:${project.grailsVersion}"
}
```

親プロファイルから継承すると以下の利点があります:

* `create-app`コマンド実行時に親プロファイルのスケルトンが先に複製されます。
* 依存とbuild.gradleが親プロファイルからマージされます。
* application.ymlファイルが親プロファイルからマージされます。
* CLIコマンドが親プロファイルから継承されます。
* 親プロファイルのフィーチャーが継承されます。

記述した順番が継承順となります:

```
dependencies {
    runtime "org.grails.profiles:plugin:${project.grailsVersion}"
    runtime "org.grails.profiles:web:${project.grailsVersion}"
}
```

上記の例では先に"plugin"のスケルトンを複製して次に"web"を複製します。加えて、"web"プロファイルが"plugin"プロファイルのコマンドをオーバーライドします。一方もし依存順序が逆であればオーバーライドも逆となります。

# プロファイル発行

## Grailsセントラルリポジトリへプロファイルの発行
`create-profile`コマンドで生成したプロファイルはあらかじめ以下ように`grails-profile-publish`プラグインが設定されています:

```
apply plugin: "org.grails.grails-profile-publish"
```

Grailsセントラルリポジトリへプロファイルを発行するには、先ずソースをGithubにオープンな状態で公開します。次にBintrayにアカウント登録します。そして以下の内容をbuild.gradleに設定します。

```
grailsPublish {
  user = 'YOUR USERNAME'
  key = 'YOUR KEY'
  githubSlug = 'your-repo/your-profile'
  license = 'Apache-2.0'
}
```

> githubSlugはGithubリポジトリへのパスを設定します。例えば`https://github.com/foo/bar`の場合は`foo/bar`となります。

設定が完了したら、`gradle publishProfile`でプロファイルを発行します:

```
gradle publishProfile
```

プロファイルがBintrayにアップロードされます。アップロードされたらGrailsプロファイルリポジトリへ行きプロファイルを追加するリクエスト"Include My Package"をクリックします。

## 内部リポジトリへのプロファイル発行
前述したとおり`grails-profile-publish`プラグインが設定されているので、それによってGradleのMavenデプロイプラグインも設定されています。内部リポジトリに発行する場合は。リポジトリの設定をbuild.gradleに追加すます:

```
publishing {
    repositories {
        maven {
            credentials {
                username "foo"
                password "bar"
            }
            url "http://foo.com/repo"
        }
    }  
}
```

設定が完了したらあとはgradle plublishを実行します:

```
gradle publish
```


# プロファイルを理解する
プロファイルは、profile.ymlファイルと、プロファイル定義された"commands", "skeleton", "templates"の各ディレクトリを含むシンプルなディレクトリで構成されています:

```
web
    * commands
        * create-controller.yml
        * run-app.groovy    
        …
    * features
        * asset-pipeline
            * skeleton
            * feature.yml
    * skeleton
        * grails-app
            * controllers
            …
        * build.gradle
    * templates
        * artifacts
            * Controller.groovy
    * profile.yml
```

上記の例は'web'プロファイルの物です。profile.ymlはプロファイルの説明とどのようにビルドが定義されてるかをコントロールします。


## profile.ymlディスクリプターを理解する

profile.ymlは以下の子エレメントを含むことができます。

### 1) repositories
ビルドに必要なMavenリポジトリリスト。例:

```
repositories:
    - "https://repo.grails.org/grails/core"
```

### 2) build.repositories
buildscriptセクションのビルドに必要なMavenリポジトリリスト。例:

```
build:
    repositories:
        - "https://repo.grails.org/grails/core"
```

### 3) build.plugins
設定したいGradleプラグインリスト。例:

```
build:
    plugins:
        - eclipse
        - idea
        - org.grails.grails-core
```

### 4) build.excludes
親プロファイルで指定されたリストから除外したいGradleプラグインリスト。例:

```
build:
    excludes:
        - org.grails.grails-core
```

### 5) dependencies
スコープ別に依存ライブラリを定義。excludesスコープで親プロファイルで定義された内容を除外できます。例:

```
dependencies:
    excludes:
        - "org.grails:hibernate"
    build:
        - "org.grails:grails-gradle-plugin:$grailsVersion" 
    compile:
        - "org.springframework.boot:spring-boot-starter-logging"
        - "org.springframework.boot:spring-boot-autoconfigure"
```

### 6) features.defaults
デフォルトフィーチャー定義。フィーチャーが指定されなかった場合に設定されます。

```
features:
    defaults: 
        - hibernate
        - asset-pipeline
```

## プロファイルを使用すると何が起こるのか？
`create-app`コマンドが実行されたら、親プロファイルからスケルトンを収集複製して新規プロジェクトを作成します。
profile.ymlに記述された情報を収集してbuild.gradleファイルを生成します。
コマンドは、親プロファイル等からの情報もbuild.gradleマージします。
grails-app/conf/application.ymlファイルも全ての親プロファイルからマージされ１つのYAMLファイルが生成されます。


# プロファイルコマンドの作成
プロファイルのみで使用するコマンドをYAMLファイルまたはGroovyスクリプトで定義します。以下の例はcreate-controllerコマンドをYAMLで定義しています:

```
description: 
    - Creates a controller
    - usage: 'create-controller [controller name]'
    - completer: org.grails.cli.interactive.completers.DomainClassCompleter
    - argument: "Controller Name"
      description: "The name of the controller"     
steps:
 - command: render
   template: templates/artifacts/Controller.groovy
   destination: grails-app/controllers/artifact.package.path/artifact.nameController.groovy
 - command: render
   template: templates/testing/Controller.groovy
   destination: src/test/groovy/artifact.package.path/artifact.nameControllerSpec.groovy
 - command: mkdir
   location: grails-app/views/artifact.propertyName
```

YAMLに定義するコマンドには1つ以上のステップの記述が必要です。各ステップ自体コマンドです。使用可能なステップは:

* render - テンプレートを指定されたdestinationに生成する。
* mkdir - 指定された位置にディレクトリを生成する。
* execute - classパラメータで指定されたコマンドを実行する。[Commandインターフェイス](http://docs.grails.org/3.1.x/api/org/grails/cli/profile/Command.html)を実装したコマンドに限る。
* gradle - tasksパラメータに指定されたGradleのタスクを1つまたは複数実行する


例としてGradleのタスクを実行する場合は、以下のようにYAMLに設定します:

```
description: Creates a WAR file for deployment to a container (like Tomcat)
minArguments: 0
usage: |
 war
steps:
 - command: gradle
   tasks:
     - war
```

YAML定義での手法よりもっと柔軟なコマンドを作成したい場合はGroovyスクリプトのコマンドを提供する事が出来ます。コマンドスクリプトはGroovyScriptCommmandの拡張となるためGroovyScriptCommmandのメソッドが使用できます。

Groovyで記述した`create-script`の例です:

```
description( "Creates a Grails script" ) {
  usage "grails create-script [SCRIPT NAME]"
  argument name:'Script Name', description:"The name of the script to create"
  flag name:'force', description:"Whether to overwrite existing files"
}
def scriptName = args[0]
def model = model(scriptName)
def overwrite = flag('force') ? true : false

render  template: template('artifacts/Script.groovy'), 
        destination: file("src/main/scripts/${model.lowerCaseName}.groovy"),
        model: model,
        overwrite: overwrite
```

CLIコマンド作成に関しては、ドキュメント[Creating custom scripts](http://docs.grails.org/3.1.x/guide/single.html#creatingCustomScripts)を参照してください。


# プロファイルフィーチャーの作成
プロファイルフィーチャーは、複数のプロファイルにまたがって共有できるテンプレートと依存管理セットです。
一般的には、幾つかのフィーチャーを持つベースプロファイルを作成して、それを継承したプロファイルから親プロファイルのフィーチャーを使用します。

プロファイルのディレクトリで`create-feature`コマンドを実行する事でフィーチャー作成できます:

```
grails create-feature myfeature
```

このコマンド実行では、myfeature/feature.ymlファイルが以下の内容で作成されます:

```
description: Description of the feature
# customize versions here
# dependencies:
#   compile:
#     - "org.grails.plugins:myplugin2:1.0"
#
```

もっと具体的な例として、以下は"asset-pipeline"フィーチャーからのfeature.ymlの内容です:

```
description: Adds Asset Pipeline to a Grails project
build:
    plugins:
        - asset-pipeline
dependencies:
    build:
        - 'com.bertramlabs.plugins:asset-pipeline-gradle:2.5.0'
    runtime:
        - "org.grails.plugins:asset-pipeline"
```

フィーチャーの階層は次のようになります:

```
FEATURE_DIR
    * feature.yml
    * skeleton
        * grails-app
            * conf
                * application.yml
        * build.gradle
```

プロファイルが使用されると、スケルトンのコンテンツはアプリケーション階層に複製され、application.ymlとbuild.gradleには指定した内容がマージされます。

feature.ymlでは依存を追加できます。それによって利用者にオプショナル機能を提供する事ができます:

```
grails create-app myapp --profile myprofile --features myfeature,hibernate
```

上記の例では、フィーチャーに"myfeature"と"hibernate"を指定して新規アプリケーションを作成しています。