tiberius 0.13.0

A TDS (MSSQL) driver
Documentation
name: Cargo tests
on:
  # qa + manual dispatch run the integration tier
  push:
    branches:
      - main
      - qa
  pull_request:
  workflow_dispatch:
jobs:
  clippy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9  # v1
        with:
          toolchain: stable
          components: clippy
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2.9.1
      - name: Install dependencies
        run: sudo apt-get update && sudo apt-get install -y openssl libkrb5-dev
      - name: Clippy
        # Advisory here: modernizes the retired actions-rs/clippy-check and reports
        # lints without gating. The strict `-D warnings` gate lands together with its
        # baseline-lint fixes in the feature stack, so main is never red in between.
        run: cargo clippy --features=all

  format:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9  # v1
        with:
          toolchain: stable
          components: rustfmt
      - name: Rustfmt
        run: cargo fmt --check

  msrv:
    name: MSRV (1.88)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      # Keep this in sync with `rust-version` in Cargo.toml.
      - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: "1.88"
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
      - name: Install dependencies
        run: sudo apt-get update && sudo apt-get install -y openssl libkrb5-dev
      - name: Check on MSRV
        run: cargo check --features all

  # The `rustls-webpki-roots` feature (and the rustls trust-store code paths in
  # general) are excluded from `--features=all` because the three TLS backends
  # are mutually exclusive, so neither the clippy nor the MSRV job above builds
  # them. This server-less lane keeps them clippy-clean, buildable, and unit-
  # tested so a regression (e.g. a `webpki-roots` major bump changing
  # `TLS_SERVER_ROOTS`) is caught in CI.
  rustls-features:
    name: rustls trust-store (unit)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: stable
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
      - name: Install dependencies
        run: sudo apt-get update && sudo apt-get install -y openssl libkrb5-dev
      # Build + unit-test both rustls feature sets. `--lib` needs no live server.
      # (Strict `-D warnings` clippy is deferred repo-wide until the baseline
      # lints land, matching the advisory `clippy` job above.)
      - name: Unit tests (rustls)
        run: cargo test --no-default-features --features rustls,chrono,time,tds73 --lib
      - name: Unit tests (rustls-webpki-roots)
        run: cargo test --no-default-features --features rustls-webpki-roots,chrono,time,tds73 --lib

  semver:
    name: semver-checks (advisory)
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    # Advisory during 0.x: reports API-breaking changes vs the target branch
    # without blocking (breaking changes are allowed pre-1.0, but should be
    # visible in review).
    continue-on-error: true
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
          fetch-depth: 0
      - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: stable
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
      - name: Install dependencies
        run: sudo apt-get update && sudo apt-get install -y openssl libkrb5-dev
      - name: Install cargo-semver-checks
        uses: taiki-e/install-action@cargo-semver-checks
      - name: Fetch baseline branch
        # `actions/checkout` leaves the PR base branch without a local ref, so
        # `--baseline-rev origin/<base>` can't be resolved; fetch it explicitly
        # and compare against FETCH_HEAD.
        run: git fetch --no-tags --depth=100 origin "${{ github.base_ref }}"
      - name: Check for semver-breaking changes
        # Scope to one coherent, non-conflicting feature set. Checking all
        # features at once enables the mutually-exclusive TLS backends
        # (native-tls + rustls + vendored-openssl) together, whose duplicate
        # `TlsStream` definitions make rustdoc fail to build (E0428). These are
        # also the crate's original features, so they exist in every baseline
        # slice this PR is compared against.
        run: >-
          cargo semver-checks --baseline-rev FETCH_HEAD
          --only-explicit-features
          --features rustls,chrono,time,tds73,rust_decimal,bigdecimal

  smoke:
    name: integration smoke (SQL 2022)
    # Fast real-server signal on the dev lane; the full matrix runs on qa.
    if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/dev')
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        database:
          - 2017
          - 2019
          - 2022
          - azure-sql-edge
        features:
          - "--features=all"
          - "--no-default-features"
          - "--no-default-features --features=chrono"
          - "--no-default-features --features=time"
          - "--no-default-features --features=rustls"
          - "--no-default-features --features=vendored-openssl"
          - "--no-default-features --features=rustls,chrono,time,tds73,rust_decimal,bigdecimal"

    env:
      TIBERIUS_TEST_CONNECTION_STRING: "server=tcp:localhost,1433;user=SA;password=<YourStrong@Passw0rd>;TrustServerCertificate=true"
      RUSTFLAGS: "-Dwarnings"

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          persist-credentials: false

      - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9  # v1
        with:
          toolchain: stable

      - name: Compute cache key
        shell: bash
        run: |
          key="${{ matrix.features }}"
          key="${key//,/+}"
          echo "RUST_CACHE_KEY=$key" >> "$GITHUB_ENV"

      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2.9.1
        with:
          shared-key: ${{ env.RUST_CACHE_KEY }}

      - name: Start SQL Server ${{matrix.database}}
        run: DOCKER_BUILDKIT=1 docker compose -f docker-compose.yml up -d mssql-${{matrix.database}}

      - name: Install dependencies
        run: sudo apt-get update && sudo apt-get install -y openssl libkrb5-dev

      - name: Wait for SQL Server
        # A listening port is not readiness: SQL Server binds 1433 before the SA
        # login and databases finish initializing, so tests started too early race
        # it and hit sporadic connection/login failures. Gate on an authenticated
        # `SELECT 1` from a throwaway mssql-tools container (works uniformly across
        # the full server images and azure-sql-edge, which ships no in-box sqlcmd).
        run: |
          pw='<YourStrong@Passw0rd>'
          for _ in $(seq 1 60); do
            if docker run --rm --network host mcr.microsoft.com/mssql-tools \
                 /opt/mssql-tools/bin/sqlcmd -S localhost,1433 -U SA -P "$pw" -Q "SELECT 1" >/dev/null 2>&1; then
              echo "SQL Server ready (authenticated login succeeded)"; exit 0
            fi
            sleep 3
          done
          echo "SQL Server did not accept an authenticated login in time" >&2
          docker compose -f docker-compose.yml logs mssql-${{matrix.database}} || true
          exit 1

      - name: Run tests
        run: cargo test ${{matrix.features}}

  integration-macos:
    name: macos (SQL 2022 via colima)
    if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/qa')
    # Intel runner: hosted macOS has no Linux Docker daemon, so we host the
    # linux/amd64 SQL Server container inside a colima (Lima) Linux VM. An x86_64
    # runner runs that image natively — no qemu emulation — which keeps the VM
    # fast enough for the full integration suite instead of build + unit only.
    runs-on: macos-15-intel
    continue-on-error: ${{ matrix.soft_fail }}
    strategy:
      fail-fast: false
      matrix:
        # Exercise every TLS backend:
        include:
          # rustls (TLS 1.3)
          - features: "--no-default-features --features=rustls,chrono,time,tds73,rust_decimal,bigdecimal"
            soft_fail: false
          # vendored-openssl (opentls, statically-linked OpenSSL) — cross-platform.
          - features: "--no-default-features --features=vendored-openssl,chrono,time,tds73,rust_decimal,bigdecimal"
            soft_fail: false
          # NOTE: a `--features=all` lane is intentionally omitted here. On macOS
          # `native-tls` resolves to Apple Secure Transport, which cannot complete
          # the SQL Server TLS handshake (it works on Linux=OpenSSL and
          # Windows=SChannel, both covered elsewhere). Running it here could only
          # ever fail, so the two TLS backends that do work on macOS (rustls and
          # vendored-openssl, above) provide the macOS integration coverage.
    env:
      TIBERIUS_TEST_CONNECTION_STRING: "server=tcp:localhost,1433;user=SA;password=<YourStrong@Passw0rd>;TrustServerCertificate=true"
      RUSTFLAGS: "-Dwarnings"
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: stable
      - name: Compute cache key
        run: |
          key="${{ matrix.features }}"
          key="${key//,/+}"
          echo "RUST_CACHE_KEY=$key" >> "$GITHUB_ENV"
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
        with:
          shared-key: ${{ env.RUST_CACHE_KEY }}
      - name: Install build dependencies (openssl, krb5)
        run: |
          brew install openssl krb5
          # krb5 is keg-only; expose its pkg-config so integrated-auth-gssapi
          # and any openssl-linking features build against Homebrew's copy.
          echo "PKG_CONFIG_PATH=$(brew --prefix krb5)/lib/pkgconfig:$(brew --prefix openssl)/lib/pkgconfig" >> "$GITHUB_ENV"
      - name: Start Docker (colima)
        run: |
          brew install colima docker docker-compose
          # SQL Server wants ~2 GB RAM; give the VM headroom for it + the build.
          colima start --cpu 3 --memory 6 --disk 20
          docker version
      - name: Start SQL Server 2022
        run: docker compose -f docker-compose.yml up -d mssql-2022
      - name: Wait for SQL Server
        # A listening port is not readiness: SQL Server binds 1433 before the SA
        # login and databases finish initializing, so the connection-heavy bulk
        # tests can race it and hit "Login failed for user 'SA'" (18456). Gate on
        # an actual authenticated `SELECT 1` succeeding instead.
        run: |
          pw='<YourStrong@Passw0rd>'
          for _ in $(seq 1 60); do
            for bin in /opt/mssql-tools18/bin/sqlcmd /opt/mssql-tools/bin/sqlcmd; do
              if docker compose -f docker-compose.yml exec -T mssql-2022 \
                   "$bin" -S localhost -U SA -P "$pw" -C -Q "SELECT 1" >/dev/null 2>&1; then
                echo "SQL Server ready (authenticated login succeeded)"; exit 0
              fi
            done
            sleep 3
          done
          echo "SQL Server did not accept an authenticated login in time" >&2
          docker compose -f docker-compose.yml logs mssql-2022 || true
          exit 1
      - name: Run tests
        run: cargo test ${{ matrix.features }}

  integration-windows:
    name: windows (SQL 2019, integrated auth)
    if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/qa')
    runs-on: windows-latest

    strategy:
      fail-fast: false
      matrix:
        database:
          - 2019
        features:
          - "--features=all"
          - "--no-default-features --features=rustls,winauth"
          - "--no-default-features --features=vendored-openssl,winauth"

    env:
      TIBERIUS_TEST_INSTANCE: "MSSQLSERVER"
      TIBERIUS_TEST_CONNECTION_STRING: "server=tcp:127.0.0.1,1433;IntegratedSecurity=true;TrustServerCertificate=true"

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          persist-credentials: false

      - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9  # v1
        with:
          toolchain: stable

      - name: Compute cache key
        shell: bash
        run: |
          key="${{ matrix.features }}"
          key="${key//,/+}"
          echo "RUST_CACHE_KEY=$key" >> "$GITHUB_ENV"

      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4  # v2.9.1
        with:
          shared-key: ${{ env.RUST_CACHE_KEY }}

      - name: Set required PowerShell modules
        id: psmodulecache
        uses: potatoqualitee/psmodulecache@ee5e9494714abf56f6efbfa51527b2aec5c761b8  # v6.2.1
        with:
          modules-to-cache: SqlServer

      - name: Setup Chocolatey download cache
        id: chococache
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae  # v5.0.5
        with:
          path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey\
          key: chocolatey-install

      - name: Install required PowerShell modules
        shell: powershell
        run: |
            Set-PSRepository PSGallery -InstallationPolicy Trusted
            Install-Module SqlServer

      - name: Install SQL Server ${{matrix.database}}
        shell: powershell
        run: |
          choco feature disable --name="'exitOnRebootDetected'"
          $ErrorActionPreference = 'SilentlyContinue'
          choco install sql-server-${{matrix.database}} --params="'/IgnorePendingReboot'"

      - name: Setup SQL Server ${{matrix.database}}
        shell: powershell
        run: |
          Import-Module 'sqlps'

          [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null
          [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SqlWmiManagement") | Out-Null

          $serverName = $env:COMPUTERNAME
          $instanceName = "MSSQLSERVER"

          $smo = 'Microsoft.SqlServer.Management.Smo.'
          $wmi = new-object ($smo + 'Wmi.ManagedComputer')
          $wmi

          # Enable TCP/IP
          echo "Enabling TCP/IP"
          $Tcp = $wmi.GetSmoObject("ManagedComputer[@Name='$serverName']/ServerInstance[@Name='$instanceName']/ServerProtocol[@Name='Tcp']")
          $Tcp.IsEnabled = $true
          $Tcp.alter()
          $Tcp

          # Enable named pipes
          echo "Enabling named pipes"
          $Np = $wmi.GetSmoObject("ManagedComputer[@Name='$serverName']/ServerInstance[@Name='$instanceName']/ServerProtocol[@Name='Np']")
          $Np.IsEnabled = $true
          $Np.Alter()
          $Np

          # Set Alias
          echo "Setting the alias"
          New-Item HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client -Name ConnectTo | Out-Null
          Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo -Name '(local)' -Value "DBMSSOCN,$serverName\$instanceName" | Out-Null

          # Start services
          echo "Starting services"
          Set-Service SQLBrowser -StartupType Manual
          Start-Service SQLBrowser
          net stop MSSQLSERVER
          net start MSSQLSERVER

      - name: Run normal tests
        shell: powershell
        run: cargo test ${{matrix.features}}