■ 概要
全体図
【事前準備】
Slack に GitHub を追加する
こちらのURL から Incoming Webhook を Slack に追加し、通知を受信したい channel を選択 → インテグレーションを追加する
下記の Webhook URL を取得しておく
シークレット情報をそのまま記載しておくのはセキュリティ的によろしくないので、リモートリポジトリに環境変数を設定する。(SupabaseのプロジェクトURL / anonキー / Slack の Webhook URL を登録するため)
対象のリポジトリを選択 → Settings → secrets and variables → Actions にて New repository secret を押下しプロジェクトURLやanonキーを記載し Add secret を追加。
下記の様に3つシークレットを作成している状態となる。
ワークフローのセットアップ
以下のコマンドでプロジェクト配下に GitHub Action 用ディレクトリとファイルを作成(ファイル名は好きな名前で可能)
% mkdir -p .github/workflows
% touch .github/workflows/flutter_analyze_flutter_test.yaml
ディレクトリ & ファイルが出来た事を確認
ワークフローファイルの内容
# ワークフローの名前
name: flutter_analyze_flutter_test
# トリガー(mainブランチにプルリクが作成されたら起動)
on:
pull_request:
branches:
- main
types: [opened]
workflow_dispatch:
env:
SLACK_USERNAME: DeployBot
SLACK_ICON: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
jobs:
flutter_analyze:
runs-on: ubuntu-latest
concurrency: # 同時実行を防止
group: flutter_analyze
cancel-in-progress: true # 実行中のジョブをキャンセル
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Install and Cache Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.24.3"
channel: "stable"
cache: true
cache-key: flutter-${{ runner.os }}-3.24.3
- name: Show Flutter Version
run: flutter --version
- name: Get Flutter Packages
run: flutter pub get
working-directory: .
- name: Analyze Flutter Code
env:
SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
run: flutter analyze
- name: Run Flutter Tests
run: flutter test
slack_notification: # Slack通知を別ジョブに分離
runs-on: ubuntu-latest
needs: flutter_analyze
if: ${{ failure() }} # flutter_analyze または flutter test が失敗した場合に実行
steps:
- name: Send Slack Notification on Failure
uses: rtCamp/action-slack-notify@v2
env:
SLACK_TITLE: flutter_analyze_flutter_test / Failure
SLACK_COLOR: danger
SLACK_MESSAGE: CI/CDが失敗しました
静的解析(flutter analyze)
- ルートディレクトリにある analysis_options.yaml はこんな感じ。
include: package:flutter_lints/flutter.yaml
linter:
rules:
avoid_print: true # print文があると警告が出る
prefer_single_quotes: true # シングルクオートでないと警告が出る
always_use_package_imports: true # 相対パスでインポートすると警告が出る。
avoid_annotating_with_dynamic: true # dynamicで型をつけると警告が出る。
- 参考
テスト(flutter test)
- testフォルダにテストコードを記載
一旦ここでは、テストが確実に成功するため、初期画面に「ログイン」というテキストが表示されることを確認するためのシンプルなテストコードにする。
各々変えてもらえらばと!
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hogehoge/main.dart';
void main() {
testWidgets('アプリが正しく起動するか確認する', (WidgetTester tester) async {
// ProviderScopeでアプリをラップ
await tester.pumpWidget(
const ProviderScope(
child: MyApp(),
),
);
// 初期画面に「ログイン」というテキストが表示されていることを確認
expect(find.text('ログイン'), findsOneWidget);
});
}
CI/CD の動作確認
今回トリガーは下記の通り main ブランチへのプルリクを作る事なので適当に作ります。プルリクが作成されると自動的に CI/CD が走ります。
# トリガー(mainブランチにプルリクが作成されたら起動)
on:
pull_request:
branches:
- main
チェック中( Details を押下すると今どの段階か詳細がわかる)
全てのチェックが完了し成功したパターン
失敗した時はこんな感じで Slack に通知が来る
以上。