name: Run Tests

on: [push, pull_request]

jobs:
  build:

    name: "${{ matrix.bot }} (${{ matrix.dart-version }}/${{ matrix.code-version }}/${{ matrix.os }})"
    runs-on: ${{ matrix.os }}
    # We want to run on external PRs, but not on our own internal PRs as they'll be run
    # by the push to the branch. 
    if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name ! = github.repository

    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest]
        node-version: [10]
        build-version: [stable]
        bot: [flutter_debug, flutter_debug_chrome, flutter_test_debug, dart_web_debug, flutter_repo, dart_debug, dart, flutter, misc]
        include:
          - build-version: stable
            dart-version: stable
            flutter-version: stable
            code-version: stable
        #   - build-version: dev
        #     dart-version: dev
        #     flutter-version: dev
        #     code-version: insiders
          - os: ubuntu-latest
            bot: flutter_snap

    steps:

      - uses: actions/checkout@v1

      - name: Setup XVFB
        if: matrix.os == 'ubuntu-latest'
        run: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &

      - name: Setup Node v${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}

      - name: Setup Dart ${{ matrix.dart-version }}
        if: matrix.bot ! = 'flutter_snap'
        uses: DanTup/gh-actions/setup-dart@master
        with:
          channel: ${{ matrix.dart-version }}

      - name: Setup Flutter ${{ matrix.flutter-version }}
        id: flutter
        if: matrix.bot ! = 'flutter_snap' && ! startsWith(matrix.bot, 'dart')
        uses: DanTup/gh-actions/setup-flutter@master
        with:
          channel: ${{ matrix.flutter-version }}

      - run: sudo snap install flutter --classic
        if: matrix.bot == 'flutter_snap'

      - run: flutter update-packages
        if: matrix.bot == 'flutter_repo'

      - name: Print Dart version
        if: matrix.bot ! = 'flutter_snap'
        run: dart --version

      - name: Print Flutter version
        if: matrix.bot ! = 'flutter_snap' && ! startsWith(matrix.bot, 'dart')
        run: flutter --version

      - name: Enable Flutter web support
        if: startsWith(matrix.bot, 'flutter') && matrix.bot ! = 'flutter_snap'
        run: flutter config --enable-web

      - run: |
          pub global activate --no-executables devtools
          pub global activate --no-executables webdev
          pub global activate --no-executables stagehand
          pub global activate --no-executables args 1.5.0
          pub global activate --no-executables meta 1.1.6
          pub global activate --no-executables pedantic 1.4.0
          pub global activate --no-executables json_annotation 1.2.0
        if: matrix.bot ! = 'flutter_snap'
        shell: pwsh

      - name: npm install
        run: npm install

      - name: npm lint
        run: npm run lint

      - name: npm build
        run: npm run build

      - name: pub get (hello_world)
        if: startsWith(matrix.bot, 'dart')
        run: pub get
        working-directory: src/test/test_projects/hello_world

      - name: flutter pub get (flutter_hello_world)
        if: startsWith(matrix.bot, 'flutter') && matrix.bot ! = 'flutter_snap'
        run: flutter packages get
        working-directory: src/test/test_projects/flutter_hello_world

      - name: npm test
        run: npm test
        env:
          CI: true
          ELECTRON_NO_ATTACH_CONSOLE: 1
          DISPLAY: ":99.0"
          BOT: ${{ matrix.bot }}
          CODE_VERSION: ${{ matrix.code-version }}
          DART_VERSION: ${{ matrix.dart-version }}
          FLUTTER_VERSION: ${{ matrix.flutter-version }}
          LOGS_NAME: ${{ matrix.dart-version }}_${{ matrix.code-version }}
          FLUTTER_REPO_PATH: ${{ steps.flutter.outputs.flutter-sdk }}

      - name: Store logs
        uses: actions/upload-artifact@v1
        if: always()
        with:
          name: test-logs-${{ matrix.os }}
          path: .dart_code_test_logs

      - name: Store test results
        uses: actions/upload-artifact@v1
        if: always()
        with:
          name: test-results-${{ matrix.os }}
          path: .test_results

      - name: Store coverage
        uses: actions/upload-artifact@v1
        if: success() && matrix.dart-version == 'stable' && matrix.code-version == 'stable'
        with:
          name: coverage-${{ matrix.os }}
          path: coverage


  upload_logs:

    name: Upload Logs
    needs: build
    if: always() && github.event_name == 'push'
    runs-on: ubuntu-latest

    steps:

      - uses: actions/setup-ruby@v1
        with:
          ruby-version: 2.5.x
      - run: gem install dpl

      - name: Fetch Linux test results
        uses: actions/download-artifact@v1
        with:
          name: test-results-ubuntu-latest
          path: .test_results/linux
      - name: Fetch Windows test results
        uses: actions/download-artifact@v1
        with:
          name: test-results-windows-latest
          path: .test_results/win
      - name: Fetch Linux test logs
        uses: actions/download-artifact@v1
        with:
          name: test-logs-ubuntu-latest
          path: .test_logs/linux
      - name: Fetch Windows test logs
        uses: actions/download-artifact@v1
        with:
          name: test-logs-windows-latest
          path: .test_logs/win

      - name: Combine summary files
        run: find .test_results -name '*_summary.csv' -exec cat {} + > .test_results/summary.csv

      - name: Upload test results to Amazon S3
        run: dpl --provider=s3 --bucket="test-results.dartcode.org" --skip_cleanup=true --local-dir=".test_results" --upload-dir="$($env:GITHUB_REF.Replace(`"refs/heads/`", `"`"))/$($env:GITHUB_SHA)" --acl=public_read --default_text_charset=utf-8
        shell: pwsh
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets. AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets. AWS_SECRET_ACCESS_KEY }}

      - name: Upload logs to Amazon S3
        run: dpl --provider=s3 --bucket="test-results.dartcode.org" --skip_cleanup=true --local-dir=".test_logs" --upload-dir="logs/$($env:GITHUB_REF.Replace(`"refs/heads/`", `"`"))/$($env:GITHUB_SHA)" --acl=public_read --default_text_charset=utf-8
        shell: pwsh
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets. AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets. AWS_SECRET_ACCESS_KEY }}

  upload_coverage:

    name: Send Coverage to CodeClimate
    needs: build
    if: always() && github.event_name == 'push'
    runs-on: ubuntu-latest

    steps:

      - uses: actions/checkout@v1

      - name: Fetch Linux coverage
        uses: actions/download-artifact@v1
        with:
          name: coverage-ubuntu-latest
          path: coverage/linux

      - name: Upload to CodeClimate
        run: |
          curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
          chmod +x ./cc-test-reporter
          export GIT_BRANCH="${GITHUB_REF/refs\/heads\//}"
          export GIT_SHA="${GITHUB_SHA}"
          find coverage/**/**/lcov.info | cut -d '/' -f2- | xargs -I % -n1 ./cc-test-reporter format-coverage -t lcov -o coverage/%.json coverage/% # -p /home/runner/work/Dart-Code/Dart-Code
          ./cc-test-reporter sum-coverage -o coverage/codeclimate.json coverage/**/**/lcov.info.json
          ./cc-test-reporter upload-coverage
        env:
          CC_TEST_REPORTER_ID: ${{ secrets. CC_TEST_REPORTER_ID }}


  notify_failure:

    name: Notify Discord of Failure
    needs: build
    if: failure() && github.event_name == 'push'
    runs-on: ubuntu-latest

    steps:

      - name: Send notification to Discord
        run: 'Invoke-WebRequest -Headers @{ "Content-Type" = "application/json" } -Method Post -Body "{`"content`":`"Build failed on $($env:GITHUB_REF.Replace(`"refs/heads/`", `"`")): https://github.com/Dart-Code/Dart-Code/commit/$($env:GITHUB_SHA)/checks`"}" -Uri $env:DISCORD_WEBHOOK'
        shell: pwsh
        env:
          DISCORD_WEBHOOK: ${{ secrets. DISCORD_WEBHOOK }}
