From 2fc2359471c885e83180eec645f050721026641e Mon Sep 17 00:00:00 2001 From: "F.D.Castel" Date: Tue, 31 Mar 2026 11:02:59 -0300 Subject: [PATCH] Add GitHub Actions CI with full build and test automation Add a unified build-and-test workflow using PowerShell (Invoke-Build) and PSFirebird for cross-platform CI on Windows and Linux: - Build the driver with CMake (Release, x64) - Download and configure Firebird 5.0.2 via PSFirebird module - Create test databases (UTF-8 and ISO-8859-1) - Register the ODBC driver - Run the full test suite with three charset configurations Also: - Fix processorArchitecture in DLL manifest from X86 to wildcard (*) so the driver loads correctly on x64 and ARM64 builds - Remove linux.yml (superseded by build-and-test.yml) - Remove rpi_arm64.yml (niche; Linux CI covers this) - Clean up temporary branch names from msbuild workflow triggers --- .github/workflows/build-and-test.yml | 52 +++++ .github/workflows/linux.yml | 36 ---- .github/workflows/msbuild.yml | 4 +- .github/workflows/msbuild_arm64.yaml | 4 +- .github/workflows/rpi_arm64.yml | 37 ---- FirebirdODBC.dll.manifest | 4 +- README.md | 66 +++++-- firebird-odbc-driver.build.ps1 | 279 +++++++++++++++++++++++++++ install-prerequisites.ps1 | 25 +++ 9 files changed, 411 insertions(+), 96 deletions(-) create mode 100644 .github/workflows/build-and-test.yml delete mode 100644 .github/workflows/linux.yml delete mode 100644 .github/workflows/rpi_arm64.yml create mode 100644 firebird-odbc-driver.build.ps1 create mode 100644 install-prerequisites.ps1 diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 00000000..36cdd970 --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,52 @@ +name: Build and Test + +on: + push: + branches: [master] + pull_request: + branches: [master] + +permissions: + contents: read + +jobs: + build-and-test: + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + - os: ubuntu-22.04 + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Full history for git-tag-based versioning + + - name: Install prerequisites + shell: pwsh + run: ./install-prerequisites.ps1 + + - name: Install unixODBC (Linux) + if: runner.os == 'Linux' + run: sudo apt-get update && sudo apt-get install -y unixodbc unixodbc-dev + + - name: Build, install and test + shell: pwsh + run: Invoke-Build test -Configuration Release -File ./firebird-odbc-driver.build.ps1 + + - name: Upload driver (Windows) + if: runner.os == 'Windows' + uses: actions/upload-artifact@v4 + with: + name: FirebirdODBC-windows-x64 + path: build/Release/FirebirdODBC.dll + + - name: Upload driver (Linux) + if: runner.os == 'Linux' + uses: actions/upload-artifact@v4 + with: + name: FirebirdODBC-linux-x64 + path: build/libOdbcFb.so \ No newline at end of file diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml deleted file mode 100644 index f01e39d1..00000000 --- a/.github/workflows/linux.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Linux - -on: - push: - branches: [ "master", "new-build-system", "new-build-system-no-pr" ] - pull_request: - branches: [ "master" ] - -permissions: - contents: read - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install UnixODBC package - run: sudo apt-get install -y unixodbc unixodbc-dev - - - name: Configure CMake - run: cmake -B build -DCMAKE_BUILD_TYPE=Release - - - name: Build - run: cmake --build build --config Release - - - name: Run tests (no database — all tests skip) - run: ctest --test-dir build --output-on-failure - - - uses: actions/upload-artifact@v4 - with: - name: linux_x64_libs - path: | - ./build/libOdbcFb.so diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml index aa8780ef..dd0a6d32 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/msbuild.yml @@ -7,9 +7,9 @@ name: MSBuild on: push: - branches: [ "master", "new-build-system", "new-build-system-no-pr" ] + branches: [master] pull_request: - branches: [ "master" ] + branches: [master] env: # Path to the solution file relative to the root of the project. diff --git a/.github/workflows/msbuild_arm64.yaml b/.github/workflows/msbuild_arm64.yaml index 5b12a786..a4ed6c9d 100644 --- a/.github/workflows/msbuild_arm64.yaml +++ b/.github/workflows/msbuild_arm64.yaml @@ -7,9 +7,9 @@ name: MSBuild_ARM64 on: push: - branches: [ "master", "new-build-system", "new-build-system-no-pr" ] + branches: [master] pull_request: - branches: [ "master" ] + branches: [master] env: # Path to the solution file relative to the root of the project. diff --git a/.github/workflows/rpi_arm64.yml b/.github/workflows/rpi_arm64.yml deleted file mode 100644 index c6ca0bb2..00000000 --- a/.github/workflows/rpi_arm64.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: RaspberryPI - -on: - push: - branches: [ "master", "new-build-system", "new-build-system-no-pr" ] - pull_request: - branches: [ "master" ] - -permissions: - contents: read - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - uses: pguyot/arm-runner-action@v2 - with: - base_image: raspios_lite_arm64:latest - copy_repository_path: /opt/fb_odbc - copy_artifact_path: | - build/libOdbcFb.so - commands: | - sudo apt-get update - sudo apt-get install -y cmake unixodbc unixodbc-dev - cd /opt/fb_odbc - cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF - cmake --build build --config Release - - - uses: actions/upload-artifact@v4 - with: - name: linux_arm64_libs - path: | - libOdbcFb.so - diff --git a/FirebirdODBC.dll.manifest b/FirebirdODBC.dll.manifest index 26a507f7..1d17cf84 100644 --- a/FirebirdODBC.dll.manifest +++ b/FirebirdODBC.dll.manifest @@ -2,7 +2,7 @@ @@ -13,7 +13,7 @@ type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" - processorArchitecture="X86" + processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" /> diff --git a/README.md b/README.md index fdb9e1d5..09f2f720 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ All the new features and fixes are documented here - The latest build artifacts: * [Windows installation package](https://github.com/user-attachments/files/19207749/win_installers.zip) [![MSBuild](https://github.com/FirebirdSQL/firebird-odbc-driver/actions/workflows/msbuild.yml/badge.svg)](https://github.com/FirebirdSQL/firebird-odbc-driver/actions/workflows/msbuild.yml) -* [Linux x86-64](https://github.com/user-attachments/files/19207739/linux_libs.zip) [![Linux](https://github.com/FirebirdSQL/firebird-odbc-driver/actions/workflows/linux.yml/badge.svg)](https://github.com/FirebirdSQL/firebird-odbc-driver/actions/workflows/linux.yml) -* [Linux_ARM64](https://github.com/user-attachments/files/19210460/linux_arm64_libs.zip) [![RaspberryPI](https://github.com/FirebirdSQL/firebird-odbc-driver/actions/workflows/rpi_arm64.yml/badge.svg)](https://github.com/FirebirdSQL/firebird-odbc-driver/actions/workflows/rpi_arm64.yml) + +[![Build and Test](https://github.com/FirebirdSQL/firebird-odbc-driver/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/FirebirdSQL/firebird-odbc-driver/actions/workflows/build-and-test.yml) You can also download the lastest & archive build packages here: https://github.com/FirebirdSQL/firebird-odbc-driver/wiki @@ -108,21 +108,53 @@ Identifier handling options: ## Build from sources -### Linux -* Clone the git repository into your working copy folder -* Make sure you have Unix ODBC dev package installed. If not - install it (for example: `sudo apt install unixodbc-dev` for Ubuntu) -* Move to Builds/Gcc.lin -* Rename makefile.linux -> makefile -* Set the DEBUG var if you need a Debug build instead of Release (by default) -* Run `make` -* Your libraries are in ./Release_ or ./Debug_ folder. - -### Windows -* Clone the git repository into your working copy folder -* Open ``/Builds/MsVc2022.win/OdbcFb.sln with MS Visual Studio (VS2022 or later) -* Select your desired arch & build mode (debug|release) -* Build the project -* Copy the built library (``\Builds\MsVc2022.win\\`arch`\\`build_mode`\FirebirdODBC.dll) to ``\System32 (x64 arch) or ``\SysWOW64 (Win32 arch) +### Prerequisites + +Install [PowerShell](https://github.com/PowerShell/PowerShell) (v7+), then run: + +```powershell +./install-prerequisites.ps1 +``` + +This installs the required PowerShell modules ([InvokeBuild](https://github.com/nightroman/Invoke-Build) and [PSFirebird](https://github.com/fdcastel/PSFirebird)). + +On Linux, you also need the unixODBC development package: + +```bash +sudo apt-get install unixodbc unixodbc-dev +``` + +### Building + +```powershell +Invoke-Build build -Configuration Release +``` + +This runs CMake to configure and build the driver. The output is: +- **Windows**: `build/Release/FirebirdODBC.dll` +- **Linux**: `build/libOdbcFb.so` + +### Testing + +```powershell +Invoke-Build test -Configuration Release +``` + +This will build the driver, download Firebird 5.0, create test databases, register the ODBC driver, and run the full test suite with multiple charset configurations. + +### Available tasks + +| Task | Description | +|------|-------------| +| `build` | Build the driver and tests (default) | +| `test` | Build, install driver, create test databases, run tests | +| `install` | Register the ODBC driver on the system | +| `uninstall` | Unregister the ODBC driver | +| `clean` | Remove the build directory | + +### Alternative: Visual Studio + +You can also open `Builds/MsVc2022.win/OdbcFb.sln` with Visual Studio 2022 or later. Run `cmake -B build` first to fetch the required Firebird headers. ## Development & Feedback diff --git a/firebird-odbc-driver.build.ps1 b/firebird-odbc-driver.build.ps1 new file mode 100644 index 00000000..d7e06042 --- /dev/null +++ b/firebird-odbc-driver.build.ps1 @@ -0,0 +1,279 @@ +<# +.Synopsis + Build script for Firebird ODBC Driver (Invoke-Build) + +.Description + Tasks: clean, build, test, install, uninstall. + +.Parameter Configuration + Build configuration: Debug (default) or Release. +#> + +param( + [ValidateSet('Debug', 'Release')] + [string]$Configuration = 'Debug' +) + +# Detect OS +$IsWindowsOS = $IsWindows -or ($PSVersionTable.PSVersion.Major -le 5) +$IsLinuxOS = $IsLinux + +# Computed properties +$BuildDir = Join-Path $BuildRoot 'build' + +$DriverName = if ($Configuration -eq 'Release') { + 'Firebird ODBC Driver' +} else { + 'Firebird ODBC Driver (Debug)' +} + +if ($IsWindowsOS) { + $DriverFileName = 'FirebirdODBC.dll' + $DriverPath = Join-Path $BuildDir $Configuration $DriverFileName +} else { + $DriverFileName = 'libOdbcFb.so' + $DriverPath = Join-Path $BuildDir $DriverFileName +} + +# Synopsis: Remove the build directory. +task clean { + remove $BuildDir +} + +# Synopsis: Build the driver and tests (default task). +task build { + exec { cmake -B $BuildDir -S $BuildRoot -DCMAKE_BUILD_TYPE=$Configuration -DBUILD_TESTING=ON } + + if ($IsWindowsOS) { + exec { cmake --build $BuildDir --config $Configuration } + } else { + $jobs = 4 + try { $jobs = [int](nproc) } catch {} + exec { cmake --build $BuildDir --config $Configuration -- "-j$jobs" } + } + + assert (Test-Path $DriverPath) "Driver not found at: $DriverPath" +} + +# Synopsis: Create Firebird test databases. +task build-test-databases { + $fbVersion = '5.0.2' + $envPath = '/fbodbc-tests/fb502' + $dbPathUtf8 = '/fbodbc-tests/TEST.FB50.FDB' + $dbPathIso = '/fbodbc-tests/TEST-ISO.FB50.FDB' + + if ($IsLinuxOS) { + exec { sudo mkdir -p '/fbodbc-tests' } + exec { sudo chmod 777 '/fbodbc-tests' } + } else { + New-Item -ItemType Directory -Path '/fbodbc-tests' -Force | Out-Null + } + + Import-Module PSFirebird + + # Create or reuse Firebird environment + if (Test-Path (Join-Path $envPath 'firebird.msg')) { + $fb = Get-FirebirdEnvironment -Path $envPath + print Green "Reusing existing Firebird environment: $envPath" + } else { + $fb = New-FirebirdEnvironment -Version $fbVersion -Path $envPath -Force + print Green "Firebird environment created: $envPath" + } + + # Stop any running Firebird processes so database files can be replaced + if ($IsWindowsOS) { + Get-Service -Name 'FirebirdServer*' -ErrorAction SilentlyContinue | + Where-Object Status -eq 'Running' | + Stop-Service -Force -ErrorAction SilentlyContinue + } + $fbProcs = Get-Process -Name 'firebird' -ErrorAction SilentlyContinue + if ($fbProcs) { + $fbProcs | Stop-Process -Force -ErrorAction SilentlyContinue + $fbProcs | Wait-Process -Timeout 10 -ErrorAction SilentlyContinue + } + if ($IsLinuxOS) { + sudo pkill -f firebird 2>$null + Start-Sleep -Seconds 2 + } + + New-FirebirdDatabase -Database $dbPathUtf8 -Environment $fb -Force + print Green "UTF8 database created: $dbPathUtf8" + + New-FirebirdDatabase -Database $dbPathIso -Environment $fb -Charset ISO8859_1 -Force + print Green "ISO8859_1 database created: $dbPathIso" + + # Determine client library path + if ($IsWindowsOS) { + $script:ClientPath = (Resolve-Path (Join-Path $fb.Path 'fbclient.dll')).Path + } else { + $clientLib = Join-Path $fb.Path 'lib' 'libfbclient.so' + if (-not (Test-Path $clientLib)) { + $clientLib = Get-ChildItem -Path $fb.Path -Recurse -Filter 'libfbclient.so*' | + Select-Object -First 1 -ExpandProperty FullName + } + $script:ClientPath = $clientLib + } + + print Green "Client library: $script:ClientPath" +} + +# Synopsis: Run the test suite. +task test build, build-test-databases, install, { + if (-not $env:FIREBIRD_ODBC_CONNECTION) { + print Yellow 'WARNING: FIREBIRD_ODBC_CONNECTION environment variable is not set. Using built-in connection strings.' + } + + # Test suites that exercise charset/encoding-sensitive code paths. + $charsetSensitiveSuites = @( + 'WCharTest' + 'DataTypeTest' + 'CatalogTest' + 'CatalogFunctionsTest' + 'DescRecTest' + 'TypeInfoTest' + 'BlobTest' + 'ResultConversionsTest' + 'ParamConversionsTest' + 'EscapeSequenceTest' + ) + $charsetFilter = ($charsetSensitiveSuites | ForEach-Object { "$_.*" }) -join ':' + + $testConfigs = @( + @{ Database = '/fbodbc-tests/TEST.FB50.FDB'; Charset = 'UTF8'; Label = 'UTF8 database, UTF8 charset'; Filter = $null } + @{ Database = '/fbodbc-tests/TEST-ISO.FB50.FDB'; Charset = 'ISO8859_1'; Label = 'ISO8859_1 database, ISO8859_1 charset'; Filter = $charsetFilter } + @{ Database = '/fbodbc-tests/TEST-ISO.FB50.FDB'; Charset = 'UTF8'; Label = 'ISO8859_1 database, UTF8 charset'; Filter = $charsetFilter } + ) + + $passed = 0 + foreach ($cfg in $testConfigs) { + $env:FIREBIRD_ODBC_CONNECTION = "Driver={$DriverName};Database=$($cfg.Database);UID=SYSDBA;PWD=masterkey;CHARSET=$($cfg.Charset);CLIENT=$script:ClientPath" + print Cyan "--- Test run: $($cfg.Label) ---" + print Cyan " Connection: $env:FIREBIRD_ODBC_CONNECTION" + + if ($cfg.Filter) { + # Run only charset-sensitive suites for non-default configurations + $testExe = if ($IsWindowsOS) { + Join-Path $BuildDir 'tests' $Configuration 'firebird_odbc_tests.exe' + } else { + Join-Path $BuildDir 'tests' 'firebird_odbc_tests' + } + print Cyan " Filter: $($cfg.Filter)" + exec { & $testExe --gtest_filter=$($cfg.Filter) } + } else { + # Run full suite for the primary (UTF8) configuration + exec { ctest --test-dir $BuildDir -C $Configuration --output-on-failure } + } + $passed++ + } + + print Green "All $passed test runs passed." +} + +# Synopsis: Register the ODBC driver on the system. +task install build, { + if ($IsWindowsOS) { + Install-WindowsDriver + } elseif ($IsLinuxOS) { + Install-LinuxDriver + } else { + throw 'Unsupported OS. Only Windows and Linux are supported.' + } +} + +# Synopsis: Unregister the ODBC driver from the system. +task uninstall { + if ($IsWindowsOS) { + Uninstall-WindowsDriver + } elseif ($IsLinuxOS) { + Uninstall-LinuxDriver + } else { + throw 'Unsupported OS. Only Windows and Linux are supported.' + } +} + +# Synopsis: Build the driver and tests. +task . build + +#region Windows + +function Install-WindowsDriver { + $regBase = 'HKLM:\SOFTWARE\ODBC\ODBCINST.INI' + $regPath = Join-Path $regBase $DriverName + $driversPath = Join-Path $regBase 'ODBC Drivers' + + if (!(Test-Path $regPath)) { + New-Item -Path $regBase -Name $DriverName -Force | Out-Null + } + + Set-ItemProperty -Path $regPath -Name 'Driver' -Value $DriverPath -Type String -Force + Set-ItemProperty -Path $regPath -Name 'Setup' -Value $DriverPath -Type String -Force + Set-ItemProperty -Path $regPath -Name 'APILevel' -Value '1' -Type String -Force + Set-ItemProperty -Path $regPath -Name 'ConnectFunctions' -Value 'YYY' -Type String -Force + Set-ItemProperty -Path $regPath -Name 'DriverODBCVer' -Value '03.51' -Type String -Force + Set-ItemProperty -Path $regPath -Name 'FileUsage' -Value '0' -Type String -Force + Set-ItemProperty -Path $regPath -Name 'SQLLevel' -Value '1' -Type String -Force + + if (!(Test-Path $driversPath)) { + New-Item -Path $regBase -Name 'ODBC Drivers' -Force | Out-Null + } + Set-ItemProperty -Path $driversPath -Name $DriverName -Value 'Installed' -Type String -Force + + print Green "Driver '$DriverName' registered: $DriverPath" +} + +function Uninstall-WindowsDriver { + $regBase = 'HKLM:\SOFTWARE\ODBC\ODBCINST.INI' + $regPath = Join-Path $regBase $DriverName + $driversPath = Join-Path $regBase 'ODBC Drivers' + + if (Test-Path $regPath) { + Remove-Item -Path $regPath -Recurse -Force + } + if (Test-Path $driversPath) { + Remove-ItemProperty -Path $driversPath -Name $DriverName -ErrorAction SilentlyContinue + } + + print Green "Driver '$DriverName' unregistered." +} + +#endregion + +#region Linux + +function Install-LinuxDriver { + if (-not (Get-Command odbcinst -ErrorAction Ignore)) { + throw 'odbcinst not found. Install unixODBC: sudo apt-get install unixodbc' + } + + $driverAbsPath = (Resolve-Path $DriverPath).Path + + $tempIni = [System.IO.Path]::GetTempFileName() + try { + @" +[$DriverName] +Description = $DriverName +Driver = $driverAbsPath +Setup = $driverAbsPath +Threading = 0 +FileUsage = 0 +"@ | Set-Content -Path $tempIni + + exec { sudo odbcinst -i -d -f $tempIni -r } + } finally { + Remove-Item -Path $tempIni -Force -ErrorAction SilentlyContinue + } + + print Green "Driver '$DriverName' registered: $driverAbsPath" +} + +function Uninstall-LinuxDriver { + if (-not (Get-Command odbcinst -ErrorAction Ignore)) { + throw 'odbcinst not found. Install unixODBC: sudo apt-get install unixodbc' + } + + exec { odbcinst -u -d -n $DriverName } + + print Green "Driver '$DriverName' unregistered." +} + +#endregion \ No newline at end of file diff --git a/install-prerequisites.ps1 b/install-prerequisites.ps1 new file mode 100644 index 00000000..e113df8a --- /dev/null +++ b/install-prerequisites.ps1 @@ -0,0 +1,25 @@ +<# +.Synopsis + Install prerequisites for building and testing the Firebird ODBC Driver. + +.Description + Installs required PowerShell modules: PSFirebird and InvokeBuild. + This script must be separate from the Invoke-Build script because + it installs Invoke-Build itself. +#> + +[CmdletBinding()] +param() + +$ErrorActionPreference = 'Stop' + +Set-PSRepository -Name PSGallery -InstallationPolicy Trusted + +Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser -ForceBootstrap -ErrorAction Continue + +if ($IsLinux) { + Register-PackageSource -Name 'NuGet' -Location 'https://api.nuget.org/v3/index.json' -ProviderName NuGet -Force +} + +Install-Module -Name PSFirebird -Force -AllowClobber -Scope CurrentUser -Repository PSGallery +Install-Module -Name InvokeBuild -Force -Scope CurrentUser \ No newline at end of file