Skip to content

Commit 1b95689

Browse files
Add CI pipeline for multi-version SQL Server testing
- sql-tests.yml: Matrix testing on SQL Server 2017/2019/2022/2025 - Regenerates DarlingData.sql from current branch via Merge-All.ps1 - Installs all procs and verifies 9 exist via OBJECT_ID checks - test_help_output.sql: Validates @help=1 for all 9 procedures - test_basic_execution.sql: Default execution for 6 safe procedures All tests verified locally against sql2022 (9/9 help, 6/6 execution). See issue #664 for details. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4747a47 commit 1b95689

3 files changed

Lines changed: 361 additions & 0 deletions

File tree

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
CI Test: Run default execution for procedures that are safe to execute without special setup.
3+
Procs requiring extended events or special data (sp_HumanEvents, sp_HumanEventsBlockViewer,
4+
sp_QueryReproBuilder) are tested with @help = 1 only (see test_help_output.sql).
5+
Uses a temp table to track results across GO batches.
6+
*/
7+
8+
SET NOCOUNT ON;
9+
10+
CREATE TABLE #exec_results (proc_name VARCHAR(100) NOT NULL, passed BIT NOT NULL);
11+
GO
12+
13+
PRINT '========================================';
14+
PRINT 'Testing default execution';
15+
PRINT '========================================';
16+
PRINT '';
17+
GO
18+
19+
/* sp_PressureDetector - detects CPU and memory pressure */
20+
BEGIN TRY
21+
EXEC dbo.sp_PressureDetector;
22+
INSERT #exec_results VALUES ('sp_PressureDetector', 1);
23+
PRINT 'PASS: sp_PressureDetector (default)';
24+
END TRY
25+
BEGIN CATCH
26+
INSERT #exec_results VALUES ('sp_PressureDetector', 0);
27+
PRINT 'FAIL: sp_PressureDetector - ' + ERROR_MESSAGE();
28+
END CATCH;
29+
GO
30+
31+
/* sp_PerfCheck - comprehensive performance health check */
32+
BEGIN TRY
33+
EXEC dbo.sp_PerfCheck;
34+
INSERT #exec_results VALUES ('sp_PerfCheck', 1);
35+
PRINT 'PASS: sp_PerfCheck (default)';
36+
END TRY
37+
BEGIN CATCH
38+
INSERT #exec_results VALUES ('sp_PerfCheck', 0);
39+
PRINT 'FAIL: sp_PerfCheck - ' + ERROR_MESSAGE();
40+
END CATCH;
41+
GO
42+
43+
/* sp_HealthParser - analyzes system health extended event */
44+
BEGIN TRY
45+
EXEC dbo.sp_HealthParser;
46+
INSERT #exec_results VALUES ('sp_HealthParser', 1);
47+
PRINT 'PASS: sp_HealthParser (default)';
48+
END TRY
49+
BEGIN CATCH
50+
INSERT #exec_results VALUES ('sp_HealthParser', 0);
51+
PRINT 'FAIL: sp_HealthParser - ' + ERROR_MESSAGE();
52+
END CATCH;
53+
GO
54+
55+
/* sp_LogHunter - searches error logs */
56+
BEGIN TRY
57+
EXEC dbo.sp_LogHunter;
58+
INSERT #exec_results VALUES ('sp_LogHunter', 1);
59+
PRINT 'PASS: sp_LogHunter (default)';
60+
END TRY
61+
BEGIN CATCH
62+
INSERT #exec_results VALUES ('sp_LogHunter', 0);
63+
PRINT 'FAIL: sp_LogHunter - ' + ERROR_MESSAGE();
64+
END CATCH;
65+
GO
66+
67+
/* sp_IndexCleanup - identifies unused/duplicate indexes */
68+
BEGIN TRY
69+
EXEC dbo.sp_IndexCleanup
70+
@database_name = N'DarlingData_CI_Test';
71+
INSERT #exec_results VALUES ('sp_IndexCleanup', 1);
72+
PRINT 'PASS: sp_IndexCleanup (default)';
73+
END TRY
74+
BEGIN CATCH
75+
INSERT #exec_results VALUES ('sp_IndexCleanup', 0);
76+
PRINT 'FAIL: sp_IndexCleanup - ' + ERROR_MESSAGE();
77+
END CATCH;
78+
GO
79+
80+
/* sp_QuickieStore - navigates Query Store data */
81+
BEGIN TRY
82+
EXEC dbo.sp_QuickieStore
83+
@database_name = N'DarlingData_CI_Test';
84+
INSERT #exec_results VALUES ('sp_QuickieStore', 1);
85+
PRINT 'PASS: sp_QuickieStore (default)';
86+
END TRY
87+
BEGIN CATCH
88+
INSERT #exec_results VALUES ('sp_QuickieStore', 0);
89+
PRINT 'FAIL: sp_QuickieStore - ' + ERROR_MESSAGE();
90+
END CATCH;
91+
GO
92+
93+
/* Summary - fail the build if any test failed */
94+
PRINT '';
95+
PRINT '========================================';
96+
97+
DECLARE @failed int = (SELECT COUNT(*) FROM #exec_results WHERE passed = 0);
98+
DECLARE @total int = (SELECT COUNT(*) FROM #exec_results);
99+
100+
PRINT 'Basic execution: ' + CONVERT(varchar(10), @total - @failed) + '/' + CONVERT(varchar(10), @total) + ' passed';
101+
102+
IF @failed > 0
103+
RAISERROR('%d procedure(s) failed default execution', 16, 1, @failed);
104+
ELSE
105+
PRINT 'All procedures passed';
106+
107+
PRINT '========================================';
108+
109+
DROP TABLE #exec_results;
110+
GO

.github/sql/test_help_output.sql

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
CI Test: Validate @help = 1 output for all procedures.
3+
Uses a temp table to track results across GO batches.
4+
Fails with RAISERROR if any proc errors on @help = 1.
5+
*/
6+
7+
SET NOCOUNT ON;
8+
9+
CREATE TABLE #help_results (proc_name VARCHAR(100) NOT NULL, passed BIT NOT NULL);
10+
GO
11+
12+
PRINT '========================================';
13+
PRINT 'Testing @help = 1 for all procedures';
14+
PRINT '========================================';
15+
PRINT '';
16+
GO
17+
18+
/* sp_HealthParser */
19+
BEGIN TRY
20+
EXEC dbo.sp_HealthParser @help = 1;
21+
INSERT #help_results VALUES ('sp_HealthParser', 1);
22+
PRINT 'PASS: sp_HealthParser @help = 1';
23+
END TRY
24+
BEGIN CATCH
25+
INSERT #help_results VALUES ('sp_HealthParser', 0);
26+
PRINT 'FAIL: sp_HealthParser @help = 1 - ' + ERROR_MESSAGE();
27+
END CATCH;
28+
GO
29+
30+
/* sp_HumanEvents */
31+
BEGIN TRY
32+
EXEC dbo.sp_HumanEvents @help = 1;
33+
INSERT #help_results VALUES ('sp_HumanEvents', 1);
34+
PRINT 'PASS: sp_HumanEvents @help = 1';
35+
END TRY
36+
BEGIN CATCH
37+
INSERT #help_results VALUES ('sp_HumanEvents', 0);
38+
PRINT 'FAIL: sp_HumanEvents @help = 1 - ' + ERROR_MESSAGE();
39+
END CATCH;
40+
GO
41+
42+
/* sp_HumanEventsBlockViewer */
43+
BEGIN TRY
44+
EXEC dbo.sp_HumanEventsBlockViewer @help = 1;
45+
INSERT #help_results VALUES ('sp_HumanEventsBlockViewer', 1);
46+
PRINT 'PASS: sp_HumanEventsBlockViewer @help = 1';
47+
END TRY
48+
BEGIN CATCH
49+
INSERT #help_results VALUES ('sp_HumanEventsBlockViewer', 0);
50+
PRINT 'FAIL: sp_HumanEventsBlockViewer @help = 1 - ' + ERROR_MESSAGE();
51+
END CATCH;
52+
GO
53+
54+
/* sp_IndexCleanup */
55+
BEGIN TRY
56+
EXEC dbo.sp_IndexCleanup @help = 1;
57+
INSERT #help_results VALUES ('sp_IndexCleanup', 1);
58+
PRINT 'PASS: sp_IndexCleanup @help = 1';
59+
END TRY
60+
BEGIN CATCH
61+
INSERT #help_results VALUES ('sp_IndexCleanup', 0);
62+
PRINT 'FAIL: sp_IndexCleanup @help = 1 - ' + ERROR_MESSAGE();
63+
END CATCH;
64+
GO
65+
66+
/* sp_LogHunter */
67+
BEGIN TRY
68+
EXEC dbo.sp_LogHunter @help = 1;
69+
INSERT #help_results VALUES ('sp_LogHunter', 1);
70+
PRINT 'PASS: sp_LogHunter @help = 1';
71+
END TRY
72+
BEGIN CATCH
73+
INSERT #help_results VALUES ('sp_LogHunter', 0);
74+
PRINT 'FAIL: sp_LogHunter @help = 1 - ' + ERROR_MESSAGE();
75+
END CATCH;
76+
GO
77+
78+
/* sp_PerfCheck */
79+
BEGIN TRY
80+
EXEC dbo.sp_PerfCheck @help = 1;
81+
INSERT #help_results VALUES ('sp_PerfCheck', 1);
82+
PRINT 'PASS: sp_PerfCheck @help = 1';
83+
END TRY
84+
BEGIN CATCH
85+
INSERT #help_results VALUES ('sp_PerfCheck', 0);
86+
PRINT 'FAIL: sp_PerfCheck @help = 1 - ' + ERROR_MESSAGE();
87+
END CATCH;
88+
GO
89+
90+
/* sp_PressureDetector */
91+
BEGIN TRY
92+
EXEC dbo.sp_PressureDetector @help = 1;
93+
INSERT #help_results VALUES ('sp_PressureDetector', 1);
94+
PRINT 'PASS: sp_PressureDetector @help = 1';
95+
END TRY
96+
BEGIN CATCH
97+
INSERT #help_results VALUES ('sp_PressureDetector', 0);
98+
PRINT 'FAIL: sp_PressureDetector @help = 1 - ' + ERROR_MESSAGE();
99+
END CATCH;
100+
GO
101+
102+
/* sp_QueryReproBuilder */
103+
BEGIN TRY
104+
EXEC dbo.sp_QueryReproBuilder @help = 1;
105+
INSERT #help_results VALUES ('sp_QueryReproBuilder', 1);
106+
PRINT 'PASS: sp_QueryReproBuilder @help = 1';
107+
END TRY
108+
BEGIN CATCH
109+
INSERT #help_results VALUES ('sp_QueryReproBuilder', 0);
110+
PRINT 'FAIL: sp_QueryReproBuilder @help = 1 - ' + ERROR_MESSAGE();
111+
END CATCH;
112+
GO
113+
114+
/* sp_QuickieStore */
115+
BEGIN TRY
116+
EXEC dbo.sp_QuickieStore @help = 1;
117+
INSERT #help_results VALUES ('sp_QuickieStore', 1);
118+
PRINT 'PASS: sp_QuickieStore @help = 1';
119+
END TRY
120+
BEGIN CATCH
121+
INSERT #help_results VALUES ('sp_QuickieStore', 0);
122+
PRINT 'FAIL: sp_QuickieStore @help = 1 - ' + ERROR_MESSAGE();
123+
END CATCH;
124+
GO
125+
126+
/* Summary - fail the build if any test failed */
127+
PRINT '';
128+
PRINT '========================================';
129+
130+
DECLARE @failed int = (SELECT COUNT(*) FROM #help_results WHERE passed = 0);
131+
DECLARE @total int = (SELECT COUNT(*) FROM #help_results);
132+
133+
PRINT 'Help output: ' + CONVERT(varchar(10), @total - @failed) + '/' + CONVERT(varchar(10), @total) + ' passed';
134+
135+
IF @failed > 0
136+
RAISERROR('%d procedure(s) failed @help = 1', 16, 1, @failed);
137+
ELSE
138+
PRINT 'All procedures passed';
139+
140+
PRINT '========================================';
141+
142+
DROP TABLE #help_results;
143+
GO

.github/workflows/sql-tests.yml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
name: SQL Tests
2+
3+
on:
4+
push:
5+
branches: [dev]
6+
pull_request:
7+
branches: [dev, main]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
fail-fast: false
14+
matrix:
15+
include:
16+
- version: '2017'
17+
image: mcr.microsoft.com/mssql/server:2017-latest
18+
health_cmd: /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'CI_Test#2026!' -Q 'SELECT 1' -b
19+
- version: '2019'
20+
image: mcr.microsoft.com/mssql/server:2019-latest
21+
health_cmd: /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'CI_Test#2026!' -Q 'SELECT 1' -b
22+
- version: '2022'
23+
image: mcr.microsoft.com/mssql/server:2022-latest
24+
health_cmd: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'CI_Test#2026!' -C -No -Q 'SELECT 1' -b
25+
- version: '2025'
26+
image: mcr.microsoft.com/mssql/server:2025-latest
27+
health_cmd: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'CI_Test#2026!' -C -No -Q 'SELECT 1' -b
28+
29+
name: SQL Server ${{ matrix.version }}
30+
31+
services:
32+
sqlserver:
33+
image: ${{ matrix.image }}
34+
env:
35+
ACCEPT_EULA: Y
36+
MSSQL_SA_PASSWORD: CI_Test#2026!
37+
ports:
38+
- 1433:1433
39+
options: >-
40+
--health-cmd "${{ matrix.health_cmd }}"
41+
--health-interval 10s
42+
--health-timeout 5s
43+
--health-retries 10
44+
45+
steps:
46+
- uses: actions/checkout@v4
47+
48+
- name: Install sqlcmd
49+
run: |
50+
curl -sSL https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc > /dev/null
51+
source /etc/os-release
52+
echo "deb [arch=amd64] https://packages.microsoft.com/ubuntu/${VERSION_ID}/prod ${VERSION_CODENAME} main" | sudo tee /etc/apt/sources.list.d/mssql-release.list
53+
sudo apt-get update
54+
sudo ACCEPT_EULA=Y apt-get install -y mssql-tools18
55+
56+
- name: Create test database
57+
env:
58+
SA_PASSWORD: CI_Test#2026!
59+
run: |
60+
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -C -No -b -Q "CREATE DATABASE DarlingData_CI_Test;"
61+
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -C -No -b -d DarlingData_CI_Test -Q "ALTER DATABASE DarlingData_CI_Test SET QUERY_STORE = ON;"
62+
63+
- name: Regenerate DarlingData.sql from current branch
64+
shell: pwsh
65+
run: |
66+
Push-Location Install-All
67+
./Merge-All.ps1
68+
Pop-Location
69+
70+
- name: Install all procedures
71+
env:
72+
SA_PASSWORD: CI_Test#2026!
73+
run: |
74+
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -C -No -b -d DarlingData_CI_Test -i "Install-All/DarlingData.sql"
75+
76+
- name: Verify procedures exist
77+
env:
78+
SA_PASSWORD: CI_Test#2026!
79+
run: |
80+
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -C -No -b -d DarlingData_CI_Test -Q "
81+
SET NOCOUNT ON;
82+
DECLARE @missing int = 0;
83+
IF OBJECT_ID(N'dbo.sp_HealthParser', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_HealthParser'; END;
84+
IF OBJECT_ID(N'dbo.sp_HumanEvents', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_HumanEvents'; END;
85+
IF OBJECT_ID(N'dbo.sp_HumanEventsBlockViewer', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_HumanEventsBlockViewer'; END;
86+
IF OBJECT_ID(N'dbo.sp_IndexCleanup', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_IndexCleanup'; END;
87+
IF OBJECT_ID(N'dbo.sp_LogHunter', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_LogHunter'; END;
88+
IF OBJECT_ID(N'dbo.sp_PerfCheck', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_PerfCheck'; END;
89+
IF OBJECT_ID(N'dbo.sp_PressureDetector', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_PressureDetector'; END;
90+
IF OBJECT_ID(N'dbo.sp_QueryReproBuilder', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_QueryReproBuilder'; END;
91+
IF OBJECT_ID(N'dbo.sp_QuickieStore', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_QuickieStore'; END;
92+
IF @missing > 0
93+
RAISERROR('Missing %d procedure(s)', 16, 1, @missing);
94+
ELSE
95+
PRINT 'All 9 procedures installed successfully';
96+
"
97+
98+
- name: Test help output
99+
env:
100+
SA_PASSWORD: CI_Test#2026!
101+
run: |
102+
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -C -No -b -d DarlingData_CI_Test -i ".github/sql/test_help_output.sql"
103+
104+
- name: Test basic execution
105+
env:
106+
SA_PASSWORD: CI_Test#2026!
107+
run: |
108+
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -C -No -b -d DarlingData_CI_Test -i ".github/sql/test_basic_execution.sql"

0 commit comments

Comments
 (0)