name: Openfire CI

env:
  CI: true
  REGISTRY: ghcr.io
  IMAGE_NAME: openfire

on: [push, pull_request]

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

jobs:
  build:

    name: Build Openfire from source
    runs-on: ubuntu-latest
    strategy:
      matrix:
        java: [ 17, 21 ]
        distribution: [ zulu ] # We could add more here: temurin, adopt, liberica, microsoft, corretto

    steps:
      - uses: actions/checkout@v6
      - name: Set up JDK ${{ matrix.java }} ${{ matrix.distribution }}
        uses: actions/setup-java@v5
        with:
          java-version: ${{ matrix.java }}
          distribution: ${{ matrix.distribution }}
          cache: maven
      - name: Build with Maven # We install instead of package, because we want the result in the local mvn repo
        run: |
          if [[ ${{ github.ref_name }} == 'main' ]]; then            
            ./mvnw -B install -Pcoverage --file pom.xml
          else
            ./mvnw -B install
          fi
      - name: Upload failed test reports
        uses: actions/upload-artifact@v7
        if: always()
        with:
          name: Openfire Build Java ${{ matrix.java }} JUnit Test reports
          path: xmppserver/target/surefire-reports
      - name: tar distribution # sharing artifacts that consist of many files can be slow. Share one file instead.
        if: ${{ matrix.distribution == 'zulu' }}
        run: tar -cf distribution-artifact.tar distribution/target/distribution-base
      - name: Upload distribution
        if: ${{ matrix.distribution == 'zulu' }}
        uses: actions/upload-artifact@v7
        with:
          name: Openfire Distribution Java ${{ matrix.java }}
          path: distribution-artifact.tar
      - name: Upload coverage report for 'xmppserver' module
        if: ${{ matrix.distribution == 'zulu' && matrix.java == 17 && github.ref_name == 'main'}}
        uses: actions/upload-artifact@v7
        with:
          name: Openfire Build Java ${{ matrix.java }} Unit Test Coverage Report (for 'xmppserver' module)
          path: xmppserver/target/site/jacoco/
      - name: Temporarily stash openfire artifacts from the mvn repo for later jobs
        if: ${{ matrix.distribution == 'zulu' && matrix.java == 17 }}
        uses: actions/upload-artifact@v7
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
          retention-days: 1


  build-docker:

    name: Build Docker image
    runs-on: ubuntu-latest
    needs: build

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4

      - name: Compute Docker cache key hash
        id: cache-hash
        run: echo "hash=${{ hashFiles('**/pom.xml', 'Dockerfile', 'build/docker/entrypoint.sh') }}" >> $GITHUB_OUTPUT

      - name: Build Docker image
        uses: docker/build-push-action@v7
        with:
          context: .
          load: true
          tags: ${{ env.IMAGE_NAME }}:ci-${{ github.sha }}
          cache-from: type=gha,scope=openfire-${{ steps.cache-hash.outputs.hash }}
          cache-to: type=gha,mode=max,scope=openfire-${{ steps.cache-hash.outputs.hash }}-${{ github.sha }}

      - name: Save Docker image to tar archive
        run: docker save ${{ env.IMAGE_NAME }}:ci-${{ github.sha }} | gzip > openfire-docker-image.tar.gz

      - name: Upload Docker image archive
        uses: actions/upload-artifact@v7
        with:
          name: Openfire Docker Image
          path: openfire-docker-image.tar.gz
          retention-days: 1


  integration:
    name: Execute Integration CI tests
    runs-on: ubuntu-latest
    needs: build-docker
    steps:
      - uses: actions/checkout@v6

      - name: Download Docker image archive
        uses: actions/download-artifact@v8
        with:
          name: Openfire Docker Image
          path: .

      - name: Load Docker image
        run: |
          docker load < openfire-docker-image.tar.gz
          docker tag ${{ env.IMAGE_NAME }}:ci-${{ github.sha }} openfire:latest

      - name: Checkout Integration Tests
        uses: actions/checkout@v6
        with:
          repository: igniterealtime/openfire-integration-tests
          path: openfire-integration-tests

      - name: Initialize Integration Tests Submodules
        working-directory: openfire-integration-tests
        run: |
          git submodule update --init

      - name: Setup Java
        uses: actions/setup-java@v5
        with:
          distribution: 'zulu'
          java-version: '17'
          cache: 'maven'

      - name: Run Integration Tests
        working-directory: openfire-integration-tests
        run: ./mvnw -B verify

      - name: Upload test reports
        uses: actions/upload-artifact@v7
        if: always()
        with:
          name: Integration Test Reports
          path: openfire-integration-tests/target/failsafe-reports

  aioxmpp:

    name: Execute aioxmpp-based CI tests
    runs-on: ubuntu-latest
    needs: build

    steps:
      - name: Checkout local actions (that are invoked in the 'startCIServer' and 'stopCIServer' steps) # Do this _before_ untarring the distribution, as the checkout will empty the directory prior to the checkout!
        uses: actions/checkout@v6
        with:
          sparse-checkout: |
            .github
      - name: Download distribution artifact from build job.
        uses: actions/download-artifact@v8
        with:
          name: Openfire Distribution Java 17
          path: .
      - name: untar distribution # sharing artifacts that consist of many files can be slow. Share one file instead.
        run: tar -xf distribution-artifact.tar
      - name: Checkout aioxmpp devel/head
        run: git clone --depth 1 https://codeberg.org/jssfr/aioxmpp.git aioxmpp
      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          python-version: 3.11
          check-latest: true # attempt to prevent to use 3.11.3 by enticing the runner to update (to something later)
      - name: Install aoixmpp dependencies
        run: python -m pip install setuptools pytest pytest-cov coveralls pyOpenSSL pytz
      - name: Build aioxmpp
        working-directory: ./aioxmpp
        run: python -m pip install .
      - name: Create Openfire config file for aioxmpp
        working-directory: ./aioxmpp
        run: |
          cat >"openfire-config.ini" <<EOL
          [global]
          provisioner=aioxmpp.e2etest.provision.AnonymousProvisioner
          
          [aioxmpp.e2etest.provision.AnonymousProvisioner]
          domain=example.org
          host=localhost
          port=5222
          no_verify=true
          quirks=["https://zombofant.net/xmlns/aioxmpp/e2etest/quirks#no-adhoc-ping", "https://zombofant.net/xmlns/aioxmpp/e2etest/quirks#no-xep-0049", "https://zombofant.net/xmlns/aioxmpp/e2etest/quirks#muc-no-333"]
          EOL
      - name: Start CI server from distribution
        id: startCIServer
        uses: ./.github/actions/startserver-action
        with:
          logLevel: debug
      - name: Run aioxmpp tests
        working-directory: ./aioxmpp
        run: |
          set -e
          mkdir output
          # OF-2849 test_publish_and_purge
          # OF-2850 test_publish_multiple_and_get_by_id
          # OF-2851 test_convert_field_datetime_default_locale
          # OF-2853 test_set_topic
          # https://codeberg.org/jssfr/aioxmpp/pulls/417#issuecomment-11196128 test_security_layer
          python -m pytest -p aioxmpp.e2etest --e2etest-config="openfire-config.ini" -k 'not (test_security_layer or test_set_topic or test_publish_and_purge or test_publish_multiple_and_get_by_id or test_convert_field_datetime_default_locale)' tests 2>&1 | tee output/aioxmpp.test.output.txt
          if [ ${PIPESTATUS[0]} -ne 0 ]; then false; fi;
      - name: Expose test output
        if: always()
        uses: actions/upload-artifact@v7
        with:
          name: Aioxmpp Test Output
          path: aioxmpp/output
      - name: Stop CI server
        if: ${{ always() && steps.startCIServer.conclusion == 'success' }} # TODO figure out if this is correct. The intent is to have the server stopped if it was successfully started, even if the tests fail. Failing tests should still cause the job to fail.
        uses: ./.github/actions/stopserver-action
      - name: Expose openfire output
        if: always()
        uses: actions/upload-artifact@v7
        with:
          name: Aioxmpp Test Openfire logs
          path: distribution/target/distribution-base/logs/*

  check_branch:
    runs-on: ubuntu-latest
    outputs:
      is_publishable_branch: ${{ steps.check-branch.outputs.is_publishable_branch }}
      branch_tag: ${{ steps.check-branch.outputs.branch_tag }}
    steps:
      - name: check branch ${{ github.ref }} is either main or a version number
        id: check-branch
        run: |
          if [[ ${{ github.ref }} == 'refs/heads/main' ]]; then
            echo "is_publishable_branch=true" >> "${GITHUB_OUTPUT}"
            echo "branch_tag=development" >> "${GITHUB_OUTPUT}"
          elif [[ ${{ github.ref }} =~ refs\/heads\/[0-9]+\.[0-9]+ ]]; then
            echo "is_publishable_branch=true" >> "${GITHUB_OUTPUT}"
            echo -n "branch_tag=" >> "${GITHUB_OUTPUT}"
            echo "${{ github.ref }}" | sed -e 's!refs/heads/!!' >> "${GITHUB_OUTPUT}"
          else
            echo "is_publishable_branch=false" >> "${GITHUB_OUTPUT}"
            echo "branch_tag=rando" >> "${GITHUB_OUTPUT}"
          fi

  connectivity:

    name: Execute Connectivity CI tests
    runs-on: ubuntu-latest
    needs: build

    steps:
      - name: Checkout local actions (that are invoked in the 'startCIServer' and 'stopCIServer' steps) # Do this _before_ untarring the distribution, as the checkout will empty the directory prior to the checkout!
        uses: actions/checkout@v6
        with:
          sparse-checkout: |
            .github
      - name: Download distribution artifact from build job.
        uses: actions/download-artifact@v8
        with:
          name: Openfire Distribution Java 17
          path: .
      - name: untar distribution # sharing artifacts that consist of many files can be slow. Share one file instead.
        run: tar -xf distribution-artifact.tar
      - name: Start CI server from distribution
        id: startCIServer
        uses: ./.github/actions/startserver-action
        with:
          logLevel: debug
      - name: Run connectivity tests
        uses: ./.github/actions/connectivitytests-action
      - name: Stop CI server
        if: ${{ always() && steps.startCIServer.conclusion == 'success' }} # TODO figure out if this is correct. The intent is to have the server stopped if it was successfully started, even if the tests fail. Failing tests should still cause the job to fail.
        uses: ./.github/actions/stopserver-action

  xitf:
    name: Execute XMPP Interop Testing Framework
    runs-on: ubuntu-latest
    needs: build

    steps:
      - name: Checkout local actions (that are invoked in the 'startCIServer' and 'stopCIServer' steps) # Do this _before_ untarring the distribution, as the checkout will empty the directory prior to the checkout!
        uses: actions/checkout@v6
        with:
          sparse-checkout: |
            .github
      - name: Download distribution artifact from build job.
        uses: actions/download-artifact@v8
        with:
          name: Openfire Distribution Java 17
          path: .
      - name: untar distribution # sharing artifacts that consist of many files can be slow. Share one file instead.
        run: tar -xf distribution-artifact.tar
      - name: Start CI server from distribution
        id: startCIServer
        uses: ./.github/actions/startserver-action
        with:
          logLevel: debug
      - name: Run XMPP Interop Testing Framework tests against server
        uses: XMPP-Interop-Testing/xmpp-interop-tests-action@v1.7.2
        with:
          domain: 'example.org'
          adminAccountUsername: 'admin'
          adminAccountPassword: 'admin'
          disabledTests: 'EntityCapsTest,SoftwareInfoIntegrationTest,XmppConnectionIntegrationTest,StreamManagementTest,WaitForClosingStreamElementTest,IoTControlIntegrationTest,ModularXmppClientToServerConnectionLowLevelIntegrationTest'
      - name: Stop CI server
        if: ${{ always() && steps.startCIServer.conclusion == 'success' }} # TODO figure out if this is correct. The intent is to have the server stopped if it was successfully started, even if the tests fail. Failing tests should still cause the job to fail.
        uses: ./.github/actions/stopserver-action

  should-do-database-tests:
    name: Check if database install/upgrade tests should be run
    runs-on: ubuntu-latest
    permissions:
      pull-requests: read
    outputs:
      check: ${{ steps.filter.outputs.database-relevant-files }}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Check for differences
        uses: dorny/paths-filter@v4
        id: filter
        with:
          filters: |
            database-relevant-files:
              - 'distribution/src/database/**'
              - 'build/ci/**'
              - '.github/workflows/continuous-integration-workflow.yml'
              - 'xmppserver/pom.xml'
              - 'xmppserver/src/main/java/org/jivesoftware/database/**'


  xcheck-database-version:
    name: Cross check that any new database upgrades match the code version
    needs: [should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Cross check DATABASE_VERSION
        run: |
          set -e
          CODE_SAYS=$(grep 'int DATABASE_VERSION =' xmppserver/src/main/java/org/jivesoftware/database/SchemaManager.java | sed -e 's/.*= //' -e 's/;//')
          NEXT=$((CODE_SAYS + 1))
          for dbname in db2 hsqldb mysql oracle postgresql sqlserver sybase; do
            # Ensure that a file exists for CODE_SAYS
            if [ ! -f distribution/src/database/upgrade/${CODE_SAYS}/openfire_${dbname}.sql ]; then
              echo "ERROR: Expected to find a database upgrade script for ${dbname} and version ${CODE_SAYS}, but no such file exists."
              exit 1
            fi
          done
          # Ensure that the next increment does not have a directory
          if [ -d distribution/src/database/upgrade/${NEXT} ]; then
            echo "ERROR: Found a directory for the next database version ${NEXT}, but the code still says ${CODE_SAYS}. Please increment the DATABASE_VERSION in SchemaManager.java."
            exit 1
          fi


  hsqldb-install:
    name: Test HSQLDB install script
    needs: [build, should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Set up JDK 17 Zulu
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
      - name: Restore mvn repo artifacts from build job
        uses: actions/download-artifact@v8
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
      - name: Set environment variables
        run: |
          echo "CONNECTION_STRING=jdbc:hsqldb:hsql://localhost/openfire" >> $GITHUB_ENV
          echo "CONNECTION_DRIVER=org.hsqldb.jdbc.JDBCDriver" >> $GITHUB_ENV
          echo "CONNECTION_USERNAME=sa" >> $GITHUB_ENV
          echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV
          OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
          echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV
          echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV
      - name: Start database server with an empty database
        run: |
          docker compose -f ./build/ci/compose/hsqldb.yml up --detach
          docker exec -i compose-db-1 bash -c "sed -i 's/password/password '"$CONNECTION_PASSWORD"'/' ~/sqltool.rc"
      - name: Execute Openfire's database install script
        run: |
          pushd ./build/ci/updater
          ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE"


  hsqldb-upgrade:
    name: Test HSQLDB upgrade scripts
    needs: [build, should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Set up JDK 17 Zulu
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
      - name: Restore mvn repo artifacts from build job
        uses: actions/download-artifact@v8
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
      - name: Set environment variables
        run: |
          echo "CONNECTION_STRING=jdbc:hsqldb:hsql://localhost/openfire" >> $GITHUB_ENV
          echo "CONNECTION_DRIVER=org.hsqldb.jdbc.JDBCDriver" >> $GITHUB_ENV
          echo "CONNECTION_USERNAME=sa" >> $GITHUB_ENV
          echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV
          OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
          echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV
          echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV
      - name: Download an old Openfire database installation script
        run: |
          mkdir olddb
          curl https://raw.githubusercontent.com/igniterealtime/Openfire/v4.3.0/distribution/src/database/openfire_hsqldb.sql > $GITHUB_WORKSPACE/olddb/openfire_hsqldb.sql
          sed -i '/^\/\//d' $GITHUB_WORKSPACE/olddb/openfire_hsqldb.sql
          sed '/^SET /d' $GITHUB_WORKSPACE/olddb/openfire_hsqldb.sql
      - name: Start database server, install old version of the Openfire database
        run: |
          docker compose -f ./build/ci/compose/hsqldb.yml up --detach
          docker exec -i compose-db-1 bash -c "sed -i 's/password/password '"$CONNECTION_PASSWORD"'/' ~/sqltool.rc"
          docker exec -i compose-db-1 bash -c "java -jar /opt/hsqldb/sqltool.jar db /olddb/openfire_hsqldb.sql"
      - name: Execute Openfire's database upgrade scripts
        run: |
          pushd ./build/ci/updater
          ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE"


  sqlserver-install:
    name: Test MS SQL Server install script
    needs: [build, should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Set up JDK 17 Zulu
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
      - name: Restore mvn repo artifacts from build job
        uses: actions/download-artifact@v8
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
      - name: Set environment variables
        run: |
          echo "CONNECTION_STRING=jdbc:sqlserver://localhost:1433;databaseName=openfire;applicationName=Openfire;encrypt=false" >> $GITHUB_ENV
          echo "CONNECTION_DRIVER=com.microsoft.sqlserver.jdbc.SQLServerDriver" >> $GITHUB_ENV
          echo "CONNECTION_USERNAME=sa" >> $GITHUB_ENV
          echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV
          OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
          echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV
          echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV
      - name: Start database server with an empty database
        run: |
          mkdir olddb
          echo 'CREATE DATABASE openfire;' > $GITHUB_WORKSPACE/olddb/1-init-empty-database.sql
          docker compose -f ./build/ci/compose/mssql.yml up --detach
      - name: Execute Openfire's database install script
        run: |
          pushd ./build/ci/updater
          ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE"


  sqlserver-upgrade:
    name: Test MS SQL Server upgrade scripts
    needs: [build, should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Set up JDK 17 Zulu
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
      - name: Restore mvn repo artifacts from build job
        uses: actions/download-artifact@v8
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
      - name: Set environment variables
        run: |
          echo "CONNECTION_STRING=jdbc:sqlserver://localhost:1433;databaseName=openfire;applicationName=Openfire;encrypt=false" >> $GITHUB_ENV
          echo "CONNECTION_DRIVER=com.microsoft.sqlserver.jdbc.SQLServerDriver" >> $GITHUB_ENV
          echo "CONNECTION_USERNAME=sa" >> $GITHUB_ENV
          echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV
          OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
          echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV
          echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV
      - name: Download an old Openfire database installation script
        run: |
          mkdir olddb
          curl https://raw.githubusercontent.com/igniterealtime/Openfire/v4.3.0/distribution/src/database/openfire_sqlserver.sql > $GITHUB_WORKSPACE/olddb/openfire_sqlserver.sql
      - name: Start database server, install old version of the Openfire database
        run: docker compose -f ./build/ci/compose/mssql.yml up --detach
      - name: Execute Openfire's database upgrade scripts
        run: |
          pushd ./build/ci/updater
          ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE"


  postgres-install:
    name: Test Postgres install script
    needs: [build, should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Set up JDK 17 Zulu
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
      - name: Restore mvn repo artifacts from build job
        uses: actions/download-artifact@v8
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
      - name: Set environment variables
        run: |
          echo "CONNECTION_STRING=jdbc:postgresql://localhost:5432/openfire" >> $GITHUB_ENV
          echo "CONNECTION_DRIVER=org.postgresql.Driver" >> $GITHUB_ENV
          echo "CONNECTION_USERNAME=openfire" >> $GITHUB_ENV
          echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV
          OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
          echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV
          echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV
      - name: Start database server with an empty database
        run: |
          docker compose -f ./build/ci/compose/postgresql.yml up --wait
      - name: Execute Openfire's database install script
        run: |
          pushd ./build/ci/updater
          ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE"


  postgres-upgrade:
    name: Test Postgres upgrade scripts
    needs: [build, should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Set up JDK 17 Zulu
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
      - name: Restore mvn repo artifacts from build job
        uses: actions/download-artifact@v8
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
      - name: Set environment variables
        run: |
          echo "CONNECTION_STRING=jdbc:postgresql://localhost:5432/openfire" >> $GITHUB_ENV
          echo "CONNECTION_DRIVER=org.postgresql.Driver" >> $GITHUB_ENV
          echo "CONNECTION_USERNAME=openfire" >> $GITHUB_ENV
          echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV
          OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
          echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV
          echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV
      - name: Download an old Openfire database installation script
        run: |
          mkdir olddb
          curl https://raw.githubusercontent.com/igniterealtime/Openfire/v4.3.0/distribution/src/database/openfire_postgresql.sql > $GITHUB_WORKSPACE/olddb/openfire_postgresql.sql
      - name: Start database server, install old version of the Openfire database
        run: docker compose -f ./build/ci/compose/postgresql.yml up --wait
      - name: Execute Openfire's database upgrade scripts
        run: |
          pushd ./build/ci/updater
          ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE"


  mysql-install:
    name: Test MySQL install script
    needs: [build, should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Set up JDK 17 Zulu
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
      - name: Restore mvn repo artifacts from build job
        uses: actions/download-artifact@v8
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
      - name: Set environment variables
        run: |
          echo "CONNECTION_STRING=jdbc:mysql://localhost:3306/openfire?rewriteBatchedStatements=true&characterEncoding=UTF-8&characterSetResults=UTF-8&serverTimezone=UTC" >> $GITHUB_ENV
          echo "CONNECTION_DRIVER=com.mysql.cj.jdbc.Driver" >> $GITHUB_ENV
          echo "CONNECTION_USERNAME=root" >> $GITHUB_ENV
          echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV
          OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
          echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV
          echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV
      - name: Start database server with an empty database
        run: |
          mkdir olddb
          echo 'CREATE TABLE imready AS (SELECT 1);' > $GITHUB_WORKSPACE/olddb/ZZZ-signal-ready.sql
          docker compose -f ./build/ci/compose/mysql.yml up --detach --wait
      - name: Build & run database tester
        run: |
          pushd ./build/ci/updater
          ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE"


  mysql-upgrade:
    name: Test MySQL upgrade scripts
    needs: [build, should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Set up JDK 17 Zulu
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
      - name: Restore mvn repo artifacts from build job
        uses: actions/download-artifact@v8
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
      - name: Set environment variables
        run: |
          echo "CONNECTION_STRING=jdbc:mysql://localhost:3306/openfire?rewriteBatchedStatements=true&characterEncoding=UTF-8&characterSetResults=UTF-8&serverTimezone=UTC" >> $GITHUB_ENV
          echo "CONNECTION_DRIVER=com.mysql.cj.jdbc.Driver" >> $GITHUB_ENV
          echo "CONNECTION_USERNAME=root" >> $GITHUB_ENV
          echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV
          OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
          echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV
          echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV
      - name: Download an old Openfire database installation script
        run: |
          mkdir olddb
          curl https://raw.githubusercontent.com/igniterealtime/Openfire/v4.3.0/distribution/src/database/openfire_mysql.sql > $GITHUB_WORKSPACE/olddb/openfire_mysql.sql
          echo 'CREATE TABLE imready AS (SELECT 1);' > $GITHUB_WORKSPACE/olddb/ZZZ-signal-ready.sql
      - name: Start database server, install old version of the Openfire database
        run: |
          docker compose -f ./build/ci/compose/mysql.yml up --detach --wait
      - name: Execute Openfire's database upgrade scripts
        run: |
          pushd ./build/ci/updater
          ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE"


  oracle-install:
    name: Test Oracle install scripts
    needs: [build, should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Set up JDK 17 Zulu
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
      - name: Restore mvn repo artifacts from build job
        uses: actions/download-artifact@v8
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
      - name: Set environment variables
        run: |
          echo "CONNECTION_STRING=jdbc:oracle:thin:@localhost:1521/FREEPDB1" >> $GITHUB_ENV
          echo "CONNECTION_DRIVER=oracle.jdbc.driver.OracleDriver" >> $GITHUB_ENV
          echo "CONNECTION_USERNAME=openfire" >> $GITHUB_ENV
          echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV
          OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
          echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV
          echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV
      - name: Start database server with an empty database
        run: |
          mkdir olddb
          cp ./build/ci/compose/scripts/1.oracle-init.sql $GITHUB_WORKSPACE/olddb/1.install-db.sql
          docker compose -f ./build/ci/compose/oracle.yml up --wait
      - name: Execute Openfire's database install script
        run: |
          pushd ./build/ci/updater
          ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE"


  oracle-upgrade:
    name: Test Oracle upgrade scripts
    needs: [build, should-do-database-tests, check_branch]
    runs-on: ubuntu-latest
    if: ${{ needs.should-do-database-tests.outputs.check == 'true' || needs.check_branch.outputs.is_publishable_branch == 'true'}}
    steps:
      - name: Checkout Openfire
        uses: actions/checkout@v6
      - name: Set up JDK 17 Zulu
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
      - name: Restore mvn repo artifacts from build job
        uses: actions/download-artifact@v8
        with:
          name: Maven Repository
          path: ~/.m2/repository/org/igniterealtime/openfire/
      - name: Set environment variables
        run: |
          echo "CONNECTION_STRING=jdbc:oracle:thin:@localhost:1521/FREEPDB1" >> $GITHUB_ENV
          echo "CONNECTION_DRIVER=oracle.jdbc.driver.OracleDriver" >> $GITHUB_ENV
          echo "CONNECTION_USERNAME=openfire" >> $GITHUB_ENV
          echo "CONNECTION_PASSWORD=SecurePa55w0rd" >> $GITHUB_ENV
          OPENFIREVSN=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
          echo "OPENFIREVSN=$OPENFIREVSN" >> $GITHUB_ENV
          echo "JAVA_HOME=$(echo $JAVA_HOME_17_X64)" >> $GITHUB_ENV
      - name: Download an old Openfire database installation script
        run: |
          mkdir olddb
          curl https://raw.githubusercontent.com/igniterealtime/Openfire/v4.3.0/distribution/src/database/openfire_oracle.sql > $GITHUB_WORKSPACE/openfire_oracle.sql
      - name: Start database server, install old version of the Openfire database
        run: |
          cat ./build/ci/compose/scripts/1.oracle-init.sql $GITHUB_WORKSPACE/openfire_oracle.sql > $GITHUB_WORKSPACE/olddb/1.install-db.sql
          docker compose -f ./build/ci/compose/oracle.yml up --wait
      - name: Execute Openfire's database upgrade scripts
        run: |
          pushd ./build/ci/updater
          ./mvnw -B clean package exec:java -Dexec.args="$GITHUB_WORKSPACE"


  publish-maven:
    name: Publish to Maven
    runs-on: ubuntu-latest
    needs: [aioxmpp, connectivity, integration, xitf, check_branch, hsqldb-install, hsqldb-upgrade, sqlserver-install, sqlserver-upgrade, postgres-install, postgres-upgrade, mysql-install, mysql-upgrade, oracle-install, oracle-upgrade]
    if: ${{github.repository == 'igniterealtime/Openfire' && github.event_name == 'push' && needs.check_branch.outputs.is_publishable_branch == 'true'}}

    steps:
      - uses: actions/checkout@v6
        with:
          # Defend against another commit quickly following the first
          # We want the one that's been tested, rather than the head of main
          ref: ${{ github.event.push.after }}
      - name: Set up Java for publishing
        uses: actions/setup-java@v5
        with:
          java-version: 17
          distribution: zulu
          cache: maven
          server-id: igniterealtime
          server-username: IGNITE_REALTIME_MAVEN_USERNAME
          server-password: IGNITE_REALTIME_MAVEN_PASSWORD
      - name: Publish
        run: ./mvnw -B deploy -Pci -Dmaven.test.skip=true
        env:
          IGNITE_REALTIME_MAVEN_USERNAME: ${{ secrets.IGNITE_REALTIME_MAVEN_USERNAME }}
          IGNITE_REALTIME_MAVEN_PASSWORD: ${{ secrets.IGNITE_REALTIME_MAVEN_PASSWORD }}

  publish-docker:
    name: Publish to GitHub's Docker registry
    runs-on: ubuntu-latest
    needs: [build-docker, aioxmpp, connectivity, integration, xitf, check_branch, hsqldb-install, hsqldb-upgrade, sqlserver-install, sqlserver-upgrade, postgres-install, postgres-upgrade, mysql-install, mysql-upgrade, oracle-install, oracle-upgrade]
    if: |
      github.event_name == 'push' && 
      (contains(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main')

    permissions:
      contents: read
      packages: write
      attestations: write
      id-token: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      - name: Download Docker image archive
        uses: actions/download-artifact@v8
        with:
          name: Openfire Docker Image
          path: .

      - name: Load Docker image
        run: docker load < openfire-docker-image.tar.gz

      - name: Log in to the Container registry
        uses: docker/login-action@v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels) for image registry
        id: meta
        uses: docker/metadata-action@v6
        with:
          images: ${{ env.REGISTRY }}/igniterealtime/${{ env.IMAGE_NAME }}

      - name: Retag and push final image
        id: push
        run: |
          FIRST_TAG=$(echo "${{ steps.meta.outputs.tags }}" | head -n1)
          docker tag ${{ env.IMAGE_NAME }}:ci-${{ github.sha }} $FIRST_TAG
          DIGEST=$(docker push $FIRST_TAG | grep -oP 'digest: \K\S+')
          for tag in $(echo "${{ steps.meta.outputs.tags }}" | tail -n +2); do
            docker tag $FIRST_TAG $tag
            docker push $tag
          done
          echo "digest=$DIGEST" >> $GITHUB_OUTPUT

      - name: Generate artifact attestation
        uses: actions/attest-build-provenance@v4
        with:
          subject-name: ${{ env.REGISTRY }}/igniterealtime/${{ env.IMAGE_NAME }}
          subject-digest: ${{ steps.push.outputs.digest }}
          push-to-registry: true

  build-deb-artifact:
    name: Generate DEB artifact
    runs-on: ubuntu-latest
    needs: [aioxmpp, connectivity, integration, xitf, check_branch, hsqldb-install, hsqldb-upgrade, sqlserver-install, sqlserver-upgrade, postgres-install, postgres-upgrade, mysql-install, mysql-upgrade, oracle-install, oracle-upgrade]
    steps:
      - uses: actions/checkout@v6
        with:
          # Defend against another commit quickly following the first
          # We want the one that's been tested, rather than the head of main
          ref: ${{ github.event.push.after }}
      - name: Download distribution artifact from build job.
        uses: actions/download-artifact@v8
        with:
          name: Openfire Distribution Java 17
          path: .
      - name: untar distribution # sharing artifacts that consist of many files can be slow. Share one file instead.
        run: tar -xf distribution-artifact.tar
      - name: Install build deps
        run: sudo apt-get install -y debhelper-compat=13
      - name: Run build script
        run: bash build/debian/build_debs.sh
