#
# Logisim-evolution nightly builder
# https://github.com/logisim-evolution/logisim-evolution
#
# Cron driven Github Action builder, intended to create nightly builds
# from Logisim-evolution's "main" branch. It assumes to be invoked
# daily (once per 24 hrs) and skips building if there was no repo activity
# during last 24 hours.
#
# Marcin Orlowski
#

name: "Nightly"
on:
  # To enable "nightly" on closing pull requests uncomment the following:
  #pull_request:
  #  branches: [ main ]
  #  types: [ closed ]
  schedule:
    # every day at midnight
    - cron: "0 0 * * *"

env:
  JDK_VERSION: 21
  JDK_DISTRO: 'temurin'

jobs:
  git_check:
    name: "Any changes since last run?"
    runs-on: ubuntu-latest

    # Export build vars so other steps can use it.
    outputs:
      # Shall we build anything?
      run_build: ${{ steps.filter.outputs.run_build }}
      # Base application name and version (read from gradle.properties).
      lse_name: ${{ steps.filter.outputs.lse_name }}
      lse_version: ${{ steps.filter.outputs.lse_version }}
      # Same as lse_version but with with no "unstable suffix (i.e. no "-dev" etc)
      lse_version_short: ${{ steps.filter.outputs.lse_version_short }}
      # Base name for final daily build files.
      base_name: ${{ steps.filter.outputs.base_name }}

    steps:
      # https://github.com/marketplace/actions/checkout
      - name: 'Checkout sources'
        uses: actions/checkout@v6

      # Check if latest commit is less than a day.
      - name: "ANY CHANGES SINCE LAST BUILD?"
        id: filter
        continue-on-error: true
        # if: ${{ github.event_name == 'schedule' }}
        run: |
          # Have no mercy.
          set -euo pipefail

          # Short name for branch in which action was triggered.
          declare -r branch_name="${GITHUB_BASE_REF:-${GITHUB_REF#refs/heads/}}"
          echo "Triggered for branch: ${branch_name}"

          # Get SHA of last commit in that branch.
          declare -r last_commit_sha="$(git rev-parse HEAD)"

          # Let's see if we have any commits in last 24 hours.
          if [[ -n "$(git rev-list --after="24 hours" ${last_commit_sha})" ]]; then
            echo "run_build=true" >> $GITHUB_OUTPUT
          else
            echo "*** No code changes since yesterday. Skipping."
          fi

          # I need to export current version, even if is incorrect for main branch as it
          # is part of produced artifacts. We will strip it prior uploading anyway.

          # LSe version string can have additional "unstable" indicator (i.e. "-dev") but
          # we are forced to drop the "-" as some packages do not allow it. So in fact
          # Gradle artifact for "1.2.3-dev" uses "1.2.3dev" in file names, so we need to
          # consider that whlie looking for artifacts (i.e. for upload).
          declare -r version_prop=$(grep '^version\s*=.*' gradle.properties | awk '{print $3}')

          # Remove "-" (if present) from version string.
          declare -r lse_version=$(echo "${version_prop}" | awk '{gsub("-","", $0); print}')
          echo "lse_version=${lse_version}" >> $GITHUB_OUTPUT

          # Version string with suffix stripped. Required for some packages/platforms.
          declare -r lse_version_short=$(echo "${version_prop}" | awk '{ split($0, v, "-")} {print v[1]}')
          echo "lse_version_short=${lse_version_short}" >> $GITHUB_OUTPUT

          declare -r lse_name="$(fgrep name gradle.properties | awk '{print $3}')"
          echo "lse_name=${lse_name}" >> $GITHUB_OUTPUT

          # Base name for uploaded artifacts.
          echo "base_name=${lse_name}_${branch_name}_$(date +%Y%m%d)" >> $GITHUB_OUTPUT

  # ###############################################################################################

  # Building for Linux.
  build_linux:
    name: 'Linux build'
    runs-on: ubuntu-latest
    # Will run only if git_check determined it is needed.
    needs: git_check
    if: needs.git_check.outputs.run_build == 'true'
    steps:
      # https://github.com/z0al/dependent-issues
      - name: 'Checkout branch: ${{ env.GITHUB_REF }}'
        uses: actions/checkout@v6
        with:
          ref: 'main'

      - name: 'Build Snap package'
        # https://github.com/snapcore/action-build
        uses: snapcore/action-build@v1
        id: snapcraft

      - name: 'Upload *.snap artifact.'
        uses: actions/upload-artifact@v6
        if: success()
        with:
           path: ${{ steps.snapcraft.outputs.snap }}
           name: ${{ needs.git_check.outputs.base_name }}_amd64.snap

#      - name: 'Pushing *.snap to snapcraft.io'
#        # https://github.com/snapcore/action-publish
#        uses: snapcore/action-publish@v1
#        if: success()
#        env:
#          # Obtain Snapcraft.io store token:
#          # $ snapcraft export-login --snaps=logisim-evolution --acls package_access,package_push,package_update,package_release token.txt
#          # then open Github repository settings and add new secred named SNAPCRAFT_STORE_TOKEN with the value of token.txt
#          SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_TOKEN }}
#        with:
#          snap: ${{ steps.snapcraft.outputs.snap }}
#          release: edge

        # ###########################################################################################

      - name: Set up JDK ${{ env.JDK_VERSION }} ${{ env.JDK_DISTRO }}
        uses: actions/setup-java@v5
        with:
          java-version: ${{ env.JDK_VERSION }}
          distribution: ${{ env.JDK_DISTRO }}

      # ###########################################################################################

      - name: 'Build binary JAR'
        run: |
          # Have no mercy.
          set -euo pipefail

          chmod +x gradlew
          ./gradlew shadowJar

      # https://github.com/marketplace/actions/upload-a-build-artifact
      - name: 'Upload binary JAR'
        uses: actions/upload-artifact@v6
        if: success()
        with:
          path: build/libs/${{ needs.git_check.outputs.lse_name }}-${{ needs.git_check.outputs.lse_version }}-all.jar
          name: ${{ needs.git_check.outputs.base_name }}-all-jdk${{ env.JDK_VERSION }}.jar

      # ###########################################################################################

      - name: 'Build DEB'
        run: |
          # Have no mercy.
          set -euo pipefail

          chmod +x gradlew
          ./gradlew createDeb -x checkstyleMain -x checkstyleTest

      - name: 'Upload *.deb'
        uses: actions/upload-artifact@v6
        if: success()
        with:
          path: build/dist/${{ needs.git_check.outputs.lse_name }}_${{ needs.git_check.outputs.lse_version }}_amd64.deb
          name: ${{ needs.git_check.outputs.base_name }}_amd64.deb

        # ###########################################################################################

      - name: 'Build RPM'
        run: |
          # Have no mercy.
          set -euo pipefail

          chmod +x gradlew
          # Needs rpm package, but it should be installed already.
          ./gradlew createRpm -x checkstyleMain -x checkstyleTest

      - name: 'Upload *.rpm'
        uses: actions/upload-artifact@v6
        if: success()
        with:
          path: build/dist/${{ needs.git_check.outputs.lse_name }}-${{ needs.git_check.outputs.lse_version }}-1.x86_64.rpm
          name: ${{ needs.git_check.outputs.base_name }}.x86_64.rpm

        # ###########################################################################################

      - name: 'Build sources JAR'
        run: |
          # Have no mercy.
          set -euo pipefail

          chmod +x gradlew
          # Need to clean to have just one JAR or createDistDir task would fail.
          ./gradlew clean
          ./gradlew sourcesJar

      - name: 'Upload sources JAR'
        uses: actions/upload-artifact@v6
        if: success()
        with:
          path: build/libs/${{ needs.git_check.outputs.lse_name }}-${{ needs.git_check.outputs.lse_version }}-src.jar
          name: ${{ needs.git_check.outputs.base_name }}-src.jar

  # ###############################################################################################

  # Building for Linux Arm.
  build_linux_arm:
    name: 'Linux Arm build'
    runs-on: ubuntu-22.04-arm
    # Will run only if git_check determined it is needed.
    needs: git_check
    if: needs.git_check.outputs.run_build == 'true'
    steps:
      # https://github.com/z0al/dependent-issues
      - name: 'Checkout branch: ${{ env.GITHUB_REF }}'
        uses: actions/checkout@v6
        with:
          ref: 'main'

      - name: Set up JDK ${{ env.JDK_VERSION }} ${{ env.JDK_DISTRO }}
        uses: actions/setup-java@v5
        with:
          java-version: ${{ env.JDK_VERSION }}
          distribution: ${{ env.JDK_DISTRO }}

      # ###########################################################################################

      - name: 'Build Arm DEB'
        run: |
          # Have no mercy.
          set -euo pipefail

          chmod +x gradlew
          ./gradlew createDeb -x checkstyleMain -x checkstyleTest

      - name: 'Upload *arm64.deb'
        uses: actions/upload-artifact@v6
        if: success()
        with:
          path: build/dist/${{ needs.git_check.outputs.lse_name }}_${{ needs.git_check.outputs.lse_version }}_arm64.deb
          name: ${{ needs.git_check.outputs.base_name }}_arm64.deb

        # ###########################################################################################

      - name: 'Build Arm RPM'
        run: |
          # Have no mercy.
          set -euo pipefail

          chmod +x gradlew
          # Needs rpm package, but it should be installed already.
          ./gradlew createRpm -x checkstyleMain -x checkstyleTest

      - name: 'Upload *aarch64.rpm'
        uses: actions/upload-artifact@v6
        if: success()
        with:
          path: build/dist/${{ needs.git_check.outputs.lse_name }}-${{ needs.git_check.outputs.lse_version }}-1.aarch64.rpm
          name: ${{ needs.git_check.outputs.base_name }}.aarch64.rpm

  # ###############################################################################################

  # Building for macOS.
  build_macos:
    name: 'macOS build'
    runs-on: macos-latest
    # Will run only if git_check determined it is needed.
    needs: git_check
    if: needs.git_check.outputs.run_build == 'true'

    steps:
      # https://github.com/marketplace/actions/checkout
      - name: "Checkout sources"
        uses: actions/checkout@v6
        with:
          ref: ${{ github.ref_name }}

      - name: Set up aarch64 JDK ${{ env.JDK_VERSION }} ${{ env.JDK_DISTRO }}
        uses: actions/setup-java@v5
        with:
          java-version: ${{ env.JDK_VERSION }}
          distribution: ${{ env.JDK_DISTRO }}

      - name: "Build aarch64 DMG"
        run: |
          # Have no mercy.
          set -euo pipefail

          chmod +x gradlew
          ./gradlew createDmg -x checkstyleMain -x checkstyleTest

      - name: 'Upload aarch64 DMG'
        uses: actions/upload-artifact@v6
        if: success()
        with:
          path: build/dist/${{ needs.git_check.outputs.lse_name }}-${{ needs.git_check.outputs.lse_version }}-aarch64.dmg
          name: ${{ needs.git_check.outputs.base_name }}-aarch64.dmg

      - name: Set up x86_64 JDK ${{ env.JDK_VERSION }} ${{ env.JDK_DISTRO }}
        uses: actions/setup-java@v5
        with:
          java-version: ${{ env.JDK_VERSION }}
          distribution: ${{ env.JDK_DISTRO }}
          architecture: "x64"

      - name: "Build x86_64 DMG"
        run: |
          # Have no mercy.
          set -euo pipefail

          chmod +x gradlew
          ./gradlew createDmg -x checkstyleMain -x checkstyleTest

      - name: 'Upload x86_64 DMG'
        uses: actions/upload-artifact@v6
        if: success()
        with:
          path: build/dist/${{ needs.git_check.outputs.lse_name }}-${{ needs.git_check.outputs.lse_version }}-x86_64.dmg
          name: ${{ needs.git_check.outputs.base_name }}-x86_64.dmg

  # ###############################################################################################

  # Building for Windows.
  build_windows:
    name: 'Windows build'
    runs-on: windows-latest
    # Will run only if git_check determined it is needed.
    needs: git_check
    if: needs.git_check.outputs.run_build == 'true'

    steps:
      # https://github.com/marketplace/actions/checkout
      - name: "Checkout sources"
        uses: actions/checkout@v6
      - name: Set up JDK ${{ env.JDK_VERSION }} ${{ env.JDK_DISTRO }}
        uses: actions/setup-java@v5
        with:
          java-version: ${{ env.JDK_VERSION }}
          distribution: ${{ env.JDK_DISTRO }}

      - name: "Build MSI"
        run: .\gradlew.bat createMsi -x checkstyleMain -x checkstyleTest

      - name: "Upload MSI"
        uses: actions/upload-artifact@v6
        if: success()
        with:
          # NOTE: Gradle builder creates MSI file that always uses short version format in file name.
          path: build\dist\${{ needs.git_check.outputs.lse_name }}-${{ needs.git_check.outputs.lse_version_short }}-amd64.msi
          name: ${{ needs.git_check.outputs.base_name }}-amd64.msi

      - name: "Build self-contained archive for Windows"
        run: .\gradlew.bat createWindowsPortableZip -x checkstyleMain -x checkstyleTest

      - name: "Upload self-contained archive for Windows"
        uses: actions/upload-artifact@v6
        if: success()
        with:
          path: build\dist\${{ needs.git_check.outputs.lse_name }}-${{ needs.git_check.outputs.lse_version }}-windows-amd64.zip
          name: ${{ needs.git_check.outputs.base_name }}-windows-amd64.zip

  # ###############################################################################################

#  This is currently disabled because JPackage uses the WiX Toolset which is not installed.
#  # Building for Windows Arm.
#  build_windows_arm:
#    name: 'Windows Arm build'
#    runs-on: windows-11-arm
#    # Will run only if git_check determined it is needed.
#    needs: git_check
#    if: needs.git_check.outputs.run_build == 'true'
#
#    steps:
#      # https://github.com/marketplace/actions/checkout
#      - name: "Checkout sources"
#        uses: actions/checkout@v6
#      - name: Set up JDK ${{ env.JDK_VERSION }} ${{ env.JDK_DISTRO }}
#        uses: actions/setup-java@v5
#        with:
#          java-version: ${{ env.JDK_VERSION }}
#          distribution: ${{ env.JDK_DISTRO }}
#
#      - name: "Build Arm MSI"
#        run: .\gradlew.bat createMsi -x checkstyleMain -x checkstyleTest
#
#      - name: "Upload Arm MSI"
#        uses: actions/upload-artifact@v6
#        if: success()
#        with:
#          # NOTE: Gradle builder creates AArch64 file that always uses short version format in file name.
#          path: build\dist\${{ needs.git_check.outputs.lse_name }}-${{ needs.git_check.outputs.lse_version_short }}-aarch64.msi
#          name: ${{ needs.git_check.outputs.base_name }}-aarch64.msi
