name: MSBuild
run-name: psql ODBC CI - ${{ github.event.head_commit.message }}

on:
  push:
    branches: [ "main" ]
    tags:
      - 'REL-*'
      - '!REL-*-mimalloc'
  pull_request:
    branches: [ "main" ]

env:
  # Path to the solution file relative to the root of the project.
  SOLUTION_FILE_PATH: .

  # Configuration type to build.
  # You can convert this to a build matrix if you need coverage of multiple configuration types.
  # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
  BUILD_CONFIGURATION: Release

  # Workflow versions. Increment these when you make changes to a build step in the workflow and
  # you want the step to run, but the corresponding cache is causing the step to be skipped.
  WORKFLOW_VERSION_POSTGRESQL: '1' # for build steps related to the 'cachePostgres' cache

  # Software versions. 
  POSTGRESQL_SOURCE_TAG: 'REL_17_STABLE'
  POSTGRESQL_PACKAGE_FILEID: '1259019'
  OPENSSL_VERSION: '3_3_3'
  PKGCONFIGLITE_VERSION: '0.28-1'
  WINFLEXBISON_VERSION: '2.5.24'
  DIFFUTILS_VERSION: '2.8.7-1'

permissions:
  contents: read

jobs:
  build_and_test:
    runs-on: windows-latest

    steps:
    - name: Cache Postgres build output
      uses: actions/cache@v4
      id: cachePostgres
      with:
        path: |
          d:\postgresql
          d:\postgresql86
        key: postgresql-${{env.POSTGRESQL_SOURCE_TAG}}_openssl-${{env.OPENSSL_VERSION}}_pkgconfiglite-${{env.PKGCONFIGLITE_VERSION}}_winflexbison-${{env.WINFLEXBISON_VERSION}}_workflow-${{env.WORKFLOW_VERSION_POSTGRESQL}}

    - name: Cache Postgres source
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: actions/cache@v4
      id: cachePostgresSource
      with:
        path: postgres
        key: postgres-source-${{env.POSTGRESQL_SOURCE_TAG}}
    - name: Get Postgres source
      uses: actions/checkout@v4
      if: ${{steps.cachePostgresSource.outputs.cache-hit != 'true' && steps.cachePostgres.outputs.cache-hit != 'true'}}
      with:
        repository: "postgres/postgres.git"
        ref: ${{env.POSTGRESQL_SOURCE_TAG}}
        path: postgres

    - name: 'get meson'
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      run: |
        python -m pip install meson
        python -m pip install ninja

    - name: Cache GNU diffutils for Test on PostgreSQL for Windows
      uses: actions/cache@v4
      id: cacheDiffutilsZip
      with:
        path: C:\OTHERBIN\diffutils
        key: diff_utils-${{env.DIFFUTILS_VERSION}}
      env:
        SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
    - name: Cache PostgreSQL installer
      uses: actions/cache@v4
      id: cachePostgresInstaller
      with:
        path: C:\OTHERBIN\postgresql_install.exe
        key: postgresql_installer-${{env.POSTGRESQL_PACKAGE_FILEID}}
    - name: Cache pkgconfiglite for Compile using msvc and meson
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: actions/cache@v4
      id: cachePkgConfigLiteZip
      with:
        path: C:\OTHERBIN\pkgconfiglite
        key: pkg-config-lite-${{env.PKGCONFIGLITE_VERSION}}-win32
      env:
        SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
    - name: Cache Win32OpenSSL32 for Win32Compile
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: actions/cache@v4
      id: cacheWin32OpenSSL
      with:
        path: C:\OTHERBIN\openssl32
        key: Win32OpenSSL-${{env.OPENSSL_VERSION}}
    - name: Cache Win64OpenSSL64 for Win64Compile
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: actions/cache@v4
      id: cacheWin64OpenSSL
      with:
        path: C:\OTHERBIN\openssl64
        key: Win64OpenSSL-${{env.OPENSSL_VERSION}}
    - name: Cache winflexbison for Compile using msvc
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: actions/cache@v4
      id: cacheWinFlexBisonZip
      with:
        path: C:\OTHERBIN\winflexbison
        key: winflexbison-${{env.WINFLEXBISON_VERSION}}
      env:
        SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1    

    - name: Download GNU diffutils for Test on PostgreSQL for Windows 
      if: ${{steps.cacheDiffutilsZip.outputs.cache-hit != 'true'}}
      uses: suisei-cn/actions-download-file@v1.6.0
      id: downloadDiffutilsZip
      with:
        retry-times: 5
        url: https://zenlayer.dl.sourceforge.net/project/gnuwin32/diffutils/${{env.DIFFUTILS_VERSION}}/diffutils-${{env.DIFFUTILS_VERSION}}-bin.zip
        filename: diffutils-bin.zip
    
    - name: Download openssl32 for win32 compile
      if: ${{steps.cacheWin32OpenSSL.outputs.cache-hit != 'true' && steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: suisei-cn/actions-download-file@v1.6.0
      id: downloadWin32OpenSSL
      with:
        retry-times: 5
        url: https://slproweb.com/download/Win32OpenSSL-${{env.OPENSSL_VERSION}}.exe
        filename: Win32OpenSSL.exe
    
    - name: Download openssl64 for win64 compile
      if: ${{steps.cacheWin64OpenSSL.outputs.cache-hit != 'true' && steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: suisei-cn/actions-download-file@v1.6.0
      id: downloadWin64OpenSSL
      with:
        retry-times: 5
        url: https://slproweb.com/download/Win64OpenSSL-${{env.OPENSSL_VERSION}}.exe
        filename: Win64OpenSSL.exe
  
    - name: Download pkgconfiglite for Compile using msvc and meson
      if: ${{steps.cachePkgConfigLiteZip.outputs.cache-hit != 'true' && steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: suisei-cn/actions-download-file@v1.6.0
      id: downloadPkgConfigLiteZip
      with:
        retry-times: 5
        url: http://downloads.sourceforge.net/project/pkgconfiglite/${{env.PKGCONFIGLITE_VERSION}}/pkg-config-lite-${{env.PKGCONFIGLITE_VERSION}}_bin-win32.zip
        filename: pkg-config-lite_bin-win32.zip

    - name: Download winflexbison for Compile using msvc
      if: ${{steps.cacheWinFlexBisonZip.outputs.cache-hit != 'true' && steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: suisei-cn/actions-download-file@v1.6.0
      id: downloadWinFlexBisonZip
      with:
        retry-times: 5
        url: https://sourceforge.net/projects/winflexbison/files/win_flex_bison-${{env.WINFLEXBISON_VERSION}}.zip
        filename: win_flex_bison.zip

    - name: Download postgresql install from EDB
      uses: suisei-cn/actions-download-file@v1.6.0
      if: ${{steps.cachePostgresInstaller.outputs.cache-hit != 'true'}}
      id: downloadPostgresInstaller
      with:
        retry-times: 5
        url: https://sbp.enterprisedb.com/getfile.jsp?fileid=${{env.POSTGRESQL_PACKAGE_FILEID}}
        target: c:\OTHERBIN
        filename: postgresql_install.exe

    - name: Extract Diffutils for Test on PostgreSQL for Windows
      if: ${{steps.cacheDiffutilsZip.outputs.cache-hit != 'true'}}
      shell: cmd
      run: |
        rem MKDIR creates any intermediate directories in the path, if needed.
        mkdir "C:\OTHERBIN\diffutils"
        rem 7z is provided by Github Actions
        7z x diffutils-bin.zip -o"C:\OTHERBIN\diffutils"
    - name: Add Diffutils bin directory to the PATH for Test on PostgreSQL for Windows
      shell: cmd
      run: |
        rem - man7.org/linux/man-pages/man1/printf.1.html
        printf "C:\\OTHERBIN\\diffutils\\bin" >> %GITHUB_PATH%

    - name: Extract pkgconfiglite for Compile using msvc and meson
      if: ${{steps.cachePkgConfigLiteZip.outputs.cache-hit != 'true' && steps.cachePostgres.outputs.cache-hit != 'true'}}
      shell: cmd
      run: |
        rem MKDIR creates any intermediate directories in the path, if needed.
        mkdir "C:\OTHERBIN\pkgconfiglite"
        rem 7z is provided by Github Actions
        7z x pkg-config-lite_bin-win32.zip -o"C:\OTHERBIN\pkgconfiglite"
    - name: Add pkgconfiglite bin directory to the PATH for Compile using msvc and meson
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      shell: cmd
      run: |
        rem - man7.org/linux/man-pages/man1/printf.1.html
        printf "C:\\OTHERBIN\\pkgconfiglite\\pkg-config-lite-%PKGCONFIGLITE_VERSION%\\bin" >> %GITHUB_PATH%

    - name: Install Win32OpenSSL
      if: ${{steps.cacheWin32OpenSSL.outputs.cache-hit != 'true' && steps.cachePostgres.outputs.cache-hit != 'true'}}
      shell: cmd
      run: Win32OpenSSL.exe /sp /silent /dir=c:\OTHERBIN\openssl32

    - name: Install Win64OpenSSL
      if: ${{steps.cacheWin64OpenSSL.outputs.cache-hit != 'true' && steps.cachePostgres.outputs.cache-hit != 'true'}}
      shell: cmd
      run: Win64OpenSSL.exe /sp /silent /dir=c:\OTHERBIN\openssl64

      # Choco Install winflexbison
      # BUT the "crazy-max/ghaction-chocolatey@v2" "install pkgconfiglite" file download often times-out
    - name: Extract winflexbison for Compile using msvc
      if: ${{steps.cacheWinFlexBisonZip.outputs.cache-hit != 'true' && steps.cachePostgres.outputs.cache-hit != 'true'}}
      shell: cmd
      run: |
        rem MKDIR creates any intermediate directories in the path, if needed.
        mkdir "C:\OTHERBIN\winflexbison"
        rem 7z is provided by Github Actions
        7z x win_flex_bison.zip -o"C:\OTHERBIN\winflexbison"
    - name: Add the winflexbison directory to the PATH for Compile using msvc
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      shell: cmd
      run: |
        rem - man7.org/linux/man-pages/man1/printf.1.html
        printf "C:\OTHERBIN\\winflexbison" >> %GITHUB_PATH%

    - name: 'setup msvc x86'
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: TheMrMilchmann/setup-msvc-dev@v3
      with: 
        arch: x86
    - name: 'build postgresx86'    
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      working-directory: postgres
      run: |
        meson setup buildx86 -Dssl=openssl -Dextra_lib_dirs=c:\OTHERBIN\openssl32\lib\VC\x86\MT -Dextra_include_dirs=c:\OTHERBIN\openssl32\include --prefix=d:\postgresql86
        cd buildx86
        ninja -v 
        ninja -v install
        cp c:\OTHERBIN\openssl32\*.dll d:\postgresql86\bin
    - name: 'setup msvc x64'    
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      uses: TheMrMilchmann/setup-msvc-dev@v3
      with: 
        arch: x64
    - name : 'build postgres x64'
      if: ${{steps.cachePostgres.outputs.cache-hit != 'true'}}
      working-directory: postgres
      run: |
        meson setup build -Dssl=openssl -Dextra_lib_dirs=c:\OTHERBIN\openssl64\lib\VC\x64\MT -Dextra_include_dirs=c:\OTHERBIN\openssl64\include --prefix=d:\postgresql
        cd build
        ninja
        ninja install
        cp c:\OTHERBIN\openssl64\*.dll d:\postgresql\bin
    - name: install postgresql binary
      shell: cmd
      run: |
        echo on
        C:\OTHERBIN\postgresql_install.exe --mode unattended --unattendedmodeui none --superpassword password --enable-components server    
    - name: start postgresql
      shell: cmd
      run: |
        echo on
        sc config "postgresql-x64-14" start= auto
    - name: get psqlodbc
      uses: actions/checkout@v4
      with:
        path: psqlodbc
        submodules: true
    - name: 'setup msvc for psqlodbc'
      uses: TheMrMilchmann/setup-msvc-dev@v3
      with: 
        arch: x86

    - name: Install WiX
      shell: cmd
      run: |
        dotnet tool install --global wix
        wix extension add --global WixToolset.UI.wixext/6.0.0

    - name: build psqlodbc standard
      shell: powershell      
      working-directory: psqlodbc
      run: |
        copy .github\workflows\configuration.xml winbuild
        winbuild\BuildAll.ps1
        installer\buildInstallers.ps1
      env:
        PSQLODBC_OBJBASE: ${{ github.workspace }}\psqlodbc\winbuild\standard
    - name: test psqlodbc standard
      shell: powershell
      working-directory: psqlodbc
      run: |
        winbuild\regress.ps1 -DsnInfo "SERVER=localhost|DATABASE=contrib_regression|PORT=5432|UID=postgres|PWD=password"
        standard\test_x86\RegisterRegdsn.exe uninstall_driver postgres_devw
        standard\test_x64\RegisterRegdsn.exe uninstall_driver postgres_devw
      env:
        PSQLODBC_OBJBASE: ${{ github.workspace }}\psqlodbc\winbuild\standard

    - name: build psqlodbc mimalloc
      shell: powershell      
      working-directory: psqlodbc
      run: |
        copy .github\workflows\configuration.xml winbuild
        winbuild\BuildAll.ps1 -UseMimalloc
        installer\buildInstallers.ps1
      env:
        PSQLODBC_OBJBASE: ${{ github.workspace }}\psqlodbc\winbuild\mimalloc
    - name: test psqlodbc mimalloc
      shell: powershell
      working-directory: psqlodbc
      run: |
        winbuild\regress.ps1 -DsnInfo "SERVER=localhost|DATABASE=contrib_regression|PORT=5432|UID=postgres|PWD=password" -ExpectMimalloc
        mimalloc\test_x86\RegisterRegdsn.exe uninstall_driver postgres_devw
        mimalloc\test_x64\RegisterRegdsn.exe uninstall_driver postgres_devw
      env:
        PSQLODBC_OBJBASE: ${{ github.workspace }}\psqlodbc\winbuild\mimalloc

    - name: Upload standard x64 merge module
      uses: actions/upload-artifact@v4
      with:
        name: psqlODBC Standard x64 Merge Module
        path: psqlodbc/winbuild/standard/installer/x64/*.msm
        retention-days: 5
        if-no-files-found: error
    - name: Upload standard x64 installer package
      uses: actions/upload-artifact@v4
      with:
        name: psqlODBC Standard x64 Installer
        path: psqlodbc/winbuild/standard/installer/x64/*.msi
        retention-days: 5
        if-no-files-found: error
    - name: Upload standard x86 merge module
      uses: actions/upload-artifact@v4
      with:
        name: psqlODBC Standard x86 Merge Module
        path: psqlodbc/winbuild/standard/installer/x86/*.msm
        retention-days: 5
        if-no-files-found: error
    - name: Upload standard x86 installer package
      uses: actions/upload-artifact@v4
      with:
        name: psqlODBC Standard x86 Installer
        path: psqlodbc/winbuild/standard/installer/x86/*.msi
        retention-days: 5
        if-no-files-found: error
    - name: Upload standard x64 setup
      uses: actions/upload-artifact@v4
      with:
        name: psqlODBC Standard x64 Setup
        path: psqlodbc/winbuild/standard/installer/psqlodbc-setup/bin/Release/psqlodbc-setup.exe
        retention-days: 5
        if-no-files-found: error

    - name: Upload mimalloc x64 merge module
      uses: actions/upload-artifact@v4
      with:
        name: psqlODBC mimalloc x64 Merge Module
        path: psqlodbc/winbuild/mimalloc/installer/x64/*.msm
        retention-days: 5
        if-no-files-found: error
    - name: Upload mimalloc x64 installer package
      uses: actions/upload-artifact@v4
      with:
        name: psqlODBC mimalloc x64 Installer
        path: psqlodbc/winbuild/mimalloc/installer/x64/*.msi
        retention-days: 5
        if-no-files-found: error
    - name: Upload mimalloc x86 merge module
      uses: actions/upload-artifact@v4
      with:
        name: psqlODBC mimalloc x86 Merge Module
        path: psqlodbc/winbuild/mimalloc/installer/x86/*.msm
        retention-days: 5
        if-no-files-found: error
    - name: Upload mimalloc x86 installer package
      uses: actions/upload-artifact@v4
      with:
        name: psqlODBC mimalloc x86 Installer
        path: psqlodbc/winbuild/mimalloc/installer/x86/*.msi
        retention-days: 5
        if-no-files-found: error
    - name: Upload mimalloc x64 setup
      uses: actions/upload-artifact@v4
      with:
        name: psqlODBC mimalloc x64 Setup
        path: psqlodbc/winbuild/mimalloc/installer/psqlodbc-setup/bin/Release/psqlodbc-setup.exe
        retention-days: 5
        if-no-files-found: error

    - name: Create mimalloc Release
      if: startsWith(github.ref, 'refs/tags/REL-')
      uses: ncipollo/release-action@v1.14.0
      id: create_mimalloc_release
      with:
        tag: ${{github.ref_name}}-mimalloc
        commit: ${{github.sha}}
        body: A build of ${{github.ref_name}} that uses the mimalloc allocator for improved performance.
        makeLatest: false
        draft: false
        prerelease: false
        token: ${{secrets.RELEASE_TOKEN}}
        artifacts: "psqlodbc/winbuild/mimalloc/installer/x64/*.ms?,psqlodbc/winbuild/mimalloc/installer/x86/*.ms?,psqlodbc/winbuild/mimalloc/installer/psqlodbc-setup/bin/Release/psqlodbc-setup.exe"
    - name: Create Standard Release
      if: startsWith(github.ref, 'refs/tags/REL-')
      uses: ncipollo/release-action@v1.14.0
      id: create_standard_release
      with:
        makeLatest: true
        draft: false
        prerelease: false
        token: ${{secrets.RELEASE_TOKEN}}
        artifacts: "psqlodbc/winbuild/standard/installer/x64/*.ms?,psqlodbc/winbuild/standard/installer/x86/*.ms?,psqlodbc/winbuild/standard/installer/psqlodbc-setup/bin/Release/psqlodbc-setup.exe"
