概要
Grinder とはDart で実装されたタスクランナーです。
あまり聞かないかもしれませんが、Flutterの公式サンプルでも導入されていたりします。
今回は導入方法からビルドタスクの書き方を紹介したいと思います。
Flutterの公式サンプルを確認したい方は下のリンクからどうぞ
https://github.com/flutter/samples/blob/master/web/samples_index/tool/grind.dart
Version
- Flutter
- version: 1.22.4
- channel: stable
- Grinder
- version: 0.8.6
Grinder のインストール
Grider のinstallを参考に進めていきます。
プロジェクトに対してビルドタスクを追加するので、1つFlutterプロジェクトを開いてください。
Grinder を有効にする
$ flutter pub global activate grinder
Grinderが有効になっているかを確認します。
grind と打って実際に動くか確認しましょう。
Grinder
という名前ですがコマンドはgrind
です。
$ grind
まだビルドタスクの設定ファイルを作成していないので、下記のようなエラーが出ると思います。
Error: expected to find 'tool/grind.dart' relative to the current directory.
あとで設定ファイルを作成するので、今は無視してください。
基本的な使い方
プロジェクトルートに tool/grind.dart
というファイルを作成します
ビルドタスクを追加する
以下はdart analyze
を実行するビルドタスクです。
import 'package:grinder/grinder.dart';
main(List<String> args) => grind(args);
/// 静的解析
@Task('analyze')
void analyze() {
Analyzer.analyze(['./lib']);
}
追加した静的解析のタスクを実行する
grind analyze
で実行できます。
今回はわざと警告が出るようにしているので、以下のメッセージが表示されています。
$ grind analyze
grinder running analyze
analyze
/Users/0maru/development/flutter/bin/cache/dart-sdk/bin/dartanalyzer ./lib/main.dart
Analyzing lib/main.dart...
lint • Prefer using lowerCamelCase for constant names. • lib/main.dart:9:16 • constant_identifier_names
1 lint found.
finished in 7.9 seconds
追加したビルドタスク一覧を確認する
grind -h
で登録しているタスク一覧を確認できます。
$ grind -h
Dart workflows, automated.
Usage: grinder [options] [<tasks>...]
Global options:
--no-color Whether to use terminal colors.
--version Reports the version of this tool.
-h, --help Print this usage information.
Available tasks:
test unit test
(depends on: analyze)
build build
(depends on: test)
analyze analyze
pub pub get
runner run build_runner
色々なビルドタスクを追加してみる
以下は、アプリのビルドやユニットテストを実行できるビルドタスク
import 'dart:io';
import 'dart:async';
import 'dart:convert';
import 'package:async/async.dart' show StreamGroup;
import 'package:grinder/grinder.dart';
main(List<String> args) => grind(args);
/// flutter pub get
@Task('pub get')
void pub() {
_processLog(Process.start('flutter', ['pub', 'get']));
}
/// build_runner でファイルを生成
@Task('run build_runner')
void runner() {
_runProcess(
'flutter',
['pub', 'run', 'build_runner', 'build', '--delete-conflicting-outputs'],
);
}
/// 静的解析
@Task('analyze')
void analyze() {
Analyzer.analyze(['./lib']);
}
/// ユニットテスト
@Task('unit test')
@Depends(analyze) // 先にanalyzeを実行する
void test() {
TestRunner().test(files: 'test/unit');
}
/// 静的解析・ユニットテストを行ったのちビルドする
@Task('build')
@Depends(test) // 先にtestを実行する
void build() {
TaskArgs args = context.invocation.arguments;
final mode = args.getOption('mode');
log(mode);
if (mode?.isEmpty ?? true) {
throw Exception('mode option is required.');
}
// APサーバ、データベースの接続先などを指定する環境変数
final isRelease = args.getFlag('release');
final env = isRelease ? 'release' : 'staging';
_processLog(Process.start(
'flutter',
['build', mode, '--dart-define=ENV=${env}']
));
}
// ビルド中にログを出力する方法1
Future<void> _processLog(Future<Process> process) async {
final _process = await process;
final output = StreamGroup.merge([_process.stdout, _process.stderr]);
await for (final message in output) {
log(utf8.decode(message));
}
}
// ビルド中にログを出力する方法2
Future<void> _runProcess(String executable, List<String> arguments) async {
final result = await Process.run(executable, arguments);
stdout.write(result.stdout);
stderr.write(result.stderr);
}
Github Actions でGrinderを利用する
Grinder で作成したビルドタスクはGithub Actions やTravis CI で使用することができます
以下Github Actions のサンプル
name: Dart
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- uses: actions/checkout@v2
- uses: subosito/flutter-action@v1
with:
flutter-version: '1.22.x'
channel: 'stable'
- run: flutter pub get
- name: test
run: dart tool/grind.dart analyze
まとめ
いかがでしたか?
Dart で書かれているので型を書くことができたり、CIサービスと同じ流れでローカルでもビルドができたりなどGrinderを使用するメリットはあるかと思います。
Makefileが早いだのシェルスクリプトで良いだのと言われるとそこまでなのですが、一度使ってみて快適なDartライフをお送りください。
今回作成したプロジェクトです
コード全体を見たい方は以下からどうぞ
https://github.com/0maru/grinder_sample
Twitterもやってます。
良ければフォローしてください。
https://twitter.com/0maru_dev