name: release
on:
  schedule:
    - cron: "0 0 * * *" # midnight UTC

  workflow_dispatch:

  push:
    branches:
      - release
      - trigger-nightly

env:
  CARGO_INCREMENTAL: 0
  CARGO_NET_RETRY: 10
  RUSTFLAGS: "-D warnings -W unreachable-pub"
  RUSTUP_MAX_RETRIES: 10
  FETCH_DEPTH: 0 # pull in the tags for the version string
  MACOSX_DEPLOYMENT_TARGET: 10.15
  CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc

jobs:
  dist:
    strategy:
      matrix:
        include:
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            code-target: win32-x64
          - os: windows-latest
            target: aarch64-pc-windows-msvc
            code-target: win32-arm64
          - os: ubuntu-20.04
            target: x86_64-unknown-linux-gnu
            code-target: linux-x64
          - os: ubuntu-20.04
            target: aarch64-unknown-linux-gnu
            code-target: linux-arm64
          - os: macos-11
            target: x86_64-apple-darwin
            code-target: darwin-x64
          - os: macos-11
            target: aarch64-apple-darwin
            code-target: darwin-arm64

    name: dist (${{ matrix.target }})
    runs-on: ${{ matrix.os }}

    env:
      RA_TARGET: ${{ matrix.target }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
        with:
          fetch-depth: ${{ env.FETCH_DEPTH }}

      # We need to disable the existing toolchain to avoid updating rust-docs
      # which takes a long time. The fastest way to do this is to rename the
      # existing folder, as deleting it takes about as much time as not doing
      # anything and just updating rust-docs.
      - name: Rename existing Rust toolchain
        if: matrix.os == 'windows-latest'
        run: Rename-Item C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc.old

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          target: ${{ matrix.target }}
          profile: minimal
          override: true

      - name: Install Rust library source
        if: matrix.target == 'x86_64-unknown-linux-gnu'
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          target: ${{ matrix.target }}
          profile: minimal
          override: true
          components: rust-src

      - name: Install Node.js
        uses: actions/setup-node@v1
        with:
          node-version: 14.x

      - name: Update apt repositories
        if: matrix.target == 'aarch64-unknown-linux-gnu'
        run: sudo apt-get update

      - name: Install target toolchain
        if: matrix.target == 'aarch64-unknown-linux-gnu'
        run: sudo apt-get install gcc-aarch64-linux-gnu

      - name: Dist
        run: cargo xtask dist --client-patch-version ${{ github.run_number }}

      - run: npm ci
        working-directory: editors/code

      - name: Package Extension (release)
        if: github.ref == 'refs/heads/release'
        run: npx vsce package -o "../../dist/rust-analyzer-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }}
        working-directory: editors/code

      - name: Package Extension (nightly)
        if: github.ref != 'refs/heads/release'
        run: npx vsce package -o "../../dist/rust-analyzer-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} --pre-release
        working-directory: editors/code

      - if: matrix.target == 'x86_64-unknown-linux-gnu'
        run: rm -rf editors/code/server

      - if: matrix.target == 'x86_64-unknown-linux-gnu' && github.ref == 'refs/heads/release'
        run: npx vsce package -o ../../dist/rust-analyzer-no-server.vsix
        working-directory: editors/code

      - if: matrix.target == 'x86_64-unknown-linux-gnu' && github.ref != 'refs/heads/release'
        run: npx vsce package -o ../../dist/rust-analyzer-no-server.vsix --pre-release
        working-directory: editors/code

      - name: Run analysis-stats on rust-analyzer
        if: matrix.target == 'x86_64-unknown-linux-gnu'
        run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats .

      - name: Run analysis-stats on rust std library
        if: matrix.target == 'x86_64-unknown-linux-gnu'
        run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std

      - name: Upload artifacts
        uses: actions/upload-artifact@v1
        with:
          name: dist-${{ matrix.target }}
          path: ./dist

  dist-x86_64-unknown-linux-musl:
    name: dist (x86_64-unknown-linux-musl)
    runs-on: ubuntu-latest
    env:
      RA_TARGET: x86_64-unknown-linux-musl
      # For some reason `-crt-static` is not working for clang without lld
      RUSTFLAGS: "-C link-arg=-fuse-ld=lld -C target-feature=-crt-static"
    container:
      image: rust:alpine
      volumes:
        - /usr/local/cargo/registry

    steps:
      - name: Install dependencies
        run: apk add --no-cache git clang lld musl-dev nodejs npm

      - name: Checkout repository
        uses: actions/checkout@v2
        with:
          fetch-depth: ${{ env.FETCH_DEPTH }}

      - name: Dist
        run: cargo xtask dist --client-patch-version ${{ github.run_number }}

      - run: npm ci
        working-directory: editors/code

      - name: Package Extension (release)
        if: github.ref == 'refs/heads/release'
        run: npx vsce package -o "../../dist/rust-analyzer-alpine-x64.vsix" --target alpine-x64
        working-directory: editors/code

      - name: Package Extension (nightly)
        if: github.ref != 'refs/heads/release'
        run: npx vsce package -o "../../dist/rust-analyzer-alpine-x64.vsix" --target alpine-x64 --pre-release
        working-directory: editors/code

      - run: rm -rf editors/code/server

      - name: Upload artifacts
        uses: actions/upload-artifact@v1
        with:
          name: dist-x86_64-unknown-linux-musl
          path: ./dist

  publish:
    name: publish
    runs-on: ubuntu-latest
    needs: ["dist", "dist-x86_64-unknown-linux-musl"]
    steps:
      - name: Install Nodejs
        uses: actions/setup-node@v1
        with:
          node-version: 14.x

      - run: echo "TAG=$(date --iso -u)" >> $GITHUB_ENV
        if: github.ref == 'refs/heads/release'
      - run: echo "TAG=nightly" >> $GITHUB_ENV
        if: github.ref != 'refs/heads/release'
      - run: 'echo "TAG: $TAG"'

      - name: Checkout repository
        uses: actions/checkout@v2
        with:
          fetch-depth: ${{ env.FETCH_DEPTH }}

      - run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
      - run: 'echo "HEAD_SHA: $HEAD_SHA"'

      - uses: actions/download-artifact@v1
        with:
          name: dist-aarch64-apple-darwin
          path: dist
      - uses: actions/download-artifact@v1
        with:
          name: dist-x86_64-apple-darwin
          path: dist
      - uses: actions/download-artifact@v1
        with:
          name: dist-x86_64-unknown-linux-gnu
          path: dist
      - uses: actions/download-artifact@v1
        with:
          name: dist-x86_64-unknown-linux-musl
          path: dist
      - uses: actions/download-artifact@v1
        with:
          name: dist-aarch64-unknown-linux-gnu
          path: dist
      - uses: actions/download-artifact@v1
        with:
          name: dist-x86_64-pc-windows-msvc
          path: dist
      - uses: actions/download-artifact@v1
        with:
          name: dist-aarch64-pc-windows-msvc
          path: dist
      - run: ls -al ./dist

      - name: Publish Release
        uses: ./.github/actions/github-release
        with:
          files: "dist/*"
          name: ${{ env.TAG }}
          token: ${{ secrets.GITHUB_TOKEN }}

      - run: rm dist/rust-analyzer-no-server.vsix

      - run: npm ci
        working-directory: ./editors/code

      - name: Publish Extension (release)
        if: github.ref == 'refs/heads/release' && github.repository == 'rust-analyzer/rust-analyzer'
        working-directory: ./editors/code
        # token from https://dev.azure.com/rust-analyzer/
        run: npx vsce publish --pat ${{ secrets.MARKETPLACE_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix

      - name: Publish Extension (nightly)
        if: github.ref != 'refs/heads/release' && github.repository == 'rust-analyzer/rust-analyzer'
        working-directory: ./editors/code
        run: npx vsce publish --pat ${{ secrets.MARKETPLACE_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix --pre-release