Lazybonesでプロジェクトの雛形を作る

TL;DR

GradleやMavenなどのビルドツールには、プロジェクトの雛形を作る機能があります。 しかし、生成されるファイルやディレクトリー構造をカスタマイズしたいと思っても、手軽にカスタマイズする方法がありません。

Lazybonesを用いると、あらかじめ用意したファイル、ディレクトリー構造に基づいて、対話式にプロジェクトの雛形を生成できます。

出来上がったサンプルはGitHubに置いてあります。

Lazybones

github.com

インストール手順

sdkman(旧gvm)がインストール済みであれば、sdk install lazybonesでインストールできます。 もしくは、Bintrayからバイナリーをダウンロードして、展開したディレクトリーをPATHに付け加えます。

できること

$ lazybones --help
Lazybones is a command-line based tool for creating basic software projects from templates.

Available commands:

    create         Creates a new project from a template.
    config         Displays general help, or help for a specific command.
    generate       Generates new files in the current project based on a sub-template.
    list           Lists the templates that are available for you to install.
    info           Displays information about a template, such as latest version, description, etc.
    help           Displays general help, or help for a specific command.

テンプレートを作る

まず、任意のディレクトリーへ移動して、lazybones create lazybones-project <dir>を実行し、テンプレートをビルドするためのGradleプロジェクトを生成します。

$ lazybones create lazybones-project lazybones-templates
Creating project from template lazybones-project (latest) in 'lazybones-templates'

..(snip)..

Project created in lazybones-templates!

Gradleプロジェクトが生成できたら、templatesディレクトリーへ移動して、Lazybonesコマンド実行時に生成されるファイルやディレクトリー構造を定義するためのディレクトリーを作ります。 そして、そのディレクトリーにファイルやディレクトリーを作っていきます。

$ # gradle-java-single テンプレートの例
$ tree -a templates/gradle-java-single/
templates/gradle-java-single/
├── .gitignore
├── README.md
├── VERSION
├── build.gradle
├── gradle
│   ├── checkstyle
│   │   └── sun_checks.xml
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── lazybones.groovy
└── src
    ├── main
    │   ├── java
    │   │   └── .retain
    │   └── resources
    │       └── logback.xml
    └── test
        ├── java
        │   └── .retain
        └── resources
            └── .retain

10 directories, 15 files

Lazybonesテンプレートを作るうえで、README.mdとVERSIONの2つのファイルは必須です。 それ以外のファイルやディレクトリーは任意です。

.retainファイルは中身が空のディレクトリーを生成したいときに置いておくファイルで、Lazybonesコマンドで生成するプロジェクトには展開されないファイルです。

lazybones.groovyファイルは、Lazybonesコマンドでプロジェクトを生成したあとに実行されるスクリプトファイルです。 対話的にアプリケーション名を入力してもらい、そのアプリケーション名を展開したファイルに埋め込む(書き換える)といった用途で使います。

# lazybones.groovy 
def props = [:]
props.app_name = ask("Define value for 'name' [java-app]: ", 'java-app', 'app_name')
props.app_group = ask("Define value for 'group' [org.example]: ", 'org.example', 'app_group')
props.app_version = ask("Define value for 'version' [0.1]: ", '0.1', 'app_version')
props.app_main_class = ask("Define value for 'main class' [org.example.Main]: ", 'org.example.Main', 'app_main_class')

processTemplates 'README.md', props
processTemplates 'gradle.properties', props
# gradle.properties
# ${...} のプレースホルダーが、lazybones.groovyで受け付けた入力値に置き換わる
app_name=${app_name}
app_group=${app_group}
app_version=${app_version}
app_main_class=${app_main_class}

ファイルやディレクトリー構造を準備できたら、ビルドしてテンプレートをzipファイルにまとめます。

Gradleプロジェクトのルートディレクトリーへ移動して、gradle packageTemplate<task-name>を実行します。

※<task-name>の部分はテンプレートのディレクトリー名をキャメルケースに変換した値を指定します。(例: gradle-java-single -> GradleJavaSingle)。

ビルドしたテンプレートは、build/packagesディレクトリーに出力されます。

$ gradle packageTemplateGradleJavaSingle
:packageTemplateGradleJavaSingle

BUILD SUCCESSFUL

Total time: 0.766 secs

テンプレートを用いてプロジェクトを生成する

まず、gradle installTemplate<task-name>を実行し、ビルドしたテンプレートをローカルキャッシュへインストールします。

Lazybonesのローカルキャッシュは、~/.lazybones/templatesディレクトリーにあります。

$ gradle --daemon installTemplateGradleJavaSingle
:packageTemplateGradleJavaSingle
:installTemplateGradleJavaSingle

BUILD SUCCESSFUL

Total time: 0.744 secs

任意のディレクトリーへ移動して、lazybones create <template-name> <template-version> <dir>を実行し、インストールしたテンプレートを用いてプロジェクトを生成します。

※<template-name>の部分はテンプレートのディレクトリー名(zipファイル名のバージョン部分を除いたものと同じ)です。 また、<template-version>の部分はテンプレートに含めたVERSIONファイルに記述した値(zipファイル名のバージョン部分と同じ)です。

$ lazybones create gradle-java-single 1.0.0 java-app
Creating project from template gradle-java-single 1.0.0 in 'java-app'
Define value for 'name' [java-app]: my-java-app
Define value for 'group' [org.example]: my.org.example                
Define value for 'version' [0.1]: 0.0.1
Define value for 'main class' [org.example.Main]: my.org.example.Main

..(snip)..

Project created in java-app!

$ tree -a java-app/
java-app/
├── .lazybones
│   └── stored-params.properties
├── README.md
├── build.gradle
├── gradle
│   ├── checkstyle
│   │   └── sun_checks.xml
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── src
    ├── main
    │   ├── java
    │   └── resources
    │       └── logback.xml
    └── test
        ├── java
        └── resources

11 directories, 10 files

参考情報