name: Plugin Build

on:
  push:
    paths-ignore:
      - '**.md'
    branches:
      - master
    tags:
      - '*'
  pull_request:
    paths-ignore:
      - '**.md'
    branches:
      - master

env:
  PLUGIN_NAME: SceneSwitcher
  LIB_NAME: advanced-scene-switcher

jobs:
  clang_check:
    name: 01 - Code Format Check
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Install clang-format
        run: sudo apt-get install -y clang-format-13

      - name: Run clang-format
        run: ./.github/scripts/check-format.sh && ./.github/scripts/check-changes.sh

      - name: Install cmake-format
        run: sudo pip install cmakelang

      - name: Run cmake-format
        run: ./.github/scripts/check-cmake.sh

  macos_build:
    name: 02 - macOS
    runs-on: macos-12
    strategy:
      fail-fast: true
      matrix:
        arch: [x86_64, arm64, universal]
    if: always()
    needs: [clang_check]
    outputs:
      commitHash: ${{ steps.setup.outputs.commitHash }}
    env:
      CODESIGN_IDENT: '-'
      CODESIGN_IDENT_INSTALLER: ''
      MACOSX_DEPLOYMENT_TARGET: '10.15'
    defaults:
      run:
        shell: zsh {0}
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          path: plugin
          submodules: recursive

      - name: Checkout obs-studio
        uses: actions/checkout@v3
        with:
          repository: 'obsproject/obs-studio'
          path: obs-studio
          fetch-depth: 0
          submodules: recursive

      - name: Setup Environment
        id: setup
        working-directory: ${{ github.workspace }}/plugin
        run: |
          ## SETUP ENVIRONMENT SCRIPT
          print '::group::Clean Homebrew Environment'
          typeset -a to_remove=()

          for formula (speexdsp curl php) {
            if [[ -d ${HOMEBREW_PREFIX}/opt/${formula} ]] to_remove+=(${formula})
          }

          if (( #to_remove > 0 )) brew uninstall --ignore-dependencies ${to_remove}
          print '::endgroup::'

          print '::group::Set up code signing'
          if [[ '${{ secrets.MACOS_SIGNING_APPLICATION_IDENTITY }}' != '' && \
                '${{ secrets.MACOS_SIGNING_INSTALLER_IDENTITY }}' != '' && \
                '${{ secrets.MACOS_SIGNING_CERT }}' != '' ]] {
            print 'haveCodesignIdent=true' >> $GITHUB_OUTPUT
          } else {
            print 'haveCodesignIdent=false' >> $GITHUB_OUTPUT
          }

          if [[ '${{ secrets.MACOS_NOTARIZATION_USERNAME }}' != '' && \
                '${{ secrets.MACOS_NOTARIZATION_PASSWORD }}' != '' ]] {
            print 'haveNotarizationUser=true' >> $GITHUB_OUTPUT
          } else {
            print 'haveNotarizationUser=false' >> $GITHUB_OUTPUT
          }
          print '::endgroup::'

          print "ccacheDate=$(date +"%Y-%m-%d")" >> $GITHUB_OUTPUT
          print "commitHash=${"$(git rev-parse HEAD)"[0,9]}" >> $GITHUB_OUTPUT
          echo "$PWD/.github/scripts" >> $GITHUB_PATH

      - name: Restore Compilation Cache
        id: ccache-cache
        uses: actions/cache@v3
        with:
          path: |
            ${{ github.workspace }}/.ccache
            ${{ github.workspace }}/plugin/deps/opencv/build_*
            ${{ github.workspace }}/plugin/deps/leptonica/build_*
            ${{ github.workspace }}/plugin/deps/tesseract/build*
          key: macos-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
          restore-keys: |
            macos-${{ matrix.arch }}-ccache-plugin-

      - name: Check for GitHub Labels
        id: seekingTesters
        if: ${{ github.event_name == 'pull_request' }}
        run: |
          if [[ -n "$(curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -s "${{ github.event.pull_request.url }}" | jq -e '.labels[] | select(.name == "Seeking Testers")')" ]] {
            print 'found=true' >> $GITHUB_OUTPUT
          } else {
            print 'found=false' >> $GITHUB_OUTPUT
          }

      - name: Install Apple Developer Certificate
        if: ${{ steps.setup.outputs.haveCodesignIdent == 'true' }}
        uses: apple-actions/import-codesign-certs@253ddeeac23f2bdad1646faac5c8c2832e800071
        with:
          keychain-password: ${{ github.run_id }}
          p12-file-base64: ${{ secrets.MACOS_SIGNING_CERT }}
          p12-password: ${{ secrets.MACOS_SIGNING_CERT_PASSWORD }}

      - name: Set Signing Identity
        if: ${{ steps.setup.outputs.haveCodesignIdent == 'true' }}
        run: |
          print "CODESIGN_IDENT=${{ secrets.MACOS_SIGNING_APPLICATION_IDENTITY }}" >> $GITHUB_ENV
          print "CODESIGN_IDENT_INSTALLER=${{ secrets.MACOS_SIGNING_INSTALLER_IDENTITY }}" >> $GITHUB_ENV

      - name: Build Plugin
        uses: ./plugin/.github/actions/build-plugin
        with:
          workingDirectory: ${{ github.workspace }}/plugin
          target: ${{ matrix.arch }}
          config: RelWithDebInfo
          codesign: 'true'
          codesignIdent: ${{ env.CODESIGN_IDENT }}

      - name: Run tests
        uses: ./plugin/.github/actions/run-tests
        with:
          workingDirectory: ${{ github.workspace }}/plugin
          target: ${{ matrix.arch }}

      - name: Package Plugin
        uses: ./plugin/.github/actions/package-plugin
        with:
          workingDirectory: ${{ github.workspace }}/plugin
          target: ${{ matrix.arch }}
          config: RelWithDebInfo
          codesign: ${{ steps.setup.outputs.haveCodesignIdent == 'true' }}
          notarize: ${{ startsWith(github.ref, 'refs/tags/') && steps.setup.outputs.haveNotarizationUser == 'true' }}
          codesignIdent: ${{ env.CODESIGN_IDENT }}
          installerIdent: ${{ env.CODESIGN_IDENT_INSTALLER }}
          codesignUser: ${{ secrets.MACOS_NOTARIZATION_USERNAME }}
          codesignPass: ${{ secrets.MACOS_NOTARIZATION_PASSWORD }}

      - name: Upload Installer Artifact
        if: ${{ success() }}
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.PLUGIN_NAME }}-macos-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}-installer
          path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}*-macos-${{ matrix.arch }}.pkg

      - name: Upload Build Artifact
        if: ${{ success() }}
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.PLUGIN_NAME }}-macos-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}
          path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}-*.zip

  linux_build:
    name: 02 - Linux
    runs-on: ubuntu-22.04
    strategy:
      fail-fast: true
      matrix:
        arch: [x86_64]
        portable: [true, false]
    if: always()
    needs: [clang_check]
    outputs:
      commitHash: ${{ steps.setup.outputs.commitHash }}
    defaults:
      run:
        shell: bash
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          path: plugin
          submodules: recursive

      - name: Checkout obs-studio
        uses: actions/checkout@v3
        with:
          repository: 'obsproject/obs-studio'
          path: obs-studio
          fetch-depth: 0
          submodules: recursive

      - name: Setup Environment
        working-directory: ${{ github.workspace }}/plugin
        id: setup
        run: |
          ## SETUP ENVIRONMENT SCRIPT
          echo "ccacheDate=$(date +"%Y-%m-%d")" >> $GITHUB_OUTPUT
          echo "commitHash=$(git rev-parse HEAD | cut -c1-9)" >> $GITHUB_OUTPUT
          echo "$PWD/.github/scripts" >> $GITHUB_PATH

      - name: Restore Compilation Cache
        id: ccache-cache
        uses: actions/cache@v3
        with:
          path: |
            ${{ github.workspace }}/.ccache
          key: linux-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
          restore-keys: |
            linux-${{ matrix.arch }}-ccache-plugin-

      - name: Check for GitHub Labels
        id: seekingTesters
        if: ${{ github.event_name == 'pull_request' }}
        run: |
          ## GITHUB LABEL SCRIPT
          if [[ -n "$(curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -s "${{ github.event.pull_request.url }}" | jq -e '.labels[] | select(.name == "Seeking Testers")')" ]]; then
            echo 'found=true' >> $GITHUB_OUTPUT
          else
            echo 'found=false' >> $GITHUB_OUTPUT
          fi

      - name: Build Plugin
        uses: ./plugin/.github/actions/build-plugin
        with:
          workingDirectory: ${{ github.workspace }}/plugin
          target: ${{ matrix.arch }}
          config: RelWithDebInfo
          portable: ${{ matrix.portable }}

      - name: Run tests
        uses: ./plugin/.github/actions/run-tests
        with:
          workingDirectory: ${{ github.workspace }}/plugin
          target: ${{ matrix.arch }}

      - name: Package Plugin
        uses: ./plugin/.github/actions/package-plugin
        with:
          workingDirectory: ${{ github.workspace }}/plugin
          target: ${{ matrix.arch }}
          config: RelWithDebInfo
          portable: ${{ matrix.portable }}

      - name: Upload Package Artifact
        if: ${{ matrix.portable }}
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.PLUGIN_NAME }}-linux-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}-portable
          path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}*-linux-${{ matrix.arch }}.*

      - name: Upload Build Artifact
        if: ${{ ! matrix.portable }}
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.PLUGIN_NAME }}-linux-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}
          path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}*-linux-${{ matrix.arch }}.*

  windows_build:
    name: 02 - Windows
    runs-on: windows-2022
    strategy:
      fail-fast: true
      matrix:
        arch: [x64]
    if: always()
    needs: [clang_check]
    outputs:
      commitHash: ${{ steps.setup.outputs.commitHash }}
    defaults:
      run:
        shell: pwsh
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          path: plugin
          submodules: recursive

      - name: Checkout obs-studio
        uses: actions/checkout@v3
        with:
          repository: 'obsproject/obs-studio'
          path: obs-studio
          fetch-depth: 0
          submodules: recursive

      - name: Setup Environment
        working-directory: ${{ github.workspace }}/plugin
        id: setup
        run: |
          ## SETUP ENVIRONMENT SCRIPT
          $CcacheDate = (Get-Date -Format "yyyy-M-d")
          "ccacheDate=${CcacheDate}" >> $env:GITHUB_OUTPUT
          $CommitHash = (git rev-parse HEAD)[0..8] -join ''
          "commitHash=${CommitHash}" >> $env:GITHUB_OUTPUT

      - name: Restore Compilation Cache
        id: ccache-cache
        uses: actions/cache@v3
        with:
          path: |
            ${{ github.workspace }}/.ccache
            ${{ github.workspace }}/plugin/deps/opencv/build_*
            ${{ github.workspace }}/plugin/deps/leptonica/build_*
            ${{ github.workspace }}/plugin/deps/tesseract/build*
          key: windows-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
          restore-keys: |
            windows-${{ matrix.arch }}-ccache-plugin-

      - name: Check for GitHub Labels
        id: seekingTesters
        working-directory: ${{ github.workspace }}/plugin
        if: ${{ github.event_name == 'pull_request' }}
        run: |
          ## GITHUB LABEL SCRIPT
          $LabelFound = try {
            $Params = @{
              Authentication = 'Bearer'
              Token = (ConvertTo-SecureString '${{ secrets.GITHUB_TOKEN }}' -AsPlainText)
              Uri = '${{ github.event.pull_request.url }}'
              UseBasicParsing = $true
            }

            (Invoke-RestMethod @Params).labels.name.contains('Seeking Testers')
          } catch {
            $false
          }

          "found=$(([string]${LabelFound}).ToLower())" >> $env:GITHUB_OUTPUT

      - name: Build Plugin
        uses: ./plugin/.github/actions/build-plugin
        with:
          workingDirectory: ${{ github.workspace }}/plugin
          target: ${{ matrix.arch }}
          config: RelWithDebInfo
          visualStudio: 'Visual Studio 17 2022'

      - name: Run tests
        uses: ./plugin/.github/actions/run-tests
        with:
          workingDirectory: ${{ github.workspace }}/plugin
          target: ${{ matrix.arch }}

      - name: Package Plugin
        uses: ./plugin/.github/actions/package-plugin
        with:
          workingDirectory: ${{ github.workspace }}/plugin
          target: ${{ matrix.arch }}
          config: RelWithDebInfo

      - name: Upload Build Artifact
        if: ${{ success() }}
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.PLUGIN_NAME }}-windows-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}
          path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}-*.zip

      - name: Package Plugin Installer
        uses: ./plugin/.github/actions/package-plugin
        with:
          workingDirectory: ${{ github.workspace }}/plugin
          target: ${{ matrix.arch }}
          config: RelWithDebInfo
          createInstaller: true

      - name: Upload Installer Artifact
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.PLUGIN_NAME }}-windows-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}-installer
          path: ${{ github.workspace }}/plugin/release/${{ env.LIB_NAME }}-*.exe

  make-release:
    name: 03 - Create and upload release
    runs-on: ubuntu-22.04
    if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
    needs: [macos_build, linux_build, windows_build]
    defaults:
      run:
        shell: bash
    steps:
      - name: Get Metadata
        id: metadata
        run: |
          ## METADATA SCRIPT
          echo "version=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT

      - name: Download build artifacts
        uses: actions/download-artifact@v3

      - name: Generate Checksums
        run: |
          ## CHECKSUM GENERATION SCRIPT
          shopt -s extglob
          echo "### Checksums" > ${{ github.workspace }}/CHECKSUMS.txt
          for file in ${{ github.workspace }}/**/@(*.pkg|*.exe|*.deb|*.zip); do
            echo "    ${file##*/}: $(sha256sum "${file}" | cut -d " " -f 1)" >> ${{ github.workspace }}/CHECKSUMS.txt
          done
          cat ${{ github.workspace }}/CHECKSUMS.txt

      - name: Create Release
        id: create_release
        uses: softprops/action-gh-release@v1
        with:
          draft: true
          prerelease: true
          tag_name: ${{ steps.metadata.outputs.version }}
          name: "${{ env.PLUGIN_NAME }} ${{ steps.metadata.outputs.version }}"
          body_path: ${{ github.workspace }}/CHECKSUMS.txt
          files: |
            ${{ github.workspace }}/**/*.zip
            ${{ github.workspace }}/**/*.exe
            ${{ github.workspace }}/**/*.deb
            ${{ github.workspace }}/**/*.pkg
