name: ci

on: [push, pull_request]

jobs:
  build:
    name: ${{ matrix.config.kind }} ${{ matrix.config.os }}
    if: |
      github.event_name == 'push' ||
      !startsWith(github.event.pull_request.head.label, 'denoland:')
    runs-on: ${{ matrix.config.os }}
    timeout-minutes: 60
    strategy:
      matrix:
        config:
          - os: macOS-latest
            kind: test_release
          - os: windows-2019
            kind: test_release
          - os: ubuntu-16.04
            kind: test_release
          - os: ubuntu-16.04
            kind: test_debug
          - os: ubuntu-16.04
            kind: bench
          - os: ubuntu-16.04
            kind: lint

      # Always run master branch builds to completion. This allows the cache to
      # stay mostly up-to-date in situations where a single job fails due to
      # e.g. a flaky test.
      # Don't fast-fail on tag build because publishing binaries shouldn't be
      # prevented if 'cargo publish' fails (which can be a false negative).
      fail-fast:
        ${{ github.event_name == 'pull_request' || (github.ref !=
        'refs/heads/master' && !startsWith(github.ref, 'refs/tags/')) }}

    env:
      CARGO_INCREMENTAL: 0
      RUST_BACKTRACE: full

    steps:
      - name: Configure git
        run: git config --global core.symlinks true

      - name: Clone repository
        uses: actions/checkout@v2
        with:
          # Use depth > 1, because sometimes we need to rebuild master and if
          # other commits have landed it will become impossible to rebuild if
          # the checkout is too shallow.
          fetch-depth: 5
          submodules: true

      - name: Create source tarballs (release, linux)
        if: |
          startsWith(matrix.config.os, 'ubuntu') &&
          matrix.config.kind == 'test_release' &&
          github.repository == 'denoland/deno' &&
          startsWith(github.ref, 'refs/tags/') &&
          !startsWith(github.ref, 'refs/tags/std/')
        run: |
          mkdir -p target/release
          tar --exclude=.cargo_home --exclude=".git*" --exclude=target --exclude=deno_typescript/typescript/tests --exclude=third_party/cpplint --exclude=third_party/node_modules --exclude=third_party/python_packages --exclude=third_party/prebuilt -czvf target/release/deno_src.tar.gz -C .. deno

      - name: Install rust
        uses: hecrj/setup-rust-action@v1
        with:
          rust-version: 1.44.0

      - name: Install clippy and rustfmt
        if: matrix.config.kind == 'lint'
        run: |
          rustup component add clippy
          rustup component add rustfmt

      - name: Install Python
        uses: actions/setup-python@v1
        with:
          python-version: "2.7"
          architecture: x64

      - name: Remove unused versions of Python
        if: startsWith(matrix.config.os, 'windows')
        run: |-
          $env:PATH -split ";" |
            Where-Object { Test-Path "$_\python.exe" } |
            Select-Object -Skip 1 |
            ForEach-Object { Move-Item "$_" "$_.disabled" }

      - name: Log versions
        run: |
          node -v
          python --version
          rustc --version
          cargo --version

      - name: Configure cargo data directory
        # After this point, all cargo registry and crate data is stored in
        # $GITHUB_WORKSPACE/.cargo_home. This allows us to cache only the files
        # that are needed during the build process. Additionally, this works
        # around a bug in the 'cache' action that causes directories outside of
        # the workspace dir to be saved/restored incorrectly.
        run: echo "::set-env name=CARGO_HOME::$(pwd)/.cargo_home"

      - name: Cache
        uses: actions/cache@v2
        with:
          # Note: crates from the denoland/deno git repo always get rebuilt,
          # and their outputs ('deno', 'libdeno.rlib' etc.) are quite big,
          # so we cache only those subdirectories of target/{debug|release} that
          # contain the build output for crates that come from the registry.
          path: |-
            .cargo_home
            target/*/.*
            target/*/build
            target/*/deps
          key:
            ${{ matrix.config.os }}-${{ matrix.config.kind }}-${{ hashFiles('Cargo.lock') }}
          restore-keys: |
            ${{ matrix.config.os }}-${{ matrix.config.kind }}-

      - name: lint.py
        if: matrix.config.kind == 'lint'
        run: python ./tools/lint.py

      - name: test_format.py
        if: matrix.config.kind == 'lint'
        run: python ./tools/test_format.py

      - name: Build release
        if: |
          matrix.config.kind == 'test_release' ||
          matrix.config.kind == 'bench'
        run: cargo build --release --locked --all-targets

      - name: Build debug
        if: matrix.config.kind == 'test_debug'
        run: cargo build --locked --all-targets

      - name: Test release
        if: matrix.config.kind == 'test_release'
        run: cargo test --release --locked --all-targets

      - name: Test debug
        if: matrix.config.kind == 'test_debug'
        run: cargo test --locked --all-targets

      - name: Run Benchmarks
        if: matrix.config.kind == 'bench'
        run: python ./tools/benchmark.py --release

      - name: Post Benchmarks
        if: |
          matrix.config.kind == 'bench' &&
          github.repository == 'denoland/deno' &&
          github.ref == 'refs/heads/master'
        env:
          DENOBOT_PAT: ${{ secrets.DENOBOT_PAT }}
        run: |
          git clone --depth 1 -b gh-pages https://${DENOBOT_PAT}@github.com/denoland/benchmark_data.git gh-pages
          python ./tools/build_benchmark_jsons.py --release
          cd gh-pages
          git config user.email "propelml@gmail.com"
          git config user.name "denobot"
          git add .
          git commit --message "Update benchmarks"
          git push origin gh-pages

      - name: Worker info
        if: matrix.config.kind == 'bench'
        run: |
          cat /proc/cpuinfo
          cat /proc/meminfo

      - name: Pre-release (linux)
        if: |
          startsWith(matrix.config.os, 'ubuntu') &&
          matrix.config.kind == 'test_release'
        run: |
          cd target/release
          zip -r deno-x86_64-unknown-linux-gnu.zip deno
          ./deno types > lib.deno.d.ts

      - name: Pre-release (mac)
        if: |
          startsWith(matrix.config.os, 'macOS') &&
          matrix.config.kind == 'test_release'
        run: |
          cd target/release
          zip -r deno-x86_64-apple-darwin.zip deno

      - name: Pre-release (windows)
        if: |
          startsWith(matrix.config.os, 'windows') &&
          matrix.config.kind == 'test_release'
        run: |
          Compress-Archive -CompressionLevel Optimal -Force -Path target/release/deno.exe -DestinationPath target/release/deno-x86_64-pc-windows-msvc.zip

      - name: Release
        uses: softprops/action-gh-release@v1
        if: |
          matrix.config.kind == 'test_release' &&
          github.repository == 'denoland/deno' &&
          startsWith(github.ref, 'refs/tags/') &&
          !startsWith(github.ref, 'refs/tags/std/')
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          files: |
            target/release/deno-x86_64-pc-windows-msvc.zip
            target/release/deno-x86_64-unknown-linux-gnu.zip
            target/release/deno-x86_64-apple-darwin.zip
            target/release/deno_src.tar.gz
            target/release/lib.deno.d.ts
          draft: true

      - name: Publish
        if: |
          startsWith(matrix.config.os, 'ubuntu') &&
          matrix.config.kind == 'test_release' &&
          github.repository == 'denoland/deno' &&
          startsWith(github.ref, 'refs/tags/') &&
          !startsWith(github.ref, 'refs/tags/std/')
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: |
          cd core
          cargo publish
          cd ../deno_typescript
          sleep 30
          cargo publish
          cd ../cli
          sleep 30
          cargo publish