Skip to content

Commit 3677cd4

Browse files
Merge pull request #665 from erikdarlingdata/feature/ci-pipelines
Add CI pipeline for multi-version SQL Server testing
2 parents 4747a47 + 4d0b3e9 commit 3677cd4

3 files changed

Lines changed: 350 additions & 0 deletions

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
CI Test: Run default execution for procedures that are safe to execute without special setup.
3+
Procs requiring extended events, special data, or host features not available in Docker
4+
(sp_HumanEvents, sp_HumanEventsBlockViewer, sp_QueryReproBuilder, sp_PerfCheck)
5+
are tested with @help = 1 only (see test_help_output.sql).
6+
sp_PerfCheck reads the default trace which does not exist in Docker containers.
7+
Uses a temp table to track results across GO batches.
8+
*/
9+
10+
SET NOCOUNT ON;
11+
12+
CREATE TABLE #exec_results (proc_name VARCHAR(100) NOT NULL, passed BIT NOT NULL);
13+
GO
14+
15+
PRINT '========================================';
16+
PRINT 'Testing default execution';
17+
PRINT '========================================';
18+
PRINT '';
19+
GO
20+
21+
/* sp_PressureDetector - detects CPU and memory pressure */
22+
BEGIN TRY
23+
EXEC dbo.sp_PressureDetector;
24+
INSERT #exec_results VALUES ('sp_PressureDetector', 1);
25+
PRINT 'PASS: sp_PressureDetector (default)';
26+
END TRY
27+
BEGIN CATCH
28+
INSERT #exec_results VALUES ('sp_PressureDetector', 0);
29+
PRINT 'FAIL: sp_PressureDetector - ' + ERROR_MESSAGE();
30+
END CATCH;
31+
GO
32+
33+
/* sp_HealthParser - analyzes system health extended event */
34+
BEGIN TRY
35+
EXEC dbo.sp_HealthParser;
36+
INSERT #exec_results VALUES ('sp_HealthParser', 1);
37+
PRINT 'PASS: sp_HealthParser (default)';
38+
END TRY
39+
BEGIN CATCH
40+
INSERT #exec_results VALUES ('sp_HealthParser', 0);
41+
PRINT 'FAIL: sp_HealthParser - ' + ERROR_MESSAGE();
42+
END CATCH;
43+
GO
44+
45+
/* sp_LogHunter - searches error logs */
46+
BEGIN TRY
47+
EXEC dbo.sp_LogHunter;
48+
INSERT #exec_results VALUES ('sp_LogHunter', 1);
49+
PRINT 'PASS: sp_LogHunter (default)';
50+
END TRY
51+
BEGIN CATCH
52+
INSERT #exec_results VALUES ('sp_LogHunter', 0);
53+
PRINT 'FAIL: sp_LogHunter - ' + ERROR_MESSAGE();
54+
END CATCH;
55+
GO
56+
57+
/* sp_IndexCleanup - identifies unused/duplicate indexes */
58+
BEGIN TRY
59+
EXEC dbo.sp_IndexCleanup
60+
@database_name = N'DarlingData_CI_Test';
61+
INSERT #exec_results VALUES ('sp_IndexCleanup', 1);
62+
PRINT 'PASS: sp_IndexCleanup (default)';
63+
END TRY
64+
BEGIN CATCH
65+
INSERT #exec_results VALUES ('sp_IndexCleanup', 0);
66+
PRINT 'FAIL: sp_IndexCleanup - ' + ERROR_MESSAGE();
67+
END CATCH;
68+
GO
69+
70+
/* sp_QuickieStore - navigates Query Store data */
71+
BEGIN TRY
72+
EXEC dbo.sp_QuickieStore
73+
@database_name = N'DarlingData_CI_Test';
74+
INSERT #exec_results VALUES ('sp_QuickieStore', 1);
75+
PRINT 'PASS: sp_QuickieStore (default)';
76+
END TRY
77+
BEGIN CATCH
78+
INSERT #exec_results VALUES ('sp_QuickieStore', 0);
79+
PRINT 'FAIL: sp_QuickieStore - ' + ERROR_MESSAGE();
80+
END CATCH;
81+
GO
82+
83+
/* Summary - fail the build if any test failed */
84+
PRINT '';
85+
PRINT '========================================';
86+
87+
DECLARE @failed int = (SELECT COUNT(*) FROM #exec_results WHERE passed = 0);
88+
DECLARE @total int = (SELECT COUNT(*) FROM #exec_results);
89+
90+
PRINT 'Basic execution: ' + CONVERT(varchar(10), @total - @failed) + '/' + CONVERT(varchar(10), @total) + ' passed';
91+
92+
IF @failed > 0
93+
RAISERROR('%d procedure(s) failed default execution', 16, 1, @failed);
94+
ELSE
95+
PRINT 'All procedures passed';
96+
97+
PRINT '========================================';
98+
99+
DROP TABLE #exec_results;
100+
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: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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+
- version: '2019'
19+
image: mcr.microsoft.com/mssql/server:2019-latest
20+
- version: '2022'
21+
image: mcr.microsoft.com/mssql/server:2022-latest
22+
- version: '2025'
23+
image: mcr.microsoft.com/mssql/server:2025-latest
24+
25+
name: SQL Server ${{ matrix.version }}
26+
27+
services:
28+
sqlserver:
29+
image: ${{ matrix.image }}
30+
env:
31+
ACCEPT_EULA: Y
32+
MSSQL_SA_PASSWORD: CI_Test#2026!
33+
ports:
34+
- 1433:1433
35+
options: >-
36+
--health-cmd "grep -q 'SQL Server is now ready for client connections' /var/opt/mssql/log/errorlog || exit 1"
37+
--health-interval 10s
38+
--health-timeout 5s
39+
--health-retries 15
40+
41+
steps:
42+
- uses: actions/checkout@v4
43+
44+
- name: Install sqlcmd
45+
run: |
46+
# Ubuntu 24.04 runners have Microsoft repo pre-configured; avoid Signed-By conflicts
47+
if ! grep -rql 'packages.microsoft.com' /etc/apt/sources.list.d/ 2>/dev/null; then
48+
curl -sSL https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
49+
source /etc/os-release
50+
echo "deb [arch=amd64,signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/ubuntu/${VERSION_ID}/prod ${VERSION_CODENAME} main" | sudo tee /etc/apt/sources.list.d/mssql-release.list
51+
fi
52+
sudo apt-get update
53+
sudo ACCEPT_EULA=Y apt-get install -y mssql-tools18
54+
55+
- name: Create test database
56+
env:
57+
SA_PASSWORD: CI_Test#2026!
58+
run: |
59+
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -C -No -b -Q "CREATE DATABASE DarlingData_CI_Test;"
60+
/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;"
61+
62+
- name: Regenerate DarlingData.sql from current branch
63+
shell: pwsh
64+
run: |
65+
Push-Location Install-All
66+
./Merge-All.ps1
67+
Pop-Location
68+
69+
- name: Install all procedures
70+
env:
71+
SA_PASSWORD: CI_Test#2026!
72+
run: |
73+
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -C -No -b -d DarlingData_CI_Test -i "Install-All/DarlingData.sql"
74+
75+
- name: Verify procedures exist
76+
env:
77+
SA_PASSWORD: CI_Test#2026!
78+
run: |
79+
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -C -No -b -d DarlingData_CI_Test -Q "
80+
SET NOCOUNT ON;
81+
DECLARE @missing int = 0;
82+
IF OBJECT_ID(N'dbo.sp_HealthParser', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_HealthParser'; END;
83+
IF OBJECT_ID(N'dbo.sp_HumanEvents', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_HumanEvents'; END;
84+
IF OBJECT_ID(N'dbo.sp_HumanEventsBlockViewer', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_HumanEventsBlockViewer'; END;
85+
IF OBJECT_ID(N'dbo.sp_IndexCleanup', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_IndexCleanup'; END;
86+
IF OBJECT_ID(N'dbo.sp_LogHunter', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_LogHunter'; END;
87+
IF OBJECT_ID(N'dbo.sp_PerfCheck', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_PerfCheck'; END;
88+
IF OBJECT_ID(N'dbo.sp_PressureDetector', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_PressureDetector'; END;
89+
IF OBJECT_ID(N'dbo.sp_QueryReproBuilder', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_QueryReproBuilder'; END;
90+
IF OBJECT_ID(N'dbo.sp_QuickieStore', N'P') IS NULL BEGIN SET @missing += 1; PRINT 'MISSING: sp_QuickieStore'; END;
91+
IF @missing > 0
92+
RAISERROR('Missing %d procedure(s)', 16, 1, @missing);
93+
ELSE
94+
PRINT 'All 9 procedures installed successfully';
95+
"
96+
97+
- name: Test help output
98+
env:
99+
SA_PASSWORD: CI_Test#2026!
100+
run: |
101+
/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"
102+
103+
- name: Test basic execution
104+
env:
105+
SA_PASSWORD: CI_Test#2026!
106+
run: |
107+
/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)