# 【Flutter】FlutterのオレオレDanger設定【Danger】

aridaiがFlutterでCIを回す際に設定している dangerfile.ts を公開しておきます。

CIの設定 ↓

name: CI

on:
  push:
    branches: [ master ]
    paths-ignore:
      - docs/**
      - README.md
      - LICENSE
  pull_request:
    branches: [ master ]

jobs:
  prepare:
    runs-on: ubuntu-latest
    if: "!(contains(github.event.head_commit.message, 'skip') && contains(github.event.head_commit.message, 'ci'))"
    steps:
      - name: Prepare
        run: ''

  build:
    runs-on: ubuntu-latest
    needs: [prepare]
    steps:
      - uses: actions/checkout@v2
        with:
          ref: ${{ github.event.inputs.ref }}

      - name: Setup Flutter
        uses: subosito/flutter-action@v1
        with:
          channel: 'stable'
          flutter-version: '1.22.2'

      - name: Check Flutter version
        run: flutter --version

      - name: Restore dotenv
        run: echo ${{ secrets.DOT_ENV }} | base64 -d > .env

      - name: Restore dependencies
        run: flutter pub get

      - name: Build (Android)
        run: flutter build apk --debug

      - name: Test
        run: flutter test

      - name: Format
        if: github.ref == 'refs/heads/master'
        run: dart format --fix ./

      - name: Analyze
        if: github.ref == 'refs/heads/master'
        run: flutter analyze

      - name: Format and Report
        if: github.ref != 'refs/heads/master'
        run: dart format --fix ./ > dart_format_report.txt

      - name: Analyze and Report
        if: github.ref != 'refs/heads/master'
        continue-on-error: true
        run: flutter analyze > flutter_analyze_report.txt

      - name: Run Danger
        if: github.ref != 'refs/heads/master'
        uses: danger/danger-js@9.1.8
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Dangerの設定 ↓

import { markdown, fail } from 'danger';
import { readFileSync } from 'fs';

//  Dart Format Report
function parseFormattedFilePath(line: string): string | null {
    const result = line.match(/^Formatted (.+).dart$/);
    if (result == null) return null; else return `${result[1]}.dart`;
}

const dartFormatReport = readFileSync('dart_format_report.txt', 'utf-8');
const formattedFilePaths = dartFormatReport.split('\n').map(parseFormattedFilePath).filter(path => path != null);

markdown('## Dart Format Report\n');

if (formattedFilePaths.length == 0) {
    markdown('✅ No issues found.\n');
} else {
    markdown(`${formattedFilePaths.length} issue(s) found.\n`);
    for (var path of formattedFilePaths) markdown(`* ${path}`);

    fail(`Dart Format Report: ${formattedFilePaths.length} issue(s) found.`);
}


//  Flutter Analyze Report
interface Issue { level: string; message: string; file: string; rule: string; }

function parseIssueLine(line: string): Issue | null {
    const result = line.match(/(\s*)(info|warning|error) • (.+) • (.+) • (.+)/);
    if (result == null) return null;
    else return { level: result[2], message: result[3], file: result[4], rule: result[5] };
}

const report = readFileSync('flutter_analyze_report.txt', 'utf-8');
const issues = report.split('\n').map(parseIssueLine).filter(issue => issue != null);

markdown('## Flutter Analyzer Report\n');

if (issues.length == 0) {
    markdown('✅ No issues found.\n');
} else {
    var table = '| Level | Message | File | Rule |\n|:---|:---|:---|:---|\n';

    for (var issue of issues) {
        const ruleLink = `[${issue.rule}](https://dart-lang.github.io/linter/lints/${issue.rule}.html)`;
        table += `| ${issue.level} | ${issue.message} | ${issue.file} | ${ruleLink} |\n`;
    }

    markdown(`${issues.length} issue(s) found.\n`);
    markdown(table);

    fail(`Flutter Analyze Report: ${issues.length} issue(s) found.`);
}

CI で dart format --fix ./flutter analyze を実行して、何かしらの指摘事項があった場合に ↓ のようにbotがコメントしてくれます。

Danger