コンテンツにスキップ

Dartでワークフローを書く

手順も、条件分岐も、関数も。アプリ開発で使っているDartを、そのままCIに。

ワークフローは、リポジトリの openci/ ディレクトリに置くDartファイルです。OpenCI.init でワークフローを初期化し、実行したいコマンドを順番に呼び出します。

import 'package:openci_workflow/openci_workflow.dart';
Future<void> main() async {
final ci = await OpenCI.init(
workflowName: 'Dart checks',
ciTriggers: [CITrigger.push(branch: 'main')],
);
await ci.run('dart pub get');
await ci.run('dart analyze --fatal-infos');
await ci.run('dart test');
}

プランナーが実行前に読み取れるように、ワークフロー名とトリガーのブランチは文字列リテラルで定義してください。

シェルコマンドを実行する

シェルコマンドを実行するへのリンク

ci.run は sh を使ってコマンドを実行します。標準出力・標準エラーがビルドログに表示され、失敗したコマンドの終了コードでワークフローが終了します。

await ci.run('dart format --output=none --set-exit-if-changed .');
await ci.run('dart analyze --fatal-infos');

コマンドに await を付けると、ひとつの処理が完了してから次の処理に進みます。

処理を関数にまとめる

処理を関数にまとめるへのリンク

複数のワークフローで共通する処理は、Dartの関数にできます。

Future<void> checkFlutter(OpenCI ci) async {
await ci.run('flutter pub get');
await ci.flutter.staticAnalysis();
await ci.flutter.unitTests();
}

通常のDartファイルとして切り出し、必要なワークフローからインポートできます。

workingDirectory は、リポジトリルートからの相対パスで指定します。

await ci.run(
'flutter analyze',
workingDirectory: 'apps/mobile',
);

ワークフロー全体の既定のディレクトリには、OpenCI.init の currentWorkingDirectory を使います。Flutterヘルパーは呼び出しごとの dir も指定できます。

await ci.flutter.unitTests(dir: 'apps/mobile');

リポジトリルートからDartファイルを実行します。

ターミナル
dart run openci/flutter_ci.dart

必要なSDKとビルドツールは、実行環境側に用意してください。詳しくはクイックスタートを参照してください。

古いPRのCIを自動キャンセルする

古いPRのCIを自動キャンセルするへのリンク

openci_workflow 0.2.3と自動キャンセルに対応したサーバーで、OpenCI.initに cancelPreviousRuns: trueを指定します。

final ci = await OpenCI.init(
workflowName: 'PR checks',
ciTriggers: [CITrigger.pullRequest(branch: 'main')],
cancelPreviousRuns: true,
);

新しいコミットの実行が登録されると、同じリポジトリ・PR・ワークフローファイルの、 自動キャンセルを有効にしていた古い待機中・実行中ジョブをキャンセルします。 別PR、pushによる実行、完了済みジョブ、同じコミットの再実行は対象外です。 paths条件で新しい実行がスキップされた場合も、古い実行は継続します。

初期値はfalseです。最後まで実行したいデプロイ用ワークフローでは無効のままにします。 値にはリテラルのtrueかfalseを指定してください。実行中ジョブは通常約15秒で キャンセルを検知し、その後VMの削除とGitHub Checkの更新を行います。