-
Notifications
You must be signed in to change notification settings - Fork 226
478 lines (391 loc) · 18.9 KB
/
copilot-setup-steps.yml
File metadata and controls
478 lines (391 loc) · 18.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
name: 'Copilot Setup Steps'
# This workflow sets up a complete development environment for the PowerShell module project
# when executed by GitHub Copilot Agent for development assistance.
on:
workflow_dispatch:
pull_request:
paths:
- '.github/workflows/copilot-setup-steps.yml'
push:
paths:
- '.github/workflows/copilot-setup-steps.yml'
# cSpell: ignore unshallow LASTEXITCODE PSDSC noreport dearmor distro keyrings endgroup libmi libc
jobs:
copilot-setup-steps:
name: Setup PowerShell Development Environment
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Set Environment Variables
shell: bash
run: |
echo "Setting MODULE_NAME=$MODULE_NAME to GitHub environment"
echo "MODULE_NAME=$MODULE_NAME" >> "$GITHUB_ENV"
env:
MODULE_NAME: 'SqlServerDsc'
- name: Checkout Repository
uses: actions/checkout@v5
with:
fetch-depth: 0 # Full history needed for GitVersion
# This step is needed for GitVersion because Copilot switches to its working branch
# after checkout and fetches only depth 2.
- name: Ensure full history for GitVersion
shell: pwsh
run: |
Write-Host 'Ensuring full history for GitVersion...'
$isShallow = (& git rev-parse --is-shallow-repository) -eq 'true'
if ($isShallow)
{
Write-Host 'Repository is shallow. Fetching full history and tags...'
git fetch --prune --unshallow --tags --no-recurse-submodules
if ($LASTEXITCODE -ne 0)
{
throw 'git fetch --unshallow failed'
}
}
else
{
Write-Host 'Repository is not shallow. Refreshing tags...'
git fetch --prune --tags --no-recurse-submodules
if ($LASTEXITCODE -ne 0)
{
throw 'git fetch --tags failed'
}
}
Write-Host 'History ready for GitVersion.'
- name: Install Linux Dependencies
shell: bash
run: |
echo "Installing Linux dependencies for PowerShell DSC..."
# Update package list
echo "::group::Update package list"
echo "Updating package list..."
sudo apt-get update
echo "Package list updated successfully"
echo "::endgroup::"
# Ensure gpg is available
sudo apt-get install -y gnupg
# Check if Microsoft repository is already added, if not add it
if ! grep -q "packages.microsoft.com" /etc/apt/sources.list /etc/apt/sources.list.d/* 2>/dev/null; then
echo "::group::Add Microsoft repository"
echo "Adding Microsoft repository..."
# Add Microsoft's GPG key and repository (keyring)
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/keyrings/microsoft.gpg >/dev/null
sudo chmod a+r /etc/apt/keyrings/microsoft.gpg
DISTRO_CODENAME="$(lsb_release -cs)"
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/microsoft-ubuntu-${DISTRO_CODENAME}-prod ${DISTRO_CODENAME} main" | sudo tee "/etc/apt/sources.list.d/microsoft-${DISTRO_CODENAME}-prod.list" >/dev/null
# Update package list again after adding the new repo
echo "Updating package list after adding Microsoft repository..."
if ! sudo apt-get update; then
echo "::warning::apt-get update failed after adding Microsoft repo (repo may be unavailable for this distro). Continuing..."
fi
echo "Microsoft repository added successfully"
echo "::endgroup::"
else
echo "Microsoft repository already configured, skipping..."
fi
# Install OMI (Open Management Infrastructure) which provides libmi
echo "::group::Install OMI and dependencies"
if apt-cache policy omi 2>/dev/null | grep -q 'Candidate:'; then
echo "Installing OMI package..."
# Set a shorter hostname to avoid SSL certificate generation errors
# OMI generates SSL certificates during installation and GitHub Actions runners
# often have very long hostnames that exceed the 64-character limit for CN fields
echo "Setting temporary hostname to avoid SSL certificate generation errors..."
ORIGINAL_HOSTNAME=$(hostname)
# Install trap to always restore hostname on EXIT or ERR
restore_hostname() {
echo "Restoring original hostname..."
sudo hostname "$ORIGINAL_HOSTNAME"
trap - EXIT ERR # Remove the trap after restore
}
trap 'restore_hostname' EXIT ERR
sudo hostname "dsc-runner"
if ! sudo apt-get install -y omi; then
echo "OMI package failed to install; continuing..."
echo "::warning::OMI package failed to install; continuing without OMI"
else
echo "OMI package installed successfully"
fi
# Restore original hostname and remove trap
restore_hostname
else
echo "Package 'omi' not found in repositories; skipping OMI install."
echo "::warning::OMI package not found in repositories, skipping installation"
fi
echo "::endgroup::"
echo "::group::Installing additional development dependencies..."
echo "Installing development dependencies..."
sudo apt-get install -y libc6-dev libssl-dev tree
echo "Development dependencies installed successfully"
echo "::endgroup::"
# Set LD_LIBRARY_PATH permanently for the runner session
echo "Setting LD_LIBRARY_PATH environment variable..."
echo "LD_LIBRARY_PATH=/opt/omi/lib:/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}" >> "$GITHUB_ENV"
echo "Environment variable set successfully"
echo "Linux dependencies installed successfully"
- name: Setup Docker
shell: bash
run: |
echo "Setting up Docker for SQL Server Linux containers..."
echo "::group::Setup Docker"
echo "Verifying Docker installation..."
if ! command -v docker &> /dev/null; then
echo "Docker not found, installing..."
sudo apt-get update
sudo apt-get install -y docker.io
fi
# Start Docker service if not running
if ! sudo systemctl is-active --quiet docker; then
echo "Starting Docker service..."
sudo systemctl start docker
sudo systemctl enable docker
fi
# Add current user to docker group for permissions
sudo usermod -aG docker $USER
# Verify Docker is working
docker --version
sudo docker run --rm hello-world
echo "Docker setup completed successfully"
echo "::endgroup::"
- name: Setup SQL Server on Linux Container
shell: bash
run: |
echo "Setting up SQL Server Linux container..."
# Set SQL Server environment variables
SQLSERVER_SA_PASSWORD="MyStr0ng!Passw0rd123"
SQLSERVER_CONTAINER_NAME="sqlserver-linux-ci"
SQLSERVER_PORT="1433"
echo "::group::Pull SQL Server Linux container image"
echo "Pulling SQL Server 2022 Linux container image..."
sudo docker pull mcr.microsoft.com/mssql/server:2022-latest
echo "Container image pulled successfully"
echo "::endgroup::"
echo "::group::Run SQL Server Linux container"
echo "Starting SQL Server Linux container..."
# Create volume for SQL Server data persistence
sudo docker volume create sqlserver-data
# Run SQL Server container with proper configuration
sudo docker run -e 'ACCEPT_EULA=Y' \
-e "MSSQL_SA_PASSWORD=${SQLSERVER_SA_PASSWORD}" \
-e 'MSSQL_PID=Developer' \
-p "${SQLSERVER_PORT}:1433" \
--name "${SQLSERVER_CONTAINER_NAME}" \
--hostname sqlserver-linux \
-v sqlserver-data:/var/opt/mssql \
-d mcr.microsoft.com/mssql/server:2022-latest
echo "Waiting for SQL Server container to start..."
sleep 30
# Check if container is running
if sudo docker ps | grep -q "${SQLSERVER_CONTAINER_NAME}"; then
echo "SQL Server Linux container started successfully"
# Display container information
echo "Container status:"
sudo docker ps --filter "name=${SQLSERVER_CONTAINER_NAME}" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# Check SQL Server logs for startup confirmation
echo "Checking SQL Server startup logs..."
sudo docker logs "${SQLSERVER_CONTAINER_NAME}" 2>&1 | tail -10
# Set environment variables for later steps
echo "SQLSERVER_SA_PASSWORD=${SQLSERVER_SA_PASSWORD}" >> "$GITHUB_ENV"
echo "SQLSERVER_CONTAINER_NAME=${SQLSERVER_CONTAINER_NAME}" >> "$GITHUB_ENV"
echo "SQLSERVER_PORT=${SQLSERVER_PORT}" >> "$GITHUB_ENV"
echo "SQLSERVER_CONNECTION_STRING=Server=localhost,${SQLSERVER_PORT};User Id=sa;Password=${SQLSERVER_SA_PASSWORD};TrustServerCertificate=true" >> "$GITHUB_ENV"
else
echo "::error::Failed to start SQL Server Linux container"
sudo docker logs "${SQLSERVER_CONTAINER_NAME}" || true
exit 1
fi
echo "::endgroup::"
- name: Install SQL Server Command Line Tools
shell: bash
run: |
echo "Installing SQL Server command line tools (sqlcmd)..."
echo "::group::Install mssql-tools"
# Install the Microsoft SQL Server command-line tools
if ! grep -q "packages.microsoft.com" /etc/apt/sources.list /etc/apt/sources.list.d/* 2>/dev/null; then
echo "Microsoft repository not found, adding it..."
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/keyrings/microsoft.gpg >/dev/null
sudo chmod a+r /etc/apt/keyrings/microsoft.gpg
DISTRO_CODENAME="$(lsb_release -cs)"
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/microsoft-ubuntu-${DISTRO_CODENAME}-prod ${DISTRO_CODENAME} main" | sudo tee "/etc/apt/sources.list.d/microsoft-${DISTRO_CODENAME}-prod.list" >/dev/null
sudo apt-get update
fi
# Accept EULA for mssql-tools (required for non-interactive installation)
echo 'mssql-tools accept-eula/accept-eula-license boolean true' | sudo debconf-set-selections
# Install mssql-tools18 (latest version with enhanced security)
if sudo apt-get install -y mssql-tools18; then
echo "mssql-tools18 installed successfully"
# Add sqlcmd to PATH for current session
export PATH="$PATH:/opt/mssql-tools18/bin"
echo "/opt/mssql-tools18/bin" | sudo tee -a /etc/environment
echo "PATH=$PATH:/opt/mssql-tools18/bin" >> "$GITHUB_ENV"
else
echo "::warning::mssql-tools18 installation failed, trying mssql-tools"
# Fallback to older version if needed
sudo apt-get install -y mssql-tools
export PATH="$PATH:/opt/mssql-tools/bin"
echo "/opt/mssql-tools/bin" | sudo tee -a /etc/environment
echo "PATH=$PATH:/opt/mssql-tools/bin" >> "$GITHUB_ENV"
fi
# Verify sqlcmd installation
which sqlcmd || echo "::warning::sqlcmd not found in PATH"
echo "::endgroup::"
- name: Verify SQL Server Linux Container Connection
shell: bash
run: |
echo "Testing connection to SQL Server Linux container..."
echo "::group::Test SQL Server connection"
# Wait a bit more for SQL Server to be fully ready
echo "Waiting for SQL Server to be fully ready..."
sleep 15
# Test connection using sqlcmd with retry logic
max_retries=5
retry_count=0
while [ $retry_count -lt $max_retries ]; do
echo "Connection attempt $((retry_count + 1)) of $max_retries..."
if sqlcmd -S localhost,"$SQLSERVER_PORT" -U sa -P "$SQLSERVER_SA_PASSWORD" -C -Q "SELECT @@VERSION, @@SERVERNAME, GETDATE() AS CurrentDateTime;" -o /tmp/sqltest.out; then
echo "✅ Successfully connected to SQL Server Linux container!"
echo "Query results:"
cat /tmp/sqltest.out
break
else
echo "❌ Connection attempt failed"
retry_count=$((retry_count + 1))
if [ $retry_count -lt $max_retries ]; then
echo "Retrying in 10 seconds..."
sleep 10
fi
fi
done
if [ $retry_count -eq $max_retries ]; then
echo "::error::Failed to connect to SQL Server after $max_retries attempts"
echo "Container logs:"
sudo docker logs "$SQLSERVER_CONTAINER_NAME" | tail -20
exit 1
fi
# Test creating a simple database
echo "Testing database creation..."
if sqlcmd -S localhost,"$SQLSERVER_PORT" -U sa -P "$SQLSERVER_SA_PASSWORD" -C -Q "CREATE DATABASE TestDB; SELECT name FROM sys.databases WHERE name = 'TestDB';" -o /tmp/dbtest.out; then
echo "✅ Successfully created test database!"
cat /tmp/dbtest.out
else
echo "::warning::Failed to create test database"
fi
# Display container resource usage
echo "Container resource usage:"
sudo docker stats "$SQLSERVER_CONTAINER_NAME" --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}"
echo "::endgroup::"
echo "✅ SQL Server Linux container setup completed successfully!"
echo "Connection details:"
echo " Server: localhost,$SQLSERVER_PORT"
echo " User: sa"
echo " Connection String: $SQLSERVER_CONNECTION_STRING"
- name: Configure PowerShell Environment
shell: pwsh
run: |
Write-Host "Configure PowerShell environment..."
# Install dependent PowerShell modules
Write-Host "Installing SqlServer module..."
Install-PSResource -Name 'SqlServer' -Version '21.1.18256' -Scope 'CurrentUser' -Repository 'PSGallery' -TrustRepository
Write-Host "SqlServer module installed successfully"
Write-Host "Installing PSDSC module..."
Install-PSResource -Name 'PSDSC' -Scope 'CurrentUser' -Repository 'PSGallery' -TrustRepository
Write-Host "PSDSC module installed successfully"
Write-Host "PowerShell environment configuration complete"
- name: Install DSCv3
shell: pwsh
run: |
Write-Host "Install DSCv3 in environment..."
# Install dependent PowerShell modules
Write-Host "Installing DSCv3 executable..."
Install-DscExe -IncludePrerelease -Force
Write-Host "DSCv3 installed successfully"
Write-Host "DSCv3 install complete"
- name: Verify DSCv3
shell: pwsh
run: |
Write-Host "Running DSCv3 to validate correct operation..."
dsc --version
- name: Install .NET Tools
shell: pwsh
run: |
Write-Host 'Installing/Updating .NET tools...'
# Install GitVersion for semantic versioning (idempotent)
dotnet tool update --global GitVersion.Tool --version 5.* `
|| dotnet tool install --global GitVersion.Tool --version 5.*
# Verify installation
dotnet-gitversion /version
Write-Host '.NET tools ready.'
- name: Verify GitVersion
shell: pwsh
run: |
Write-Host 'Running GitVersion to determine semantic version (parsing to PowerShell object)...'
dotnet-gitversion | ConvertFrom-Json
- name: Resolve Dependencies
shell: pwsh
run: |
Write-Host 'Resolving project dependencies...'
# Run dependency resolution
./build.ps1 -ResolveDependency -Tasks 'noop' -UseModuleFast -ErrorAction Stop
Write-Host 'Dependencies resolved successfully.'
- name: Build Module
shell: pwsh
run: |
Write-Host "Building $env:MODULE_NAME module..."
# Build the module
./build.ps1 -Tasks 'build' -ErrorAction Stop
# Verify build output
$builtPath = "output/builtModule/$env:MODULE_NAME"
if (Test-Path -Path $builtPath)
{
Write-Host "Module built successfully at: $builtPath"
# Show files with paths relative to the built module base path using `tree` (run directly in PowerShell)
$base = (Resolve-Path -Path $builtPath).ProviderPath
Write-Host "Files under $base (relative paths):"
# Run tree directly and strip leading './' from its output
tree --noreport $builtPath
}
else
{
Write-Error 'Module build failed - output directory not found'
exit 1
}
- name: Import Built Module
shell: pwsh
run: |
Write-Host "Importing built $env:MODULE_NAME module..."
./build.ps1 -Tasks 'noop'
Import-Module -Name $env:MODULE_NAME -Force
# Verify module is loaded
$module = Get-Module -Name $env:MODULE_NAME -ErrorAction SilentlyContinue
if ($module)
{
Write-Host 'Module imported successfully:'
Write-Host " Name: $($module.Name)"
Write-Host " Version: $($module.Version)"
Write-Host " Path: $($module.Path)"
# Show available commands
$commands = @(Get-Command -Module $env:MODULE_NAME)
if ($commands.Count -gt 0)
{
Write-Host " Exported Commands: $($commands.Count)"
Write-Host "`nAvailable Commands:"
$commands |
Select-Object Name, ModuleName | Format-Table -AutoSize
}
else
{
Write-Host 'No commands exported by the module.'
}
$dscResources = @(dsc resource list --adapter Microsoft.DSC/PowerShell --output-format json | ConvertFrom-Json)
Write-Host "`n Available class-based DSC Resources: $($dscResources.Count)`n"
$dscResources | Format-Table type, capabilities, implementedAs, requireAdapter -GroupBy kind -AutoSize
}
else
{
Write-Error 'Failed to import module'
exit 1
}