# This workflow is a clone of "deployment.yml"
# The difference is that this workflow uses JDK early access builds (jdk-ea) to check the build of JabRef
# We separated this from the main workflow as we do not want to check on each PR if the JDK build, but only on main
name: Deployment (JDK early access builds)

on:
  schedule:
    - cron: "0 18 * * 1"
  pull_request:
    paths:
      - .github/workflows/deployment-jdk-ea.yml
      - build.gradle
  workflow_dispatch:
    inputs:
      notarization:
        type: boolean
        required: false
        default: false

env:
  SpringerNatureAPIKey: ${{ secrets.SpringerNatureAPIKey }}
  AstrophysicsDataSystemAPIKey: ${{ secrets.AstrophysicsDataSystemAPIKey }}
  IEEEAPIKey: ${{ secrets.IEEEAPIKey }}
  BiodiversityHeritageApiKey: ${{ secrets.BiodiversityHeritageApiKey}}
  OSXCERT: ${{ secrets.OSX_SIGNING_CERT }}
  GRADLE_OPTS: -Xmx4g -Dorg.gradle.vfs.watch=false
  JAVA_OPTS: -Xmx4g

concurrency:
  group: "${{ github.workflow }}-${{ github.head_ref || github.ref }}"
  cancel-in-progress: true

jobs:
  build:
    if: github.repository_owner == 'JabRef'
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest, buildjet-8vcpu-ubuntu-2204-arm]
        jdk: [23]
        javafx: [24]
        include:
          - os: ubuntu-latest
            displayName: linux
            archivePortable: tar -c -C build/distribution JabRef | pigz --rsyncable > build/distribution/JabRef-portable_linux.tar.gz && rm -R build/distribution/JabRef
          - os: windows-latest
            displayName: windows
            archivePortable: 7z a -r build/distribution/JabRef-portable_windows.zip ./build/distribution/JabRef && rm -R build/distribution/JabRef
          - os: buildjet-8vcpu-ubuntu-2204-arm
            displayName: "linux-arm"
            archivePortable: "tar -c -C build/distribution JabRef | pigz --rsyncable > build/distribution/JabRef-portable_linux-arm64.tar.gz && rm -R build/distribution/JabRef"
          - os: macos-latest
            displayName: macOS
            archivePortable: "brew install pigz && tar -c -C build/distribution JabRef.app | pigz --rsyncable > build/distribution/JabRef-portable_macos.tar.gz && rm -R build/distribution/JabRef.app"
    runs-on: ${{ matrix.os }}
    outputs:
      major: ${{ steps.gitversion.outputs.Major }}
      minor: ${{ steps.gitversion.outputs.Minor }}
      branchname: ${{ steps.gitversion.outputs.branchName }}
    name: "JDK ${{ matrix.jdk }}: ${{ matrix.displayName }} JavaFX ${{ matrix.javafx }}"
    steps:
      - name: Check secrets presence
        id: checksecrets
        shell: bash
        run: |
          if [ "$BUILDJABREFPRIVATEKEY" == "" ]; then
            echo "secretspresent=NO" >> $GITHUB_OUTPUT
            echo "❌ Secret BUILDJABREFPRIVATEKEY not present"
          else
            echo "secretspresent=YES" >> $GITHUB_OUTPUT
            echo "✔️ Secret BUILDJABREFPRIVATEKEY present"
          fi
        env:
          BUILDJABREFPRIVATEKEY: ${{ secrets.buildJabRefPrivateKey }}
      - name: Fetch all history for all tags and branches
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          submodules: 'true'
          show-progress: 'false'
      - name: Install pigz and cache (linux)
        if: (matrix.os == 'ubuntu-latest') || (matrix.os == 'buildjet-8vcpu-ubuntu-2204-arm')
        uses: awalsh128/cache-apt-pkgs-action@master
        with:
          packages: pigz
          version: 1.0
      - name: Install GitVersion
        uses: gittools/actions/gitversion/setup@v3.0.2
        with:
          versionSpec: "5.x"
      - name: Run GitVersion
        id: gitversion
        uses: gittools/actions/gitversion/execute@v3.0.2

      # JDK
      - name: 'Set up JDK ${{ matrix.jdk }}'
        uses: actions/setup-java@v4
        with:
          java-version: ${{ matrix.jdk }}
          distribution: 'temurin'
      - name: 'Set JDK${{ matrix.jdk }} env var'
        shell: bash
        run: echo "JDK${{ matrix.jdk }}=$JAVA_HOME" >> $GITHUB_ENV
      - name: 'Set JDK${{ matrix.jdk }} in toolchain (linux, Windows)'
        if: (matrix.os != 'macos-latest')
        shell: bash
        run: |
          sed -i 's/JavaLanguageVersion.of(.*)/JavaLanguageVersion.of(${{ matrix.jdk }})/' build.gradle
          sed -i 's/JavaVersion.VERSION_(.*)/JavaVersion.VERSION_(${{ matrix.jdk }})/' build.gradle
      - name: 'Set JDK${{ matrix.jdk }} in toolchain (macOS)'
        if: (matrix.os == 'macos-latest')
        shell: bash
        run: |
          sed -i'.bak' 's/JavaLanguageVersion.of(.*)/JavaLanguageVersion.of(${{ matrix.jdk }})/' build.gradle
          sed -i'.bak' 's/JavaVersion.VERSION_(.*)/JavaVersion.VERSION_(${{ matrix.jdk }})/' build.gradle

      # JavaFX
      - name: Download and extract JavaFX ${{ matrix.javafx }}
        if: (matrix.os != 'buildjet-8vcpu-ubuntu-2204-arm')
        shell: bash
        run: |
          cd javafx
          curl --no-progress-meter https://jdk.java.net/javafx${{ matrix.javafx }}/ > javafx.html

          case "${{ matrix.os }}" in
            "ubuntu-latest")
              OS="linux"
              EXTRACT="tar xzf *.tar.gz"
              EXT="tar.gz"
              ;;
            "buildjet-8vcpu-ubuntu-2204-arm")
              OS="linux"
              EXTRACT="tar xzf *.tar.gz"
              EXT="tar.gz"
              echo "There are no ARM EA builds"
              exit 0
              ;;
            "windows-latest")
              OS="windows"
              EXTRACT="unzip -qq *.zip"
              EXT="zip"
              ;;
            "macos-latest")
              OS="macos"
              EXTRACT="tar xzf *.tar.gz"
              EXT="tar.gz"
              ;;
            *)
              echo "Unsupported OS"
              exit 1
              ;;
          esac
          echo "OS set to $OS"

          URL_SDK=$(grep -o "https://download.java.net/java/.*/javafx.*${OS}-x64_bin-sdk.${EXT}" javafx.html | head -n 1)
          echo "Downloading $URL_SDK..."
          curl -OJ --no-progress-meter $URL_SDK
          $EXTRACT
          rm *.$EXT

          URL_JMODS=$(grep -o "https://download.java.net/java/.*/javafx.*${OS}-x64_bin-jmods.${EXT}" javafx.html | head -n 1)
          echo "Downloading $URL_JMODS..."
          curl -OJ --no-progress-meter $URL_JMODS
          $EXTRACT
          rm *.$EXT
      - name: 'Set JavaFX ${{ matrix.javafx }} (linux, Windows)'
        if: (matrix.os != 'macos-latest') && (matrix.os != 'buildjet-8vcpu-ubuntu-2204-arm')
        run: |
          sed -i '/javafx {/{n;s#version = ".*"#sdk = "javafx/javafx-sdk-${{ matrix.javafx }}"#}' build.gradle
          sed -i "s#jlink {#jlink { addExtraModulePath 'javafx/javafx-jmods-${{ matrix.javafx }}'#" build.gradle
          cat build.gradle
      - name: 'Set JavaFX ${{ matrix.javafx }} (macOS)'
        if: (matrix.os == 'macos-latest') && (matrix.os != 'buildjet-8vcpu-ubuntu-2204-arm')
        run: |
          sed -i '.bak' -e '/javafx {/{n' -e 's#version = ".*"#sdk = "javafx/javafx-sdk-${{ matrix.javafx }}"#;}' build.gradle
          sed -i '.bak' -e "s#jlink {#jlink { addExtraModulePath 'javafx/javafx-jmods-${{ matrix.javafx }}'#" build.gradle
          cat build.gradle
      - name: 'Set JavaFX ${{ matrix.javafx }} (linux-arm)'
        if: (matrix.os == 'buildjet-8vcpu-ubuntu-2204-arm')
        # No JavaFX EA build for ARM at https://jdk.java.net/javafx23/, therefore using Maven Central artifact
        run: |
          curl -s "https://search.maven.org/solrsearch/select?q=g:org.openjfx+AND+a:javafx&rows=10&core=gav" > /tmp/versions.json
          jq '[.response.docs[] | select(.v | test(".*-ea\\+.*")) | select(.v | test("^17|^18|^19|^20|^21|^22") | not) | {version: .v}] | group_by(.version | capture("^(?<major>\\d+).*").major) | map(max_by(.version))' < /tmp/versions.json > /tmp/versions-latest.json
          JAVAFX=$(jq -r '.[-1].version' /tmp/versions-latest.json)
          echo "Using JavaFX ${JAVAFX}"
          sed -i "/javafx {/{n;s#version = \".*\"#version = \"${JAVAFX}\"#}" build.gradle && cat build.gradle

      # Gradle
      - name: Set up JDK
        uses: actions/setup-java@v4
        with:
          java-version: 21
          distribution: 'temurin'
      - name: Set up Gradle
        uses: gradle/actions/setup-gradle@v4
        with:
          gradle-home-cache-cleanup: true
      - name: Prepare merged jars and modules dir
        # prepareModulesDir is executing a build, which should run through even if no upload to builds.jabref.org is made
        if: (steps.checksecrets.outputs.secretspresent == 'NO')
        run: ./gradlew -i -PprojVersion="${{ steps.gitversion.outputs.AssemblySemVer }}" -PprojVersionInfo="${{ steps.gitversion.outputs.InformationalVersion }}" prepareModulesDir
      - name: Set up macOS key chain
        if: (matrix.os == 'macos-latest') && (steps.checksecrets.outputs.secretspresent == 'YES')
        uses: slidoapp/import-codesign-certs@1923310662e8682dd05b76b612b53301f431cd5d
        with:
          p12-file-base64: ${{ secrets.OSX_SIGNING_CERT }}
          p12-password: ${{ secrets.OSX_CERT_PWD }}
          keychain-password: jabref
      - name: Set up macOS key chain for app id cert
        if: (matrix.os == 'macos-latest') && (steps.checksecrets.outputs.secretspresent == 'YES')
        uses: slidoapp/import-codesign-certs@1923310662e8682dd05b76b612b53301f431cd5d
        with:
          p12-file-base64: ${{ secrets.OSX_SIGNING_CERT_APPLICATION }}
          p12-password: ${{ secrets.OSX_CERT_PWD }}
          create-keychain: false
          keychain-password: jabref
      - name: Build runtime image and installer
        shell: bash
        run: ./gradlew -i -PprojVersion="${{ steps.gitversion.outputs.AssemblySemVer }}" -PprojVersionInfo="${{ steps.gitversion.outputs.InformationalVersion }}" jpackage jlinkZip
      - name: Package application image
        shell: bash
        run: ${{ matrix.archivePortable }}
      - name: Rename files
        if: (matrix.os != 'macos-latest')
        shell: pwsh
        run: |
          get-childitem -Path build/distribution/* | rename-item -NewName {$_.name -replace "${{ steps.gitversion.outputs.AssemblySemVer }}","${{ steps.gitversion.outputs.Major }}.${{ steps.gitversion.outputs.Minor }}"}
          get-childitem -Path build/distribution/* | rename-item -NewName {$_.name -replace "portable","${{ steps.gitversion.outputs.Major }}.${{ steps.gitversion.outputs.Minor }}-portable"}
      - name: Repack deb file for Debian
        if: (matrix.os == 'ubuntu-latest')
        shell: bash
        run: |
          cd build/distribution
          ar x jabref_${{ steps.gitversion.outputs.Major }}.${{ steps.gitversion.outputs.Minor }}_amd64.deb
          zstd -d < control.tar.zst | xz > control.tar.xz
          zstd -d < data.tar.zst | xz > data.tar.xz
          ar -m -c -a sdsd jabref_${{ steps.gitversion.outputs.Major }}.${{ steps.gitversion.outputs.Minor }}_amd64_repackaged.deb debian-binary control.tar.xz data.tar.xz
          rm debian-binary control.tar.* data.tar.*
          mv -f jabref_${{ steps.gitversion.outputs.Major }}.${{ steps.gitversion.outputs.Minor }}_amd64_repackaged.deb jabref_${{ steps.gitversion.outputs.Major }}.${{ steps.gitversion.outputs.Minor }}_amd64.deb
      - name: Rename files with JDK version
        shell: bash
        run: |
          for file in build/distribution/*.*; do
            base=${file%.*}
            ext=${file##*.}
            mv "$file" "${base}-jdk${{ matrix.jdk }}-javafx${{ matrix.javafx }}.${ext}"
          done

      # Upload
      - name: Set up rsync (macOS)
        if: (matrix.os == 'macos-latest') && (steps.checksecrets.outputs.secretspresent == 'YES') && (github.ref == 'refs/heads/main')
        run: brew install rsync
      - name: Set up rsync (Windows)
        if: (matrix.os == 'windows-latest') && (steps.checksecrets.outputs.secretspresent == 'YES') && (github.ref == 'refs/heads/main')
        # We want to have rsync available at this place to avoid uploading and downloading from GitHub artifact store (taking > 5 minutes in total)
        # We cannot use "action-rsyncer", because that requires Docker which is unavailable on Windows
        # We cannot use "setup-rsync", because that does not work on Windows
        # We do not use egor-tensin/setup-cygwin@v4, because it replaces the default shell
        run: choco install --no-progress rsync
      - name: Set up SSH key
        if: (steps.checksecrets.outputs.secretspresent == 'YES') && (github.ref == 'refs/heads/main')
        run: |
          echo "${{ secrets.buildJabRefPrivateKey }}" > sshkey
          chmod 600 sshkey
      - name: Upload to builds.jabref.org (Windows)
        if: (matrix.os == 'windows-latest') && (steps.checksecrets.outputs.secretspresent == 'YES') && (github.ref == 'refs/heads/main')
        shell: cmd
        # for rsync installed by chocolatey, we need the ssh.exe delivered with that installation
        run: |
          rsync -rt --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r --itemize-changes --stats --rsync-path="mkdir -p /var/www/builds.jabref.org/www/jdk-ea && rsync" -e 'C:\ProgramData\chocolatey\lib\rsync\tools\bin\ssh.exe -p 9922 -i sshkey -o StrictHostKeyChecking=no' build/distribution/ jrrsync@build-upload.jabref.org:/var/www/builds.jabref.org/www/jdk-ea/ || true
      - name: Upload to builds.jabref.org (linux, macOS)
        if: (matrix.os != 'windows-latest') && (steps.checksecrets.outputs.secretspresent == 'YES') && (github.ref == 'refs/heads/main')
        shell: bash
        run: |
          rsync -rt --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r --itemize-changes --stats --rsync-path="mkdir -p /var/www/builds.jabref.org/www/jdk-ea && rsync" -e 'ssh -p 9922 -i sshkey -o StrictHostKeyChecking=no' build/distribution/ jrrsync@build-upload.jabref.org:/var/www/builds.jabref.org/www/jdk-ea/
      - name: Upload to GitHub workflow artifacts store
        if: (steps.checksecrets.outputs.secretspresent != 'YES') || (github.ref != 'refs/heads/main')
        uses: actions/upload-artifact@v4
        with:
          name: JabRef-${{ matrix.os }}
          path: build/distribution
          compression-level: 0 # no compression