diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f71280e..3c2f367 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,8 @@ jobs: matrix: os: [windows-latest, ubuntu-latest] sqlserver: + - label: 'SQL Server 2025' + version: '2025' - label: 'SQL Server 2022' version: '2022' - label: 'SQL Server 2019' @@ -42,3 +44,44 @@ jobs: $result = sqlcmd -Q "SELECT DB_NAME() as CatalogName" -d "my-test-catalog" echo $result + ci-full-text-search: + runs-on: ${{ matrix.os }} + name: ${{ matrix.name }}-${{ matrix.sqlserver.label }}-FTS + strategy: + fail-fast: false + matrix: + os: [windows-latest, ubuntu-latest] + sqlserver: + - label: 'SQL Server 2025' + version: '2025' + - label: 'SQL Server 2022' + version: '2022' + - label: 'SQL Server 2019' + version: '2019' + include: + - os: windows-latest + name: Windows + - os: ubuntu-latest + name: Linux + steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Run with FTS + uses: ./ + with: + connection-string-env-var: SQL_CONN_STR + catalog: my-test-catalog + sqlserver-version: ${{ matrix.sqlserver.version }} + enable-full-text-search: "true" + - name: Check FTS result + shell: pwsh + run: | + $connstr = $Env:SQL_CONN_STR + Write-Host "Connection String: $connstr" + + sqlcmd -b -Q "IF FULLTEXTSERVICEPROPERTY('IsFullTextInstalled') <> 1 THROW 50001, 'Full-Text Search is not installed.', 1;" + sqlcmd -b -Q "USE [my-test-catalog]; + CREATE TABLE dbo.FullTextSmoke (Id INT NOT NULL, Content NVARCHAR(200) NOT NULL); + CREATE UNIQUE INDEX UX_FullTextSmoke_Id ON dbo.FullTextSmoke(Id); + CREATE FULLTEXT CATALOG SmokeCatalog AS DEFAULT; + CREATE FULLTEXT INDEX ON dbo.FullTextSmoke(Content LANGUAGE 1033) KEY INDEX UX_FullTextSmoke_Id;" diff --git a/README.md b/README.md index 6791ae5..dae0cc6 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,18 @@ steps: extra-params: "Max Pool Size=100;" ``` +To enable SQL Server Full-Text Search: + +```yaml +steps: + - name: Install SQL Server + uses: Particular/install-sql-server-action@v1.4.0 # Check if this is the latest version at https://github.com/Particular/install-sql-server-action/tags + with: + connection-string-env-var: SQL_SERVER_CONNECTION_STRING + catalog: nservicebus + enable-full-text-search: "true" +``` + ## Parameters | Parameter | Required | Default | Description | @@ -56,6 +68,12 @@ steps: | `collation` | No | `SQL_Latin1_General_CP1_CS_AS` | The collation to use for the SQL Server database. Override to any available [SQL collation](https://learn.microsoft.com/en-us/sql/relational-databases/collations/collation-and-unicode-support). | | `sqlserver-version` | No | `2022` | The SQL server major version to use. | | `extra-params` | No | - | Extra parameters to be appended to the end of the connection string. | +| `enable-full-text-search` | No | `"false"` | When set to `"true"`, the action installs/enables and verifies SQL Server Full-Text Search before completion. | + +When `enable-full-text-search` is enabled, setup time may increase because extra SQL components/packages are installed. +On Windows, this switches installation to Chocolatey's `sql-server-express-adv` package so Full-Text Search is available. +On Linux, the action adds the matching Microsoft SQL Server apt feed and installs `mssql-server-fts` for the requested SQL Server major version. +Current Full-Text Search setup support includes SQL Server major versions `2019`, `2022`, and `2025`. ## Using `sqlcmd` diff --git a/action.yml b/action.yml index a951991..494b75b 100644 --- a/action.yml +++ b/action.yml @@ -19,6 +19,10 @@ inputs: extra-params: description: Extra parameters to add to the connection string required: false + enable-full-text-search: + description: Enable SQL Server Full-Text Search installation + required: false + default: "false" runs: using: "composite" steps: @@ -27,26 +31,27 @@ runs: shell: pwsh run: | # Windows SQL install via Chocolatey - $template = @' - {[string]Package*:sql-server-express}|{[int]Major:2022}.{[int]Minor:16}.{[int]Patch:0}.{[int]Build:1000} - {[string]Package*:sql-server-express}|{[int]Major:2022}.{[int]Minor:16}.{[int]Patch:0}.{[int]Build:0} - {[string]Package*:sql-server-express}|{[int]Major:14}.{[int]Minor:1801}.{[int]Patch:3958}.{[int]Build:1} - '@ - - # Limited output should be sql-server-express|versionstring - $availableVersions = choco search sql-server-express --exact --all-versions --limit-output | Where-Object { $_ -like "*${{ inputs.sqlserver-version }}**" } - # IncludeExtent will feed the input into an ExtendText property. Using the template examples helps to order by Major which is all we are interested in - $sortedVersions = $availableVersions | ConvertFrom-String -TemplateContent $template -IncludeExtent | Sort-Object -Property Major -Descending - $newestVersion = $sortedVersions[0].ExtentText.Split("|")[1] + $enableFts = '${{ inputs.enable-full-text-search }}' -eq 'true' + $packageName = if ($enableFts) { 'sql-server-express-adv' } else { 'sql-server-express' } + + # Limited output is package|version + $newestVersion = choco search $packageName --exact --all-versions --limit-output ` + | ForEach-Object { ($_ -split '\|')[1] } ` + | Where-Object { $_ -like "${{ inputs.sqlserver-version }}*" } ` + | Sort-Object { [version](($_ -split '-')[0]) } -Descending ` + | Select-Object -First 1 + + $installArgs = @('install', $packageName, '-y', '--no-progress') if ($newestVersion) { - Write-Output "Installing SQL Server Express version $newestVersion with Chocolatey..." - choco install sql-server-express --version $newestVersion -y --no-progress + $installArgs += @('--version', $newestVersion) + Write-Output "Installing $packageName version $newestVersion with Chocolatey..." } else { - Write-Output "No versions found matching the prefix '${{ inputs.sqlserver-version }}'. Installing latest with Chocolatey..." - choco install sql-server-express --no-progress + Write-Output "No versions found matching the prefix '${{ inputs.sqlserver-version }}'. Installing latest $packageName with Chocolatey..." } + choco @installArgs + Write-Output "Setting environment variables for sqlcmd..." Write-Output "SQLCMDSERVER=.\SQLEXPRESS" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append @@ -62,15 +67,71 @@ runs: sa_pw=$(uuidgen) echo "::add-mask::$sa_pw" - echo "Starting SQL Server in a Docker container..." - docker run -e "ACCEPT_EULA=Y" \ - -e "SA_PASSWORD=$sa_pw" \ - -e "MSSQL_PID=Developer" \ - -e "MSSQL_COLLATION=${{ inputs.collation }}" \ - -e "SQLCMDSERVER=localhost" \ - -e "SQLCMDUSER=sa" \ - -e "SQLCMDPASSWORD=$sa_pw" \ - -p 1433:1433 --name sqlserver -d mcr.microsoft.com/mssql/server:${{ inputs.sqlserver-version }}-latest + image="mcr.microsoft.com/mssql/server:${{ inputs.sqlserver-version }}-latest" + base_run_args=( + -e "ACCEPT_EULA=Y" + -e "SA_PASSWORD=$sa_pw" + -e "MSSQL_PID=Developer" + -e "MSSQL_COLLATION=${{ inputs.collation }}" + -e "SQLCMDSERVER=localhost" + -e "SQLCMDUSER=sa" + -e "SQLCMDPASSWORD=$sa_pw" + -p 1433:1433 + --name sqlserver + -d + ) + + if [ "${{ inputs.enable-full-text-search }}" = "true" ]; then + echo "Starting SQL Server container in setup mode for Full-Text Search installation..." + docker run "${base_run_args[@]}" --entrypoint /bin/bash "$image" -lc "sleep infinity" + else + echo "Starting SQL Server in a Docker container..." + docker run "${base_run_args[@]}" "$image" + fi + + if [ "${{ inputs.enable-full-text-search }}" = "true" ]; then + case "${{ inputs.sqlserver-version }}" in + 2025*) sql_engine_major=17; repo_channel=2025 ;; + 2022*) sql_engine_major=16; repo_channel=2022 ;; + 2019*) sql_engine_major=15; repo_channel=2019 ;; + *) + echo "Unsupported sqlserver-version for FTS: '${{ inputs.sqlserver-version }}'. Supported values: 2019, 2022, 2025." >&2 + exit 1 + ;; + esac + + echo "Installing Full-Text Search support in the SQL Server container..." + docker exec -u 0 sqlserver bash -lc " + set -euo pipefail + apt-get update + ACCEPT_EULA=Y apt-get install -y --no-install-recommends curl gnupg + + . /etc/os-release + curl -fsSL https://packages.microsoft.com/keys/microsoft.asc \ + | gpg --dearmor > /usr/share/keyrings/microsoft-prod.gpg + echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/ubuntu/\${VERSION_ID}/mssql-server-${repo_channel} \${VERSION_CODENAME} main\" \ + > /etc/apt/sources.list.d/mssql-server.list + + apt-get update + + fts_version=\$(apt-cache madison mssql-server-fts \ + | awk '{print \$3}' \ + | grep -E '^${sql_engine_major}\.' \ + | head -n 1) + + if [ -z \"\${fts_version}\" ]; then + echo \"No mssql-server-fts package found for SQL Server engine major ${sql_engine_major}.\" >&2 + exit 1 + fi + + ACCEPT_EULA=Y apt-get install -y --no-install-recommends \"mssql-server-fts=\${fts_version}\" + apt-get clean + rm -rf /var/lib/apt/lists/* + " + + echo "Starting SQL Server process..." + docker exec -d sqlserver /opt/mssql/bin/sqlservr + fi echo "Creating `sqlcmd` bash script to forward commands via docker exec" mkdir -p ~/bin @@ -91,6 +152,7 @@ runs: shell: pwsh run: | # Wait for availability then create initial catalog + $enableFts = '${{ inputs.enable-full-text-search }}' -eq 'true' for ($i = 1; $i -le 30; $i++) { Write-Output "Attempt $i/30 to connect to SQL Server..." @@ -104,5 +166,13 @@ runs: } } + if ($enableFts) { + Write-Output "Verifying Full-Text Search availability..." + $ftsInstalled = (sqlcmd -h -1 -W -Q "SET NOCOUNT ON; SELECT FULLTEXTSERVICEPROPERTY('IsFullTextInstalled');").Trim() + if ($LASTEXITCODE -ne 0 -or $ftsInstalled -ne '1') { + throw "Full-Text Search was requested but is not available." + } + } + Write-Output "Creating initial catalog '${{ inputs.catalog }}'" sqlcmd -Q "CREATE DATABASE [${{ inputs.catalog }}]"