# ------------------------------------------------------------------------
#  Release workflow for multiple OSes (Linux x64, macOS x64, Windows x64)
# ------------------------------------------------------------------------
#       +---------------+                         +---------------+
#       |     BUILD     |    +---------------+    |    PUBLISH    |
#       +---------------+    |    RELEASE    |    +---------------+
#       | compile       |    +---------------+    | upload build  |
#       |   |           |    |               |    |           |   |
#       |  nix    --->  | -> |  get release  | -> |      <-- nix  |
#       |  mac ------>  |    |   (use old)   |    |     <--- mac  |
#       |  win   ---->  |    |               | <- |    <---- win  |
#       +---------------+    +---------------+    +---------------+
# ------------------------------------------------------------------------
#  Usage:
#  This workflow adds multi-os application builds when v-prefixed tags
#  pushed into the repository, e.g. git tag v9001 & git push --tags or
#  a new Github release is created with such tags.
# ------------------------------------------------------------------------

name: release
# run only when pushing v-prefixed SemVer tags (e.g. v1.0.0, v2.0.1, and etc.)
on:
  push:
    tags:
      - 'v*'
env:
  app-name: cloud-game
  app-arch: x86_64
jobs:
  # run app build for each OS in parallel
  build:
    name: Build
    strategy:
      matrix:
        os: [ ubuntu-latest, macos-latest, windows-latest ]
    runs-on: ${{ matrix.os }}
    env:
      release-dir: _release
    steps:
      - uses: actions/checkout@v3

      - uses: actions/setup-go@v4
        with:
          go-version: ^1.20

      - name: Get Linux dev libraries and tools
        if: matrix.os == 'ubuntu-latest'
        run: |
          sudo apt-get -qq update
          sudo apt-get -qq install -y make pkg-config libvpx-dev libx264-dev libopus-dev libsdl2-dev libgl1-mesa-glx

      - name: Get MacOS dev libraries and tools
        if: matrix.os == 'macos-latest'
        run: |
          brew install pkg-config libvpx x264 opus sdl2

      - name: Get Windows dev libraries and tools
        if: matrix.os == 'windows-latest'
        uses: msys2/setup-msys2@v2
        with:
          msystem: MINGW64
          path-type: inherit
          release: false
          install: >
            mingw-w64-x86_64-gcc
            mingw-w64-x86_64-pkgconf
            mingw-w64-x86_64-dlfcn
            mingw-w64-x86_64-libvpx
            mingw-w64-x86_64-opus
            mingw-w64-x86_64-x264-git
            mingw-w64-x86_64-SDL2

      - name: Build Windows app
        if: matrix.os == 'windows-latest'
        shell: msys2 {0}
        run: |
          make release RELEASE_DIR=${{ env.release-dir }} DLIB_SEARCH_PATTERN=/mingw.*dll CORE_EXT=*.dll

      - name: Build Linux app
        if: matrix.os == 'ubuntu-latest'
        run: |
          EXT_WFLAGS="-ldflags '-extldflags \"-Wl,-rpath=\$\$ORIGIN\"'" \
          make release RELEASE_DIR=${{ env.release-dir }} \
          DLIB_SEARCH_PATTERN="/lib/.*?lib\(x264\|vpx\|opus\).*?\ " \
          CORE_EXT=*_libretro.so

          cp ./scripts/install.sh ${{ env.release-dir }}

      - name: Build macOS app
        if: matrix.os == 'macos-latest'
        run: |
          # skip copy libs due to outrageous otool behaviour, depend on sys install
          # should be recursive + paths rewritten to @executable_path
          # lddx seems to be working ok
          go get github.com/jtanx/lddx
          make release RELEASE_DIR=${{ env.release-dir }} DLIB_ALTER=true DLIB_TOOL="lddx -r -c" CORE_EXT=*.dylib

      - name: Save built app for upload
        uses: actions/upload-artifact@v1
        with:
          name: ${{ runner.os }}
          path: ${{ env.release-dir }}

  release:
    name: Create or find Github release
    needs: build
    runs-on: ubuntu-latest
    steps:
    - name: Trying to find existing release
      uses: actions/github-script@0.9.0
      id: release_search
      with:
        github-token: ${{secrets.GITHUB_TOKEN}}
        result-encoding: string
        script: |
          try {
          const release = await github.repos.getReleaseByTag({
            owner: context.repo.owner,
            repo: context.repo.repo,
            tag: context.ref.replace('refs/tags/', '')
          });
          return release.data.upload_url;
          } catch (ignored) {}
          return '';
    - name: Create new release maybe?
      id: create_release
      if: steps.release_search.outputs.result == ''
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: ${{ github.ref }}
        release_name: ${{ github.ref }}
        draft: false
        prerelease: false
    # pass assets upload url of existing or new release
    # between jobs (VMs) through txt files
    - name: Get release upload URL
      run: |
        echo '${{ steps.create_release.outputs.upload_url }}${{ steps.release_search.outputs.result }}' > upload_url
    - name: Save release upload URL
      uses: actions/upload-artifact@v1
      with:
        name: upload_url
        path: ./

  publish:
    name: Publish
    needs: release
    strategy:
      matrix:
        # should be same as runner.os
        target-os: [Linux, macOS, Windows]
        include:
        - target-os: Linux
          compress: tar -zcf
          archive-ext: tar.gz
          archive-mime: tar
        - target-os: macOS
          compress: tar -zcf
          archive-ext: tar.gz
          archive-mime: tar
        - target-os: Windows
          compress: zip -qq -r
          archive-ext: zip
          archive-mime: zip
    runs-on: ubuntu-latest
    steps:
    - name: Get version tag
      id: get_version
      run: |
        echo ::set-output name=version::${GITHUB_REF#refs/tags/}
    - name: Get release upload url
      uses: actions/download-artifact@v1
      with:
        name: upload_url
    - name: Read release upload url
      id: upload_url
      run: |
          value=`cat upload_url/upload_url`
          echo "::set-output name=url::$value"
    - name: Get the build
      uses: actions/download-artifact@v1
      with:
         name: ${{ matrix.target-os }}
    - name: Compress the build
      id: compress
      # compress all the files without a parent dir
      # (cd into arch dir -> make archive in its parent -> go back)
      run: |
        cd ./${{ matrix.target-os }}
        archive='${{ env.app-name }}-${{ steps.get_version.outputs.version }}-${{ matrix.target-os }}-${{ env.app-arch }}'
        compress='${{ matrix.compress }} ../${archive,,}.${{ matrix.archive-ext }} *'
        eval $compress
        cd ../
        echo ::set-output name=archive_name::${archive,,}.${{ matrix.archive-ext }}
    - name: Upload release asset
      uses: actions/upload-release-asset@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        upload_url: ${{ steps.upload_url.outputs.url }}
        asset_path: ./${{ steps.compress.outputs.archive_name }}
        asset_name: ${{ steps.compress.outputs.archive_name }}
        asset_content_type: application/${{ matrix.archive-mime }}
